آشنایی با رست فریمورک جنگو (Django Rest FrameWork)


تو این پست نگاهی خواهیم داشت به Django Rest FrameWork یا به اختصار DRF


داخل پست قبلی توضیحاتی در رابطه با این که API چی هست دادم که میتونید قبل از خوندن این پست نگاهی بهش بندازید.

خوب برای شروع بهتره که اول یه سری بزنیم به سایت اصلی DRF

https://www.django-rest-framework.org

یه سری توضیحات اولیه داده در مورد web api ها و اینکه چرا و کجا استفادشون میکنیم و بعد پکیج های لازم برای اینکه بتونیم در واقع DRF رو روی پروژه جنگو خودمون پیاده کنیم رو معرفی کرده که اینجوری میتونید نصبش کنید :

1-پایتون و pip رو حتما باید اول نصب کنید

2-نصب پکیج های زیر :

pip install django
pip install djangorestframework
و یه سری پکیج دیگه که بر حسب نیاز در ادامه باید نصب کنید 


اما , اصلا به چه دردی میخوره این DRF :)

بزارید یه مثال ساده بزنم

فرض کنید چند مدت پیش اومدید و برای خودتون با استفاده از جنگو (یا هر فریمورک دیگه ای ) یه سایت زدید اما حالا قصد دارید که برای همون سایتتون اپ اندروید هم بزنید ، خوب کار معقولانه اینه که شما بتونید همه اطلاعاتی که روی دیتابیس سایتتون هست رو از یه طریقی داخل اپ اتون نشون بدید برای این کار میاید و یک سری API تنظیم میکنید تا بتونید هر سری با درخواست دادن به اون اطلاعات مورد نیازتون رو داخل اپ اندروید داشته باشید . بنابراین شما بدون نیاز به اینکه دیتابیس جدیدی برای اپ اندرویدتون داشته باشید میتونید تمامی اطلاعات سایتتون رو داخل اون نمایش بدید.

تصویر زیر رو ببینید


اطلاعات شما داخل یک دیتابیس قرار گرفته ولی در تمامی نسخه های نرم افزاری میتونید ازش استفاده کنید
اطلاعات شما داخل یک دیتابیس قرار گرفته ولی در تمامی نسخه های نرم افزاری میتونید ازش استفاده کنید


بنابراین وقتی مثلا داخل وبسایت شما تغییری در دیتابیس ایجاد میشود همین تغییرات درنسخه اندروید نیز ایجاد خواهد شد ، بنابراین API ابزاری هست که اطلاعات رو بر حسب نیاز ما از دیتابیس استخراج میکند و به ما ارائه میدهد و یا اطلاعات جدیدی را به دیتابیس اضافه میکند.


خوب ، یواش یواش بریم سراغ اینکه داخل یه پروژه عملی نحوه ساختن api هارو در رست فریمورک جنگو ببینیم

اگر قبلا با جنگو کار کرده باشید قطعا میدونید که modelچی هست اگرهم نه که بخوام ساده توضیح بدم شما برای این که جدول های داخل دیتابیس رو در جنگو آماده سازی کنید لازم نیست که مستقیما کد های دیتابیس بزنید و میتوانید با استفاده از مدل ها ساختار جدول هاتون و فیلد هاش رو مشخص کنید و با استفاده از دستور migrate خود پایتون اون هارو مستقیما به کد دیتابیس که به صورت پیش فرض در جنگو دیتابیس sqlite هست تبدیل میکند .

توضیحات بیشتر models در اینجا


اگر جنگو را روی دستگاه خودتون نصب داشته باشید با استفاده از دستور زیر در cmd میتونید پروژه خودت رو ایجاد کنید

django-admin startproject project_name

سپس میتونید وارد پوشه پروژه تون بشید و با دستور زیر یک اپلیکیشن ایجاد کنید

python manage.py startapp app_name

اینجا براتون در رابطه با ساخت پروژه جنگو بیشتر توضیح داده :)

باید برای این که بتونیم از DRF استفاده کنیم اپ rest_framework را هم به همراه اپی که در بالا ساختیم در فایل settings.py به قسمت INSTALLED_APPS اضافه کنیم


در ادامه لازمه که مدل خودمون(جدول های دیتابیس ) رو آماده کنیم تا بعد بتونیم برای همین دیتابیس API های دلخواهمون رو بنویسیم

من نمونه کد هارو از قسمت هایی از پروژه ای که این روز ها درگیرش هستم برای آشنایی بیشتر شما میارم :

فایل models.py

همینطور که میبیند مدل Group دارای 4 فیلد هست که یکی از اون ها به صورت manytomany هست که باز اگر خواستید بیشتر باهاش آشنا بشید به اینجا سر بزنید

این مدل بعد از migrate شدن یک جدول از دیتابیس خواهد شد و من میتونم از طریق پنل ادمین اطلاعات خودم را داخلش ذخیره کنم

بعد از اینکه یک مدل رو ساختیم باید براش serializer بسازیم

توضیح ساده اش اینه که بتونیم مکانیزمی را فراهم کنیم که اطلاعات مدل های ایجاد شده در جنگو را به فرمتی در بیاریم که به راحتی قابل استفاده باشند مثل JSON و بالعکس.

برای اینکار یک فایل serializers.py در هر اپلیکیشنی که در واقع میخواید مدل های اون رو serialize کنید ،ایجاد کنید

موارد زیر را به اون اضافه کنید

from rest_framework import serializers
from .models import Group #مدلی که میخواهید سریالایز کنید

در ادامه یک کلاس GroupSerializer ایجاد میکنیم و داخل اون مدل و فیلد هایی که میخواهیم سریالایز شود را اضافه میکنیم

میتوانیم تنها فیلد های دلخواهمون رو اضافه کنیم به صورت زیر :


بعد از این مرحله باید داخل فایل Views.py بریم و موارد زیر را اضافه کنیم:

from rest_framework.decorators import api_view #   GET PUT POST , ..... نوع در خواست 
from rest_framework.response import Response #ارسال پاسخ ها 
from rest_framework import status #مشخص کردن وضعیت یک درخواست
from .models import Group#مدل هایی که میخواهیم سریالایز کنیم
from .serializers import GroupSerializer # سریالایز که در مرحله قبل نوشتیم


در مثال بالا نوع درخواست ارسال شده به سمت سرور GET می باشد

از مدل Group تمام اطلاعاتش را دریافت میکنیم وداخل متغیر groups میریزیم

اطلاعات را به سریالایزر میدهیم و خروجی که شامل دیتای مناسب برای پاسخ هست را ارسال میکنیم

از status.HTTP_200_OK به معنای درست بودن وضعیت استفاده میکنیم

لیست همه استاتوس هارو اینجا میتونید ببیند

و لیست متد های HTTP رو هم در تصویر زیر میتونید ببیند

لیست متدهای HTTP
لیست متدهای HTTP


بعد از این مرحله باید url های لازم رو ایجادکنیم

داخل فایل urls.py از path زیر استفاده میکنیم و متد get_groups که داخل فایل views نوشته شده را اینجا اضافه میکنیم :

path('get-groups',views.get_groups)


***بعضی جا ها شما نمیخواهید که این APIها در اختیار عموم قرار بگیرد و تنها کسی که مثلا لاگین کرده باشد و یا ادمین سایت باشد بتواند به این ها دسترسی داشته باشد

برای این که بتوانید این محدودیت هارا قائل شوید باید از permission های مربوط به rest استفاده کنید که اینجا میتوانید اطلاعات بیشتری از permission ها کسب کنید

برای نمونه من فقط به کسانی که داخل سایت لاگین کرده اند و یا ادمین هستند این اجازه را میدهم

برای این کار داخل فایل settings.py از دستورات زیر استفاده میکنم

در بعضی مواقع خود شما هم میتوانید میتوانید permission های شخصی سازی شده خودتون رو بنویسید

برای این کار هم یک فایل permissions.py داخل اپ مورد نظرتون ایجاد کنید و به صورت زیر دسترسی های شخصی سازی شده رو اعمال کنید

من در این فایل یک Permission با نام IsOwner میسازم :

فایل permissions.py
فایل permissions.py


و سپس داخل view هایی که قبلا نوشته اید IsOwner رو به صورت زیر اضافه کنید :



خوب در نهایت برای دیدن نحوه کار کردن این API ها هم میتوانید از خوده محیطی که جنگو برای rest فراهم کرده استفاده کنید و هم از نرم افزار معروف Postman

برای شروع پروژه خودتون رو ران کنید

 python manage.py runserver


از local host استفاده کنید که به صورت 127.0.0.1:8000 هست

اگر آدرس زیر رو بزنید داخل مرورگر در ابتدا چون لاگین صورت نگرفته و permission داده نشده به چیزی که میبنیم به این صورت است

http://127.0.0.1:8000/elmi/get-groups

اما پس از لاگین کردن خروجی به صورت JSON است که اطلاعات تمام گروه هارا نشان میدهد

***این یک مثال اولیه و ساده بود از Django RestFramework و بیشتر جنبه آشنایی داشت و پست آموزشی نبود و امیدوارم کلیت کار دستتون اومده باشه و بتونید با سرچ زدن و استفاده از داکیومنت های اصلی خود DRF پروژه های خوبی رو داشته باشید :)




خوب سلام دوباره، بکم آپدیت :)

توی داکیومنت های جدید djando rest framework میتونید در مورد Generic View ها و viewset ها بیشتر بخونید ، چون خیلی سرعت توسعه با این روش ها بیشتر و بهتر شده و به نظرم واجبه که در موردشون مطالعه داشته باشید

من سعی میکنم در ادامه یه نمونه از Concrete View Classes رو براتون توضیح بدم باشد که رستگار شوید :

مدلی که برای این مثال داریم به صورت زیره :

class Post(models.Model):
         author = models.ForeignKey(User,on_delete=models.CASCADE)
         title = models.CharField(max_length=250)
         content = models.TextField()
         status = models.BooleanField()
         category = models.ForeignKey(&quotCategory&quot,on_delete=models.SET_NULL,null=True)
         created_date = models.DateTimeField(auto_now_add=True)
         updated_date = models.DateTimeField(auto_now=True)
         def __str__(self):
                  return self.title

بیاید به این چند خط کد در فایل views.py نگاه کنید تا بعدش توضیح بدم چه اتفاقی میفته :

from rest_framework.permissions import IsAuthenticated,IsAuthenticatedOrReadOnly

from rest_framework.views import APIViewfrom rest_framework.generics import ListAPIView,RetrieveUpdateAPIView,ListCreateAPIView,DestroyAPIView,UpdateAPIView,CreateAPIView,RetrieveUpdateDestroyAPIView

from .permissions import IsOwnerOrReadOnly

from django_filters.rest_framework import DjangoFilterBackend

from rest_framework.filters import SearchFilter,OrderingFilter


class PostList(ListCreateAPIView):
                permission_classes = [IsAuthenticatedOrReadOnly]
               serializer_class = PostSerializer
               queryset = Post.objects.all()

               filter_backends = [DjangoFilterBackend,SearchFilter,OrderingFilter]
              filterset_fields = {
                            &quotcategory&quot: [&quotin&quot, &quotexact&quot]
              }
              search_fields = ['title','content']
              ordering_fields = ['created_date']


class PostDetail(RetrieveUpdateDestroyAPIView):
               permission_classes = [IsOwnerOrReadOnly]
               queryset = Post.objects.filter(status = True)
               serializer_class = PostSerializer

خوب همینطور که میبینید در وهله اول نوشتن view ها خیلی راحت تر شده و یه سری ویژگی های خوب دیگه مثل filters , search, ordering قابل استفاده است

در واقع شما برحسب نیاز خودتون باید اون class view مناسب رو انتخاب کنید و ازش ارث بری داشته باشید، فقط همین، بقیه موارد رو خود django کنترل میکنه .

توی فایل url تون حواستون باشه که برای حالت get,update,delete که برای یک object هست حتما مقدار pk را در url ارسال کنید .

path('post-list/',views.PostList.as_view(),name='post-list'),
path('post-detail/<int:pk>/',views.PostDetail.as_view(),name='post-detail')

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

اگر تجربه استفاده از rest رو داشته اید و یا منبع خوبی برای آموزش میشناسید این زیر معرفی کنید برای بقیه :)