احراز هویت کاربر در جنگو 1/3
در این پست میخوام عملکرد login, logout با سیستم احراز هویت از پیش ساخته شده جنگو را آموزش بدم.در این آموزش فرض شده که شما توانایی پیکربندی و ساخت یک پروژه جدید جنگو را دارید.
سورس کد کامل این پروژه در گیت هاب قرار داده شده.
پیکربندی
محلی را برای شروع پروژه انتخاب کنید.میتونید هرجا که مایلید در کامپیوتر خودتون کدهاتون رو قرار بدید.میتونید تمام دستورات زیر را از طریق خط فرمان وارد کنید:
- ساخت پوشه accounts در دسکتاپ
- نصب جنگو با pipenv
- فعال کردن محیط مجازی
- ساخت پروژه جدید جنگو به اسم config
- ساخت دیتابیس sqlite با کامند migrate
- فعال کردن سرور محلی
1234567$ cd ~/Desktop $ mkdir accounts && cd accounts $ python3 -m venv env $ source env/bin/activate (accounts) $ django-admin.py startproject config . (accounts) $ python manage.py migrate (accounts) $ python manage.py runserver
توجه : در اینجا من با استفاده از venv محیط مجازی رو ساختم اما شما میتوانید با هر ابزارهای دیگه ای مثل virtualenv یا pipenv استفاده کنید.
حالا اگر به آدرس http://127.0.0.1:8000 در مرورگر خودتون وارد بشید باید این تصویر رو مشاهده کنید.
احراز هویت در جنگو
جنگو به صورت اتوماتیک اپ auth را که مسئول احراز هویت در جنگو است را هنگامی که پروژه جدیدی ساخته میشود نصب میکند.
در مسیر config/settings.py به اپ های نصب شده در لیست INSTALLED_APPS نگاه کنید میتونید auth رو مشاهده کنید.
123456789# config/settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
برای استفاده از اپ auth ما نیاز داریم اون رو به فایل urls.py اصلی اضافه کنید.
در ابتدای فایل از ماژول django.urls کتابخونه include را اضافه کنید من اسم آدرس URL رو /accounts انتخاب کردم که نام پیشفرض هستش اما شما میتونید هر اسمی برای ادرستون انتخاب کنید.
12345678# config/urls.py from django.contrib import admin from django.urls import path, include # new urlpatterns = [ path('admin/', admin.site.urls), path('accounts/', include('django.contrib.auth.urls')), # new ]
اپ auth شامل چندین view و url برای login, logout و password management میشه.
یو آر ال های auth شامل :
12345678accounts/login/ [name='login'] accounts/logout/ [name='logout'] accounts/password_change/ [name='password_change'] accounts/password_change/done/ [name='password_change_done'] accounts/password_reset/ [name='password_reset'] accounts/password_reset/done/ [name='password_reset_done'] accounts/reset/<uidb64>/<token>/ [name='password_reset_confirm'] accounts/reset/done/ [name='password_reset_complete']
برای هر view یک url هم وجود دارد تنها کار باقی مانده ساخت template برای استفاده هر کدام است.
ساخت قالب Login
خب بریم که صفحه لاگین رو بسازیم!جنگو به صورت پیشفرض به دنبال پوشه registration برای پیدا کردن قالب های ویوهای auth میگرده. نام قالب login.html است.
در خط فرمان Control-c را وارد کنید تا سرور قطع شود.پوشه جدیدی به اسم registration بسازید . در داخل آن هم فایل login.html را بسازید.
123(accounts) $ mkdir templates (accounts) $ mkdir templates/registration (accounts) $ touch templates/registration/login.html
توجه: مطمئن باشید پوشه templates در مسیر اصلی پروژه ساخته شده باشد.شما میتونید کدهای های اصلی پروژه رو در اینجا ببیند و به ساختارفایل ها دقت کنید.
کدهای زیر را در فایل login.html وارد کنید.
1234567<!-- templates/registration/login.html --> <h2>Log In</h2> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">Log In</button> </form>
این حالت استاندارد فرم در جنگو هستش از متد POST برای ارسال داده ها استفاده شده و از تگ {% csrf_token %} برای جلوگیری از حمله های CSRF Attack استفاده شده.خروجی محتوای فرم به خاطر استفاده از {{ form.as_p }} در بین تگ های p قرار میگیره و درنهایت دکمه submit برای ارسال داده به سمت سرور استفاده میکنیم.
حالا به فایل settings.py بروید و متغییر TEMPLATES را به شکل زیر در بیاورید.با این کار جنگو در پوشه اصلی پروژه به دنبال پوشه templates میگردد نه در هر اپ
جنگو ورژن ۳ به پایین
12345678# config/settings.py TEMPLATES = [ { ... 'DIRS': [str(BASE_DIR.joinpath('templates'))], ... }, ]
جنگو ورژن ۳.۱ به بالا
1234567TEMPLATES = [ { ... 'DIRS': [BASE_DIR / 'templates'], ... }, ]
سیستم login ما الان به درستی کار میکنه اما برای بهتر کردن اون ما باید مشخص کنیم که بعد از ورود موفق به کجا ریدایرکت بشه.به عبارت دیگه وقتی کاربر بعد از اینکه اطلاعاتشو به درستی وارد کرد باید به کدوم قسمت سایت فرستاده بشه مثلا وقتی اطاعاتشو وارد کرد و اطاعات صحیح بودن به پروفایلش یا صفحه اول وارد بشه این میشه ریدایرکت کردن.
در فایل تنظیمات از LOGIN_REDIRECT_URL استفاده میکنیم که نشون دهنده مسیر ریدایرکت هستش. درپایین فایل settings.py ما این متغییر را وارد میکنیم.تا به صفحه اول ریدایرکت بشه.
12# config/settings.py LOGIN_REDIRECT_URL = '/'
حالا اگه با کامند python manage.py runserver سرور جنگو را فعال کنید و به ادرس http://127.0.0.1:8000/accounts/login بروید این صفحه را مشاهده میکنید.
ساخت کاربر
تا اینجا همه کارا رو انجام دادیم به جز ساختن کاربر.ما میتونیم این کار رو به سرعت از طریق خط فرمان با دستور createsuperuser انجام دهیم ابتدا با کلید Control+c اتصال سرور را قطع کنید و بعد از آن با دستور python manage.py createsuperuser و دادن اطلاعات کاربر ادمین ساخته میشود.
123456(accounts) $ python manage.py createsuperuser Username (leave blank to use 'ayoub'): Email address: [email protected] Password: Password (again): Superuser created successfully.
حالا اگه دوباره با دستور python manage.py runserver سرور جنگو رو فعال کنید و به http://127.0.0.1:8000/accounts/login این ادرس بروید و اطلاعات کاربر را وارد کنید به این صفحه وارد میشوید.
صفحه لاگین ما به درستی کار میکند اما به دلیل اینکه بعد از صحیح بودن اطلاعات به صفحه اول ریدایرکت میشود و ما هنوز صفحه اول را طراحی نکردیم به ارور Page not foundبرمیخوریم که میگه این صفحه پیدا نشد.خب بریم که درستش کنیم.
طراحی صفحه اول
میخواهیم یک صفحه ساده بسازیم که فقط یک پیام به کاربرانی که sign in و sign out انجام میدهند نشان بدهد.
ابتدا با Control+c سرور رو قطع کنید و در پوشه templates دوفایل base.html و home.html بسازید.
12(accounts) $ touch templates/base.html (accounts) $ touch templates/home.html
و کدهای زیر رو داخل هر کدوم از فایل ها بنویسید.
1234567891011121314<!-- templates/base.html --> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>{% block title %}Django Auth Tutorial{% endblock %}</title> </head> <body> <main> {% block content %} {% endblock %} </main> </body> </html>
12345678910111213<!-- templates/home.html --> {% extends 'base.html' %} {% block title %}Home{% endblock %} {% block content %} {% if user.is_authenticated %} Hi {{ user.username }}! {% else %} <p>You are not logged in</p> <a href="{% url 'login' %}">Log In</a> {% endif %} {% endblock %}
حالا میتونیم فایل login.html ادیت کنیم و از فایل base.html ارث بری کنیم
12345678910111213<!-- templates/registration/login.html --> {% extends 'base.html' %} {% block title %}Login{% endblock %} {% block content %} <h2>Log In</h2> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">Log In</button> </form> {% endblock %}
حالا فایل urls.py رو ادیت کنید و کدهای زیر رو داخلش قرار بدید
در اینجا من از TemplateView برای نمایش فایل های html استفاده کردم .زمانی که ما فقط نیاز به فایل html بدون استفاده از دیتابیس داریم میتونیم از TemplateView استفاده کنیم.
12345678910# config/urls.py from django.contrib import admin from django.urls import path, include from django.views.generic.base import TemplateView # new urlpatterns = [ path('admin/', admin.site.urls), path('accounts/', include('django.contrib.auth.urls')), path('', TemplateView.as_view(template_name='home.html'), name='home'), # new ]
در اینجا ‘ ‘ نشون دهنده صفحه اصلی هستش.و حالا اگه با دستور python manage.py runserver سرور جنگو را فعال کنیم و به ادرس http://127.0.0.1:8000 برویم این تصویر را میبینیم.
کارکرد!حالا چطوری خارج بشیم؟تنها راه logout رفتن به صفحه ادمین http://127.0.0.1:8000/admin و زدن دکمه “Logout” است
با این کار ما خارج و به این صفحه ریدایرکت میشویم
حالا اگه به صفحه http://127.0.0.1:8000 بروید و صفحه رو رفرش کنید میتونید دکمه logout رو ببینید.
لینک logout
حالا لینک logout رو به صفحه اضافه میکنیم تا به راحتی بتونیم این کارو انجام بدیم.خوشبختانه سیستم authentication جنگو با استفاده از viewها و urlهای پیش ساخته این کارو برامون میکنه.ازونجایی که برای logout نیاز به نمایش اطلاعاتی نداریم نیازی هم به طراحی قالب نداریم.تنها کاری که باید انجام بدیم اینه که لینکش رو در صفحه اول قراربدیم و مشخص کنیم بعد از logout کردن به کدوم صفحه ریدایرکت بشیم.
لینک logout پیش ساخته شده رو در فایل home.html قرار میدیم.
1234567891011121314<!-- templates/home.html--> {% extends 'base.html' %} {% block title %}Home{% endblock %} {% block content %} {% if user.is_authenticated %} Hi {{ user.username }}! <p><a href="{% url 'logout' %}">Log Out</a></p> {% else %} <p>You are not logged in</p> <a href="{% url 'login' %}">Log In</a> {% endif %} {% endblock %}
خب به فایل settings.py برید و LOGOUT_REDIRECT_URL را در پایین فایل قرار دهید که نشان دهنده مسیر بعد از logout شدن است.
123# config/settings.py LOGIN_REDIRECT_URL = '/' LOGOUT_REDIRECT_URL = '/' # new
حالا ما صفحه اول رو ساختیم. در فانکشن path کیورد آرگیومنتی به اسم name وجود دارد که با استفاده ازون میتونیم راحت تر url هارو صدا بزنیم
1234# config/urls.py ... path('', TemplateView.as_view(template_name='home.html'), name='home'), ...
حالت میتونیم در فایل settings.py از home به جای ‘/’ استفاده کنیم:
123# config/settings.py LOGIN_REDIRECT_URL = 'home' LOGOUT_REDIRECT_URL = 'home'
حالا اگه صفحه اول رو رفرش کنیم و login کنیم ما به صفحه اول ریدایرکت میشویم و لینک logout برای ما به نمایش در میاد.
حالا اگه روی logout کلیک کنید به صفحه اول ریدایرکت میشوید و لینک login برای شما به نمایش در میاد.
خب اینم از این در سری بعدی قراره sign upکردن در جنگو رو آموزش بدم خوشحال میشم نظراتتون رو بشنوم همچنین میتونید در سایت pythonheroes.ir چیزای بیشتری راجع به جنگو و پایتون یاد بگیرید.