django之restframework使用 (一)

Restframework

這裏先簡單的介紹一下restful協議,Django REST framework 是一個強大且靈活的工具包,用以構建Web APIs,體現了一切皆是資源,操做只是請求方式前端

基於restful協議的框架有不少,Django下的restframework只是其中的一種,restful協議是一套開發的規範,url裏不能有動做相關的詞彙,好比add,edit,這些都經過用請求的方式來實現。python

安裝數據庫

pip3 install djangorestframework

 註冊django

INSTALLED_APPS = (
    ...
    'rest_framework',
)

 基本使用json

登陸認證restful

url(r'^login/$', views.LoginView.as_view(),name="login"),

 

def get_random_str(user):
    import hashlib,time
    ctime=str(time.time())

    md5=hashlib.md5(bytes(user,encoding="utf8"))
    md5.update(bytes(ctime,encoding="utf8"))

    return md5.hexdigest()

from .models import User

class LoginView(APIView):

    def post(self,request):

        name=request.data.get("name")
        pwd=request.data.get("pwd")
        user=User.objects.filter(name=name,pwd=pwd).first()
        res = {"state_code": 1000, "msg": None}
        if user:

            random_str=get_random_str(user.name)
            token=Token.objects.update_or_create(user=user,defaults={"token":random_str})
            res["token"]=random_str
        else:
            res["state_code"]=1001 #錯誤狀態碼
            res["msg"] = "用戶名或者密碼錯誤"

        import json
        return Response(json.dumps(res,ensure_ascii=False))

 認證類app

from .models import *
class TokenAuth(BaseAuthentication):
    def authenticate(self,request):
        token = request.GET.get("token")
        token_obj = Token.objects.filter(token=token).first()
        if not token_obj:
            raise exceptions.AuthenticationFailed("驗證失敗123!")
        else:
            return token_obj.user.name,token_obj.token

 

models.py

from django.db import models
 
class Author(models.Model):
    name=models.CharField(max_length=32)
    age=models.IntegerField()
    def __str__(self):
        return self.name

 urls.py框架

from django.conf.urls import url
from django.contrib import admin
from rest_demoimport views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^authors/$', views.AuthorsView.as_view()),
    url(r'^authors/(\d+)/$', views.AuthorsDetailView.as_view()),
]

 serializer.pydom

from rest_framework import serializers
from rest_demo import models
 
class AuthorModelSerializers(serializers.ModelSerializer):
    class Meta:
        model = models.Author
        fields = '__all__'

 views.py工具

from rest_demo import serializer
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_demo import models
 
class AuthorsView(APIView):
    def get(self,request):
        '''
        查詢全部做者
        :param request:
        :return:
        '''
        author_list = models.Author.objects.all()
        auts = serializer.AuthorModelSerializers(author_list,many=True)#  默認爲False
        return Response(auts.data)   #  .data  拿json對象
 
 
    def post(self,request):
        '''
        添加做者
        :param request:
        :return:
        '''
        auts = serializer.AuthorModelSerializers(data=request.data)
        if auts.is_valid():
            auts.save()
            return Response(auts.data)
        return Response(auts.errors)
 
 
class AuthorsDetailView(APIView):
    def get(self,request,id):
        '''
        查詢單條做者
        :param request:
        :param id:
        :return:
        '''
        author = models.Author.objects.filter(pk=id).first()
        auts = serializer.AuthorModelSerializers(author)
        return Response(auts.data)
 
 
    def put(self,request,id):
        '''
        修改單條做者
        :param request:
        :param id:
        :return:
        '''
        author = models.Author.objects.filter(pk=id).first()
        auts = serializer.AuthorModelSerializers(instance=author,data=request.data)
        if auts.is_valid():
            auts.save()
            return Response(auts.data)
        return Response(auts.errors)
 
 
    def delete(self,request,id):
        '''
        刪除單條做者
        :param request:
        :param id:
        :return:
        '''
        models.Author.objects.filter(pk=id).delete()
        return Response()

 url中

urlpatterns = [
    url(r'^books/$', views.BookViewSet.as_view(),name="book_list"),
    url(r'^books/(?P<pk>\d+)$', views.BookDetailViewSet.as_view(),name="book_detail"),
    url(r'^publishers/$', views.PublishViewSet.as_view(),name="publish_list"),
    url(r'^publishers/(?P<pk>\d+)$', views.PublishDetailViewSet.as_view(),name="publish_detail"),
]

 view視圖中

class Books(View):
            def get(self,requset):
                pass #查看全部書籍
                
            def post(self,request):
                pass #添加書籍
                
        class BooksDetail(View):
            def get(self,request,id):
                pass #查看某一本書籍
        
            def put(self,requset,id):
                pass #更新書籍
                
            def delete(self,request,id):
                pass #刪除書籍

 在父類的基礎上擴展,並執行父類方法

繼承後調用父類的方法:
    擴展後子類繼續調用父類的方法:
    class LoginView(View):
        def dispatch(self,request,*arg,**kwargs):
        # 兩種方式均可以
                       print('擴展父類方法')
            ret = super(LoginView,self).dispatch(self,request,*arg,**kwargs)
            ret = super().dispatch(self,request,*arg,**kwargs)
            return ret

 序列化的方式,下列三種

model.py中

rom django.db import models

# Create your models here.


class Book(models.Model):
    title=models.CharField(max_length=32)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("Publish")
    authors=models.ManyToManyField("Author")
    def __str__(self):
        return self.title

class Publish(models.Model):
    name=models.CharField(max_length=32)
    email=models.EmailField()
    def __str__(self):
        return self.name

class Author(models.Model):
    name=models.CharField(max_length=32)
    age=models.IntegerField()
    def __str__(self):
        return self.name

model

 view部分

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse
from django.core import serializers


from rest_framework import serializers

class BookSerializers(serializers.Serializer):
    title=serializers.CharField(max_length=32)
    price=serializers.IntegerField()
    pub_date=serializers.DateField()
    # 一對多核多對多須要咱們本身構建
    publish=serializers.CharField(source="publish.name")
    #authors=serializers.CharField(source="authors.all")
    authors=serializers.SerializerMethodField()
    def get_authors(self,obj):
        temp=[]
        for author in obj.authors.all():
            temp.append(author.name)
        return temp


class BookViewSet(APIView):

    def get(self,request,*args,**kwargs):
        book_list=Book.objects.all()
        # 序列化方式1:
        # from django.forms.models import model_to_dict
        # import json
        # data=[]
        # for obj in book_list:
        #     data.append(model_to_dict(obj))
        # print(data)
        # return HttpResponse("ok")

        # 序列化方式2:
        # data=serializers.serialize("json",book_list)
        # return HttpResponse(data)

        # 序列化方式3:
        bs=BookSerializers(book_list,many=True)
        return Response(bs.data)

上面能作的知識單純的將queryset序列化,那麼有沒有可以既可以序列化對象傳給前端,

又可以接受前端的數據而後更新到數據庫呢?

ModelSerializer

modelserializer和modelform很相似,用法也很類似.

class BookSerializers(serializers.ModelSerializer):
      class Meta:
          model=Book
          fields="__all__"
          depth=1

 提交post請求

def post(self,request,*args,**kwargs):
       
        bs=BookSerializers(data=request.data,many=False)
        if bs.is_valid():
            # print(bs.validated_data)
            bs.save()
            return Response(bs.data)
        else:
            return Response(bs.errors)

 重寫save和create方法

class BookSerializers(serializers.ModelSerializer):

      class Meta:
          model=Book
          fields="__all__"
          # exclude = ['authors',]
          # depth=1

      def create(self, validated_data):
        
          authors = validated_data.pop('authors')
          obj = Book.objects.create(**validated_data)
          obj.authors.add(*authors)
          return obj

  單條數據的get和put請求

class BookDetailViewSet(APIView):

    def get(self,request,pk):
        book_obj=Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj)
        return Response(bs.data)

    def put(self,request,pk):
        book_obj=Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj,data=request.data)
        if bs.is_valid():
            bs.save()
            return Response(bs.data)
        else:
            return Response(bs.errors)

 咱們能夠看到中間CBV的類繼承了restframework的APIView,那麼裏面的繼承關係,和流程是怎麼樣的呢?

 

 

 

url(r'^books/$', views.BookView.as_view(),name="books")#views.BookView.as_view()至關於 View下的view,用戶訪問執行view

也就至關於books/一旦被訪問: view(request)  就執行APIView: dispatch()方法

 

在restframework的dispatch方法裏幹了什麼事?

從新構建request對象
self.request=Request(request)
self.request._request

 Django原生的request:

 如何在重構的request對象裏獲取數據?

request.GET  # get

request.data # POST  PUT delete

 超連接API:Hyperlinked

class BookSerializers(serializers.ModelSerializer):
      publish= serializers.HyperlinkedIdentityField(
                     view_name='publish_detail',  #要找的url的別名   name
                     lookup_field="publish_id",   關聯的publish_id
                     lookup_url_kwarg="pk")           對應URL中?P<pk>
      class Meta:
          model=Book
          fields="__all__"
          #depth=1

 urls部分:

urlpatterns = [
    url(r'^books/$', views.BookViewSet.as_view(),name="book_list"),
    url(r'^books/(?P<pk>\d+)$', views.BookDetailViewSet.as_view(),name="book_detail"),
    url(r'^publishers/$', views.PublishViewSet.as_view(),name="publish_list"),
    url(r'^publishers/(?P<pk>\d+)$', views.PublishDetailViewSet.as_view(),name="publish_detail"),
]
相關文章
相關標籤/搜索