ثبت نام یا Sign Up

جنگو

سلام

به عنوان اولین گام باید یک url برای صفحۀ ثبت نام تعریف کنیم.

myproject/urls.py

from django.conf.urls import url
from django.contrib import admin

from accounts import views as accounts_views
from boards import views

urlpatterns = [
    url(r'^$', views.home, name='home'),
    url(r'^signup/$', accounts_views.signup, name='signup'),
    url(r'^boards/(?P<pk>\d+)/$', views.board_topics, name='board_topics'),
    url(r'^boards/(?P<pk>\d+)/new/$', views.new_topic, name='new_topic'),
    url(r'^admin/', admin.site.urls),
]

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

from accounts import views as accounts_views

مرحلۀ بعدی ساخت یک تابع درون فایل ویو و با نام sign up است.

accounts/views.py

from django.shortcuts import render

def signup(request):
    return render(request, 'signup.html')

این تابع به قالب signup.html ارجاع شده و بنابراین می بایست آن را ایجاد کنیم.

templates/signup.html

{% extends 'base.html' %}

{% block content %}
  <h2>Sign up</h2>
{% endblock %}

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

در مرورگر آدرس http://127.0.0.1:8000/signup را باز می کنیم.

 

و مثل همیشه نوبت به نوشتن برنامۀ تست می رسد.

accounts/tests.py

from django.core.urlresolvers import reverse
from django.urls import resolve
from django.test import TestCase
from .views import signup

class SignUpTests(TestCase):
    def test_signup_status_code(self):
        url = reverse('signup')
        response = self.client.get(url)
        self.assertEquals(response.status_code, 200)

    def test_signup_url_resolves_signup_view(self):
        view = resolve('/signup/')
        self.assertEquals(view.func, signup)

و حالا تستِ تست!

python manage.py test

و این هم از خروجی:

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
..................
------------------------------------------------
Ran 18 tests in 0.652s

OK
Destroying test database for alias 'default'...

در تمام صفحات اعتبارسنجی نمی خواهیم منوی بالایی در قسمت breadcrumb وجود داشته باشد و باز با این حال می توان از قالب base.html با اندکی تغییر استفاده نمود.

templates/base.html

{% load static %}<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>{% block title %}Django Boards{% endblock %}</title>
    <link href="https://fonts.googleapis.com/css?family=Peralta" rel="stylesheet">
    <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
    <link rel="stylesheet" href="{% static 'css/app.css' %}">
    {% block stylesheet %}{% endblock %}  <!-- HERE -->
  </head>
  <body>
    {% block body %}  <!-- HERE -->
      <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <div class="container">
          <a class="navbar-brand" href="{% url 'home' %}">Django Boards</a>
        </div>
      </nav>
      <div class="container">
        <ol class="breadcrumb my-4">
          {% block breadcrumb %}
          {% endblock %}
        </ol>
        {% block content %}
        {% endblock %}
      </div>
    {% endblock body %}  <!-- AND HERE -->
  </body>
</html>

در فایل بالا سعی کردیم تا با بلوکه بندی این قالب صرفاً در صفحۀ ثبت نام از بخشی از آن استفاده کنیم که به کارمان می آید.

در این راستا از بلوک {% block stylesheet %}{% endblock %} برای استفاده از CSSهای اضافه بهره برداری کرده ایم.

بلوک بعدی مربوط به {% block body %} می شود که با تگ {% endblock body %} پایان یافته است.

حالا در فایل signup.html تگ {% block content %} را به {% block body %} تغییر می دهیم.

templates/signup.html

{% extends 'base.html' %}

{% block body %}
  <h2>Sign up</h2>
{% endblock %}

و با این کار خروجی به شکل زیر تغییر می یابد.

حالا که تنظیمات اولیه اعمال شد نوبت به آن رسیده تا فرم ثبت نام را بسازیم. برای این کار از یکی از فرم‌های موجود در جنگو به نام UserCreationForm استفاده می کنیم.

accounts/views.py

from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import render

def signup(request):
    form = UserCreationForm()
    return render(request, 'signup.html', {'form': form})

فایل قالب هم به شکل زیر می شود.

templates/signup.html

{% extends 'base.html' %}

{% block body %}
  <div class="container">
    <h2>Sign up</h2>
    <form method="post" novalidate>
      {% csrf_token %}
      {{ form.as_p }}
      <button type="submit" class="btn btn-primary">Create an account</button>
    </form>
  </div>
{% endblock %}

خروجی:

نکته مهم این است که ما در فایل ویو، از تابع ()UserCreationForm استفاده و آن را به قالب signup.html پارس کرده ایم و به همین دلیل جنگو می فهمد که به چه فیلدهایی احتیاج دارد.

گام بعدی آن است که این فرم را کمی زیبا و مرتب کنیم که البته این کار را قبلاً در قالب form.html انجام داده بودیم.

{% extends 'base.html' %}

{% block body %}
  <div class="container">
    <h2>Sign up</h2>
    <form method="post" novalidate>
      {% csrf_token %}
      {% include 'includes/form.html' %}
      <button type="submit" class="btn btn-primary">Create an account</button>
    </form>
  </div>
{% endblock %}

همانطور که در خروجی مشخص است یک سری از تگ های HTML به صورت خام در صفحه نمایش داده می شود. علت این کار آن است که جنگو به دلیل مسائل امنیتی و برای جلوگیری از ارسال تگ‌ها به صورت غیرمجاز، تمام کارکترهای عملگر را نادیده می گیرد. اما در این فرم می توان به این کارکترهای خاص اعتماد کرد!

templates/includes/form.html

{% load widget_tweaks %}

{% for field in form %}
  <div class="form-group">
    {{ field.label_tag }}

    <!-- code suppressed for brevity -->

    {% if field.help_text %}
      <small class="form-text text-muted">
        {{ field.help_text|safe }}  <!-- new code here -->
      </small>
    {% endif %}
  </div>
{% endfor %}

در فایل جدید، با اضافه کردن دستور safe به عبارت field.help_text، آن را به {{ field.help_text|safe }} تغییر داده ایم.

و به همین راحتی فرم زیبا می شود!

گام بعدی آن است که فرم ثبت نام واقعاً ثبت نام کند! و یک سری فیلد خشک و خالی نباشد.

accounts/views.py

from django.contrib.auth import login as auth_login
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import render, redirect

def signup(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            user = form.save()
            auth_login(request, user)
            return redirect('home')
    else:
        form = UserCreationForm()
    return render(request, 'signup.html', {'form': form})

(تابع login را به نام مستعار auth_login تغییر داده ایم تا با ویوی لاگین پیش فرض جنگو دچار تصادم نشود.  البته ویوی لاگین در ورژن‌های جدید تغییر نام داده و حتی اگر این گونه نامگذاری نشود هم به مشکلی بر نمی خوریم اما کلاً خوب است که برای نام‌ها یک پیشوند در نظر بگیریم تا هم درک کدمان بهتر شود و هم از تصادم جلوگیری شود.)

اگر فرم معتبر باشد با استفاده از ()user = form.save یک یوزر جدید برایش ایجاد می شود. سپس یوزرِ ساخته‌شده با استفاده از یکی از آرگومان‌های تابع auth_login ارسال می شود. بعد از آن هم کاربر به صفحۀ اصلی ریدایرکت می شود.

حالا نوبت به تست عملی می رسد. می خواهیم داده های غیر معتبر یا فیلدهای خالی یا فیلدهای غیراستاندارد یا یوزرنیم‌های موجود در برنامه را به عنوان ورودی های فرم به آن ارسال کنیم.

حالا فرم را تکمیل می کنیم. می خواهیم ببینیم آیا با تکمیل درست فرم، کاربر ساخته می شود و آیا به صفحۀ اصلی ریدایرکت می شود یا خیر.

ترجمۀ اختصاصی توسط تمدن

 

مطلب بعدی: ارجاع دهی به کاربران معتبر در قالب

مطلب قبلی: تنظیمات اولیه

بدون دیدگاه

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

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

جنگو
پیکربندی گواهینامۀ https

سلام حالا می خواهیم برنامۀ خودمان را با گواهینامۀ https امن کنیم. ساده ترین کار برای انجام آن Let’s Encrypt است. قبل از Let’s Encrypt هرگز تنظیمات https به این راحتی نبوده و مهمتر اینکه اینکار کاملاً رایگان است. آن ها راه حلی به نام certbot را ارائه داده اند …

جنگو
پیکربندی سرویس ایمیل

سلام یکی از بهتر سرویس دهنده های ایمیل Mailgun با قابلیت ۱۲ هزار ایمیل رایگان در ماه است. به صورت رایگان ثبت نام کنید. برای اینکار باید آن را با سرویس دهندۀ دامین خود تنظیم کنید که در این آموزش از tamadon.org استفاده شده است. حالا اولین رکورد DNS را …

جنگو
پیکربندی NGINX

سلام کار بعدی که قرار است انجام شود؛ تنظیمان Nginx به شکلی است که پاسخگویی و سرویس دهی مربوط به فایل های استاتیک را خود انجام دهد و سایر درخواست ها را به Gunicorn بفرستد. یک فایل پیکربندی با نام boards را درون /etc/nginx/sites-available/ و با محتوای زیر اضافه می …

هرگونه استفادۀ از این آموزش به صورت رایگان و با ارجاع به تمدن جایز است.