ایجاد اپلیکیشن «نمونه کار» با استفاده از جنگو - شرح پروژه و کدها
ﺯﻣﺎﻥ ﻣﻄﺎﻟﻌﻪ: 6 دقیقه

ایجاد اپلیکیشن «نمونه کار» با استفاده از جنگو - شرح پروژه و کدها

در بخش قبلی از این مقاله ما به صورت کلی با ابزارهایی که نیاز داریم آشنا شدیم و حال قصد داریم وارد کدهایی شویم که مرتبط با این برنامه هستند. به عنوان یک نکته این را بگوییم که این پروژه صفر تا صدی نبوده و تنها بخش‌های مهم مانند ساختار ORM، فرم‌ها و... را بررسی می‌کنیم.

شرح کلی پروژه

در روند استفاده کردن از پروژه یکسری مراتب و راهکارها وجود دارد که باید آن‌ها را بدانید. در این فصل از مستندات قصد دارم قسمت‌هایی که تشکیل دهنده پروژه هستند را به شما شرح دهم.

همانطور که قبلا اشاره شد این پروژه با استفاده از زبان برنامه‌نویسی پایتون توسعه داده شده، به همین دلیل شما برای استفاده کردن و درک سورس کد این پروژه نیاز دارید که به زبان پایتون آشنا باشید.

ساختار پروژه

پروژه در نگاه اول از یکسری فایل و دایرکتوری ساخته شده که در زیر هر کدام با شرح کامل گفته شده است:

  • Profile – پروژه اصلی جنگو همواره شامل یک کنترل‌ کننده اصلی است که ساختار و فانکشنالیتی برنامه را کنترل می‌کند. Profile دایرکتوری این کنترل کننده است که وظیفه چنین کاری را دارد.
  • Users – هر پروژه جنگو جدای از یک کنترل کننده از یکسری اپلیکیشن ایجاد می‌شود که این موارد مستقیما با کنترل کننده رابطه دارند و یک ساختار تا حدی میکرو-سیستمی را ایجاد می‌کنند.
  • Db.sqlite3 – فایل اصلی بانک اطلاعاتی است که در اینجا از Sqlite3 استفاده شده. این فایل بعد از اجرا کردن ORM ایجاد می‌شود.
  • manage.py – به عنوان یک فایل کامندر یا دستور دهنده کار می‌کند. در حقیقت دستورات جنگو از فیلتر manage.py عبور می‌کند و بعد از آن اجرا می‌شود.

بانک اطلاعاتی

ما در جنگو به عنوان یک فریمورک، برای طراحی و ساخت بانک اطلاعاتی از ORM استفاده می‌کنیم. ORM یک دسترسی انتزاعی به بانک اطلاعاتی است که به ما این قابلیت را می‌دهد تا از طریق شئ‌گرایی یک مدل و رابطه از Database ایجاد بکنیم. برای این پروژه نیز ما با دو class همراه هستیم که در زیر به هرکدام اشاره شده است:

class AbstractUser(AbstractBaseUser, PermissionsMixin):
    """
    An abstract base class implementing a fully featured User model with
    admin-compliant permissions.

    Username and password are required. Other fields are optional.
    """
    username_validator = UnicodeUsernameValidator()

    username = models.CharField(
        _('username'),
        max_length=150,
        unique=True,
        help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
        validators=[username_validator],
        error_messages={
            'unique': _("A user with that username already exists."),
        },
    )
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=150, blank=True)
    email = models.EmailField(_('email address'), blank=True)

در اینجا ما با مدل شئ‌گرای بانک اطلاعاتی User همراه هستیم که شامل یکسری فیلد است. همانگونه که مشاهده می‌کنید هر کدام از فیلدها به همراه نوع‌شان تعریف و تنظیم شده است. در قطعه کد زیر نیز ما براساس نیاز پروژه یک کلاس جزئیات خواهیم ساخت که مشخصات کلی کاربر را در خود ذخیره خواهد کرد:

class Detail(models.Model):
    avatar = models.ImageField(upload_to=’user_avatar’, blank=True)
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    short = models.CharField(max_length=250, blank=True)
    about = models.TextField(blank=True)
    location = models.CharField(max_length=50, blank=True)
    facebook = models.CharField(max_length=70, default=’https://facebook.com/’)
    twitter = models.CharField(max_length=70, default=’https://twitter.com/’)
    instagram = models.CharField(max_length=70, default=’https://instagram.com/’)
    github = models.CharField(max_length=70, default=’https://github.com/’)

فرایند Routing

فرایند روتینگ یا مسیردهی به URLهایی که در پروژه وجود دارند اشاره می‌کند. برای روتینگ ما یک فایل روتینگ به صورت بیس در اختیار داریم که تمام قسمت‌های پروژه به آن گوش (Listen) می‌دهند، اما خود این فایل نیز از چندین فایل مشابه با دسترسی غیر مستقیم ساخته شده است.

به عنوان یک مثال؛ همانطور که گفته شد جنگو از یک ساختار پروژه/اپلیکیشن بهره می‌برد. فایل بیس روتینگ در داخل پروژه قرار دارد، اما هر اپلیکیشنی که ایجاد می‌گردد نیز خود یک فایل روتینگ دارد که تمام محتویات آن در نهایت برای اجرا در داخل فایل بیس روتینگ قرار می‌گیرد.

from django.contrib import admin
from django.urls import path, include

from Users import urls
from Users import views
from django.conf import settings
from django.conf.urls.static import static
from django.contrib.auth import views as auth_views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login', auth_views.LoginView.as_view(template_name='Users/login.html'),name="login"),
    path('logout', auth_views.LogoutView.as_view(template_name='Users/logout.html'),name="logout"),
    path('signup/',views.signup),
    path('ed/',views.edit),
    path('',include(urls)),
    
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

همانطور که مشاهده می‌کنید در خط پایانی از لیست urlpatterns یک دستور include قرار گرفته که به urls اشاره دارد. این urls در حقیقت روتینگ اپلیکیشنی است که ما آن را Users نامیده‌ایم.

from django.urls import path
from . import views

urlpatterns = [
    path('<user_name>/',views.show,name='show'),
    path('',views.index,name="start_page"),
]

Views

اگر به کدهای بالا دقت کنید مشاهده می‌کنید که دومین آرگومان هر path یک views است. در واقع در مدل MVT یا Model Views Template وظیفه فانکشنالیتی هر روتینگ و یا هر صفحه به عهده لایه Views است. خود این Viewsها توابعی هستند با نام‌های مختلف که ما به آن‌ها مراجعه می‌کنیم. برای مثال views.show تابعی است برای نمایش اطلاعات کاربری براساس روتینگ داده شده.

از آنجایی که فایل views طولانی است من تنها قسمتی از کدهای آن را در اینجا قرار می‌دهم:

def show(request,user_name):
    user = get_object_or_404(User, username=user_name)
    return render(request,'Users/index.html',{'user': user})

در تابع show یک user_name به عنوان ورودی از تابع فراخوانده می‌شود و روتینگ پروژه ما نیز براساس یک user_name به کاربر نمایش داده می‌شود. اگر user_name وارد شده معتبر باشد (در بانک اطلاعاتی موجود باشد) صفحه‌ای با مشخصات همان user برگشت داده می‌شود. در غیر اینصورت صفحه 404 یا Not Found برگشت داده می‌شود.

def signup(request):
    if request.method == “POST”:
        form1 = SignupForm(request.POST)
        if form1.is_valid():
            form1.save()
            username = form1.cleaned_data.get(‘username’)
            messages.success(request, f’Account for {username} Created. Please Sign in…’)
            return redirect(‘../login’)
    else:
        form1 = SignupForm()
    return render(request, ‘Users/signup.html’, {‘form1’:form1})

ساختار فرم‌ها

فرم‌ها در جنگو راهی منطقی برای ارتباط برقرار کردن با بانک اطلاعاتی هستند. این فرم‌ها را می‌شود به صورت دستی و یا می‌شود براساس مدل‌های بانک اطلاعاتی ایجاد کرد. زمانی که در جنگو فرم User را فراخوانی می‌کنیم، به این معناست که ابتدا باید مراجعه‌ای به جدول User شود و سپس براساس فیلدهای آن جدول یک فرم ایجاد می‌شود. چنین فرایندی در این پروژه هم به صورت دستی و هم براساس مدل بانک اطلاعاتی ایجاد شده است.

در زیر می‌توانید یک نمونه از فرم که برای مدل User و Detail ایجاد شده را مشاهده نمایید:

from django import forms
from .models import Detail
from django.contrib.auth.models import User
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm, UserChangeForm

class LoginForm(AuthenticationForm):
    username = forms.CharField(widget=forms.TextInput(attrs=
    {'class':'form-control',
    }))
    password = forms.CharField(widget=forms.PasswordInput(attrs={'class':'form-control'}))

class SignupForm(UserCreationForm):
    email = forms.EmailField()

    class Meta:
        model = User
        fields = ['username','email','password1','password2']

class EditProfile(UserChangeForm):

    class Meta:
        model = User
        fields = (
            'username',
            'email',
            'first_name',
            'last_name',
            'short',
            'avatar',
            'about',
            'mobile',
            'phone',
            'location',
            'facebook',
            'instagram',
            'twitter',
            'github',
            'websitename',
            'websiteurl',
        )

class DetailEdit(forms.ModelForm):

    class Meta:
        model = Detail
        fields = ['avatar','short']

پیکربندی تنظیمات پروژه

هر پروژه مبتنی بر جنگو از یک فایل settings.py برای اعمال تنظیمات کلی‌اش استفاده می‌کند. برای مثال شما در این فایل می‌توانید نوع بانک اطلاعاتی پروژه، middlewareهای پروژه، ساعت مکانی پروژه، وضعیت debugging و... را مدیریت بکنید. در زیر می‌توانید چند قطعه کد از این فایل را همراه با توضیحات کلی مشاهده بکنید:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

در قطعه کد بالا ما روال استفاده از بانک اطلاعاتی sqlite3 را پیاده‌سازی کرده‌ایم. بنابراین هر بار که پروژه ما migrate (یک نوع از build شدن پروژه/بانک اطلاعاتی) می‌شود، مدل‌های ما به جداول رابطه‌ای در sqlite3 تبدیل می‌شوند.

تنظیم زبان اصلی پروژه و منطقه زمانی نیز از این طریق انجام می‌شود.

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

نکته: اجرا کردن پروژه

برای اجرا کردن پروژه شما نیاز دارید که به فایل manage.py دسترسی داشته باشید. چرا که تمام اعمال پروژه از آن جا صورت می‌گیرد. برای اینکار دستور python manage.py runserver را وارد کنید. بعد از این کار پروژه شما روی پورت ۸۰۰۰ قابل دسترس است.

در پایان این بخش

استفاده کردن از جنگو می‌تواند بسیار لذت بخش باشد، به شرطی که شما آگاهی نسبی و خوبی از ساختار یک پروژه مبتنی بر وب را داشته باشید. اگر ندارید، پیشنهاد می‌شود قبل از یادگیری جنگو، سراغ فریمورک‌های مینیمال بروید. فلسک و اکسپرس جی‌اس فریمورک‌های مینیمال دو زبان پایتون و جاوااسکریپت هستند که به شما در این مسیر بسیار کمک می‌کنند.

چه امتیازی برای این مقاله میدهید؟

خیلی بد
بد
متوسط
خوب
عالی
4 از 1 رای

/@arastoo
ارسطو عباسی
کارشناس تولید و بهینه‌سازی محتوا

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

دیدگاه و پرسش

برای ارسال دیدگاه لازم است وارد شده یا ثبت‌نام کنید ورود یا ثبت‌نام

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

ارسطو عباسی

کارشناس تولید و بهینه‌سازی محتوا