آموزش پایتون

آموزش ساخت فرم Login و Logout در جنگو

مراحل ایجاد فرم Login در اپلیکیشن جنگو:

  1. ایجاد یک اپ جدید به نام account یا accounts به منظور پیاده سازی Login و Sign up و Logout
  2. معرفی اپ جدید به فایل settings.py
  3. اضافه کردن آدرس accounts در فایل urls.py پروژه اصلی
  4. اضافه کردن آدرس های Login و Sign up و Logout در فایل urls.py اپ account
  5. نوشتن متد برای پاسخگویی به request های وارد شده به آدرس های Login, Sign up, Logout در فایل views.py اپ account (متناظر با مسیرهایی که در مرحله قبل ایجاد کردیم)
  6. ایجاد فولدر templates در اپ account
  7. ساخت صفحه Login.html در فولدر مرحله قبل
  8. ساخت فرم الکترونیکی در صفحه فوق
  9. ایجاد متد دریافت و پردازش فرم در فایل views.py اپ account
  10. ساخت فرم Logout به صورت تک دکمه ای در فایل base.html
  11. تکمیل متد Logout در فایل views.py
  12. مدیریت نمایش Login و Signup به کاربر غیرلاگین و نمایش نام کاربری و Logout به کاربر لاگین

۱- ایجاد یک اپ جدید به نام account

در حالی که venv فعال است و داخل فولدر اصلی اپلیکیشن هستید،‌دستور زیر را برای ایجاد اپ جدید در ترمینال وارد کنید.

python manage.py startapp accounts

فرایند ثبت نام،لاگین و لاگ اوت کاربر در این اپ پیاده سازی خواهد شد.

۲-معرفی اپ جدید به فایل settings.py

ابتدا فایل apps.py اپ account رو باز کنید تا نام کلاس اصلی این اپلیکیشن رو پیدا کنید.

class AccountConfig(AppConfig):
    name = 'account'

فایل settings.py اپلیکیشن اصلی رو باز کنید و در قسمت installed apps، اپ جدید رو با نوشتن نام کلاس اصلی اون فرمتی که در زیر می بینید، معرفی کنید:‌

INSTALLED_APPS = [
    'account.apps.AccountConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

۳-اضافه کردن آدرس accounts در فایل urls.py پروژه اصلی

در اینجا میخوایم کاری کنیم که تمام رکوئست هایی که بعد از آدرس accounts در url وارد میشن به فایل urls.py اپ account سپرده بشن و تکلیفشون اونجا مشخص بشه.

برای این کار نیاز به استفاده از include داریم. اگر ایمپورت نشده باید ایمپورتش کنید.

و بعد یک path جدید تعریف می کنیم:

۵from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/',include('account.urls') , name='accounts'),

]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

۴-اضافه کردن آدرس های Login و Sign up و Logout در فایل urls.py اپ account

در فایل urls.py در اپ account،(معمولا این فایل در اپ شما وجود ندارد، آن را خودتان ایجاد کنید) سایر مسیرهای فرعی account را تعریف می کنیم. در حقیقت تعیین می کنیم که کدام متد (از متد های فایل views.py) مسئولیت تعیین تکلیف کدام مسیر ها را داشته باشند.

from django.urls import path
from . import views


urlpatterns = [
    path('', views.home, name='accounts' ),
    path('login/', views.login, name = 'login'),
    path('logout/', views.logout, name = 'logout'),
    path('signup/', views.signup, name='signup')
    ]

دقت کنید که در انتهای هر خط تعریف path، یک name هم به آن اختصاص داده ایم. از این نام خیلی جاها استفاده می شود. یکی از استفاده های این name در صفحات html پروژه است.

در صفحات html پروژه می توانیم آدرس هر کدام از این path ها را با صدازدن نام انها بعد از دستور url، صدا بزنیم.

مثلا اگر در صفحه base.html بخواهیم لینک صفحه login را قرار بدهیم، این کار را با استفاده از name ی که در فایل urls.py تعریف کرده ایم و به صورت زیر انجام می دهیم‌:

<a href = "{% url 'login' %}"> Login </a>

۵- نوشتن متد برای پاسخگویی به request های وارد شده به آدرس های Login, Sign up, Logout در فایل views.py اپ account (متناظر با مسیرهایی که در مرحله قبل ایجاد کردیم)

در فایل views.py که در اپ account قرار دارد (اگر ندارد خودتان بسازیدش)، به ازای هر مسیر، یک فانکشن ایجاد کنید (همنام با همان متدی که در صفحه urls.py به آن اشاره کرده اید).

def login(request):
     return render(request, 'account/login.html')

این متد در پاسخ به رکوئست، صفحه login.html را رندر کرده و در مرورگر نمایش می دهد.

البته در پاسخ به تکمیل فرم ثبت نام هم این متد باید کاری انجام بدهد که در ادامه آموزش، به آن خواهیم رسید.

درصورت نیاز، برای هر کدام از مسیر های Sign in و Logout هم یک فانکشن مجزا تعریف می کنیم.

(اینها را هم در آموزشهای مربوط به خودشان کامل توضیح داده ام)

۶ و ۷ ایجاد فولدر templates در اپ account و ساخت صفحه Signup.html در آن

در اپ account یک فولدر به اسم templates ایجاد کنید. داخل اینف فولدر یک فایل جدید با نام login.html ایجاد کنید. در نامگذاری این فایل دقت کنید چون باید دقیقا همان نمی باشد که در مرحله قبل در متد login وارد کرده ایم.

۸- ساخت فرم الکترونیکی در صفحه login.html

یک فرم الکترونیکی در این صفحه میسازیم.

متد ارسال آن را بر روی POST می گذاریم.

آدرس اکشن آن را هم روی login می گذاریم. که name که در path در urls.py تعریف کرده بودیم را صدا میزند.

   <form method="post" action="{% url 'login' %}">
    {% csrf_token %}
    Username:
    <br>
    <input type="text" name="username" class="form-control"/>
    Password:
    <br>
    <input type="password" name="password" class="form-control"/>
    <br>
    <input class="btn btn-primary" type="submit" value="Login" class="form-control"/>
   </form>

نکته بسیار مهم:‌در فرم های جنگو حتما میبایست {% csrf_token %} رو داخل فرم درج کنید. وگرنه موقع ارسال فرم، خطا بر می گردونه.

۹-ایجاد متد دریافت و پردازش فرم در فایل views.py اپ account

def login(request):
    # اگر رکوئست با متد POST ارسال شده بود یعنی کاربر فرم لاگین را سابمیت کرده است
    if request.method == 'POST':
        # از متد user.authemticate برای یافتن کاربر استفاده میشود. این متد یه متغیر از نوع آبجکت user بر می گرداند
        user = auth.authenticate(username=request.POST['username'], password=request.POST['password'])
        # چک می کند که اگر متغیر یوزر خالی نبود، لاگین را با اطلاعات یوزر انجام دهد
        if user is not None:
            auth.login(request, user)
            # در اینجا کاربر را به صفحه ای که میخواهیم پس از لاگین به وی نمایش دهیم ریدایرکت می کنیم
            return redirect('allproducts')
        # در صورتی که متغیر یوزر خالی بود
        # یعنی کاربر با مشخصاتی که در فرم وارد شده است وجود ندارد
        else:
            # کاربر را به همراه یک پیام خطا به صفحه لاگین باز می گرداند
            # این پیغام خطا در قسمت تعبیه شده در بالای صفحه لاگین به نمایش در می آید
            return render(request, 'account/login.html', {'error':'Invalid Username Or Password'})
    # اگر رکوئست با متد GET ارسال شده بود یعنی کاربر لینک صفحه لاگین را زده و میخواهد صفحه لاگین را ببیند
    else:
        return render(request, 'account/login.html')

در این متد، با استفاده از دستور if چک کرده ایم که آیا درخواست به این آدرس به صورت POST ارسال شده یا خیر (که یعنی به صورت GET ارسال شده).

خب در چه صورتی درخواست به یک صفحه به صورت GET ارسال میشه؟‌ در صورتی که آدرس صفحه در مرورگر فراخوانی بشه.

و اگر یادتون باشه ما فرممون رو به صورت POST ارسال کردیم.

پس در صورتی که متد درخواست دریافتی، از نوع POST باشه به این معناست که این درخواست، ارسال فرم به صفحه بوده.

اما در صورتی که متد درخواست دریافتی از نوع GET باشه به این معناست که کاربر لینک صفحه login رو زده و میخواد صفحه login رو ببینه (هنوز فرم رو سابمیت نکرده)

ما بهش گفتیم در صورتی که متد درخواست از نوع POST بود،‌پردازش روی دیتای ارسالی فرم رو انجام بده، و درصورتی که درخواست از نوع GET بود،‌ صفحه login.html رو رندر کن و به کاربر نمایش بده.

سایز توضیحات مربوط به پیاده سازی این متد رو در کامنت های کد براتون نوشتم.

فقط دقت کنید برای کار با یوزرها و authentication باید این متدها رو در فایل جاری (views.py) ایمپورت کنید:

from django.contrib.auth.models import User
from django.contrib import auth

۱۰- ساخت فرم Logout به صورت تک دکمه ای در فایل base.html

معمولا دکمه های مربوط به Login و SignUp و Logout در قسمت هدر یا فوترسایت، و در تمامی صغحات سایت نمایش داده میشوند.

به همین دلیل ما باید این دکمه ها رو در صفحه base.html ایجاد کنیم (که همه جا دیده بشن)

دکمه Logout به ظاهر یه دکمه و یا یک لینک هستش که وقتی کاربر روش کلیک می کنه،‌لاگ اوت میشه. اما ما اون رو با استفاده از فرم پیاده سازی می کنیم.

چرا Logout باید به صورت فرم پیاده سازی بشه؟

بسیاری از مرورگرهای نوین (مثل گوگل کروم و سافاری) لینک های داخل صفحه رو با هدف افزایش سرعت، پیش پردازش می کنن. یعنی یکبار تمام لینک های صفحه رو مرور می کنن و در پس زمینه اجراشون می کنن.

اگر ما Logout رو به صورت یک دکمه یا لینک طراحی کنیم (و میدونیم که لینک ها صفحه مقصد رو با متد GET فراخوانی می کنن)، لینک Logout ما جزو لینک های پیش پردازش شده ی مرورگر قرار می گیره.

یعنی قبل از اینکه کسی روی لینک کلیک کنه، یکبار در پس زمینه و توسط مرورگر اجرا میشه. و کاربر همون لحظه Logout میشه!

یعنی پیاده سازی دکمه Logout به صورت لینک ساده، باعث میشه بدون اینکه کاربر روی Logout کلیک کنه، لاگ اوت بشه!

برا جلوگیری از این کار، ما لاگ اوت رو به صورت یک فرم الکترونیکی طراحی می کنیم و متد ارسالش رو هم متد POST قرار میدیم. اینجوری دیگه مرورگر نمیتونه اون کار رو انجام بده.

پیاده سازی فرم Logout

دقیقا در جایی از صفحه base.html (معمولا این صفحه رو در فولدر templates اپ اصلی پروژه میسازیم) که میخواهید لینک Logout به کاربر نمایش داده بشه،‌ بجای درج تگ a، یک فرم ایجاد کنید.

متد فرم رو روی POST بذارید و اکشن اون رو روی logout بذارید. این کار باعث میشه درخواست به متد logout در فایل views.py ارسال بشه (و البته با متد POST)

<form method="POST" action="{% url 'logout' %}" id="logout">
	<!--
	در این قسمت برای ارسال فرم ها به جنگو باین سی اس آر اف توکن را داخل فرم بنویسیم
	در غیر اینصورت جنگو فرم ارسالی را از ما نمی پذیرد
	-->
	{% csrf_token %}
	<input type="submit" value="logout" class="btn btn-light">
</form>

۱۱- تکمیل متد Logout در فایل views.py

ما در مرحله قبل، درخواست خودمون رو از سمت کلاینت به سرور فرستادیم. در این مرحله باید این درخواست رو در سمت سرور پردازش کنیم.

اگر ایجاد مسیر در urls.py رو درست انجام داده باشین، رکوئست logout باید به فایل views.py برسه و دنبال متد logout بگرده. پس معطلش نکنید و متد logout رو پیاده سازی کنید!

def logout(request):
    if request.method == 'POST':
        auth.logout(request)
        return redirect('home')

ما از متد auth.logout جنگو برای این کار استفاده کردیم. و در آخر هم کاربر را بعد از لاگ اوت به صفحه اصلی منتقل کردیم.

۱۲-مدیریت نمایش Login و Signup به کاربر غیرلاگین و نمایش نام کاربری و Logout به کاربر لاگین

برای تعیین محتوای نمایش داده شده به کاربر لاگین و غیر لاگین از بلوک if به صورت زیر استفاده می کنیم:

{% if user.is_authenticated %}
# دیتایی که کاربر لاگین می تواند ببیند
{% else %}
# دیتایی که کاربر غیرلاگین می تواند ببیند
{% endif %}

تگ های html مورد نظرمان را در بلوک if با فرمت بالا می نویسیم.

حامد عسکریان

برنامه نویس و عاشق تکنولوژی

دیدگاهتان را بنویسید

همچنین ببینید

بستن
دکمه بازگشت به بالا
بستن
بستن