Django restframe 檢視函式以及ModelSerializer的使用
阿新 • • 發佈:2018-12-12
建立model資料庫
from django.db import models __all__ = ['Book', 'Publisher', 'Author'] # Create your models here. class Book(models.Model): title = models.CharField(max_length=32) CHOICES = ((1, 'python'), (2, 'linux'), (3, 'go')) category = models.IntegerField(choices=CHOICES, default=1, verbose_name='分類') pub_time = models.DateField(verbose_name='出版日期') publisher = models.ForeignKey(to='Publisher', verbose_name='出版社') authors = models.ManyToManyField(to='Author', verbose_name='作者') class Meta: db_table = 'book' verbose_name = '書籍表' verbose_name_plural = verbose_name def __str__(self): return self.title class Publisher(models.Model): name = models.CharField(max_length=32, verbose_name='出版社') address = models.CharField(max_length=32, verbose_name='地址') class Meta: db_table = 'publisher' verbose_name = '出版社表表' verbose_name_plural = verbose_name def __str__(self): return self.name class Author(models.Model): name = models.CharField(max_length=32, verbose_name='作者') country = models.CharField(max_length=32, verbose_name='國家') class Meta: db_table = 'author' verbose_name = '作者表' verbose_name_plural = verbose_name def __str__(self): return self.name
資料庫部分一共三張表,書籍表以及作則和出版社表
admin註冊
from django.contrib import admin
from SerDemo import models
# Register your models here.
for table in models.__all__:
admin.site.register(getattr(models,table))
這裡用到了小技巧,利用匯入的models.__all__迴圈批量註冊model模型
序列器的實現
在專案下新建serializers,py檔案
from rest_framework import serializers from SerDemo.models import Book, Author, Publisher # 自定義檢驗函式在欄位引數validators中作為引數新增 def my_validate(value): if "敏感詞彙" in value.lower(): raise serializers.ValidationError("輸入的資訊含有敏感詞彙") return value ### 建立django序列化器類,繼承serializers.ModelSerializer欄位可自動關聯 class BookSerializer(serializers.ModelSerializer): ## 需要重寫的欄位,SerializerMethodField 會去找get_欄位名的函式並執行獲取返回值作為欄位值 category_read = serializers.SerializerMethodField(read_only=True,validators=[my_validate,]) publisher_read = serializers.SerializerMethodField(read_only=True) authors_read = serializers.SerializerMethodField(read_only=True) # category_read的鉤子函式,返回要顯示的值,注意obj是每個要顯示到前端的資料物件 def get_category_read(self,obj): return obj.get_category_display() # publisher_read的鉤子函式,返回要顯示的值 def get_publisher_read(self,obj): return {'id':obj.publisher_id,'title':obj.publisher.name} def get_authors_read(self,obj): ret = [{'id':i.id,'name':i.name} for i in obj.authors.all()] return ret ## 全域性校驗鉤子函式 def validate(self, attrs): # attrs 包含所有欄位的資料 if 'se' in attrs['title']: #如果敏感詞彙在title欄位中則丟擲錯誤 raise serializers.ValidationError('含有敏感詞彙') # 否則返回原資訊 return attrs # 區域性校驗鉤子函式validate_+欄位名 def validate_title(self, data): if 'se' in data: raise serializers.ValidationError('含有敏感詞彙') return data # 序列化器的元資訊 class Meta: # 繫結的資料表model model=Book #要展示的表的欄位 fields = '__all__' # depth = 1 # depth 讓你所有的外來鍵關係變成read_only=True,不建議使用 # 額外要新增的欄位的屬性引數 extra_kwargs = { 'category':{'write_only':True}, 'publisher': {'write_only': True}, 'authors':{'write_only':True}, }
路由以及檢視函式部分
from django.conf.urls import url
from SerDemo.views import BooklistView,EditBookView
urlpatterns = [
# 展示書籍資訊路由
url(r'^booklist/',BooklistView.as_view()),
#編輯書籍路由,接受id引數
url(r'^editbook/(?P<id>\d+)/',EditBookView.as_view())
]
檢視部分
展示所有書籍資料和新增資料檢視,
class BooklistView(ListCreateModelMixin): #get 請求傳送所有資料給前端 def get(self, request): # 獲取資料庫中所有資料物件 query_set = Book.objects.all() # 將queryset物件傳給序列化器例項化,many=True告訴序列化器這是多個物件 ser_obj = BookSerializer(query_set, many=True) # 所有要顯示的資料都在ser_obj.data中用restframe的Response返回 return Response(ser_obj.data) # post請求為新增資料 def post(self, request): # 序列化前端傳過來的資料(request.data) ser_obj = BookSerializer(data=request.data) # 校驗各欄位資料是否符合要求 if ser_obj.is_valid(): ser_obj.save() return Response(ser_obj.data) else: return Response(ser_obj.errors)
編輯資料和刪除書籍部分
class EditBookView(UpdateDestroyModelMixin):
# 展示當前要編輯的資料物件
def get(self, request, id):
#根據url中的id引數獲取要編輯資料物件
book_obj = Book.objects.filter(id=id).first()
if book_obj:
# 返回給前端頁面
ser_obj = BookSerializer(book_obj)
return Response(ser_obj.data)
return Response('沒有')
#put請求對應修改資料
def put(self, request, id):
#根據url中的id引數獲取要編輯資料物件
book_obj = Book.objects.filter(id=id).first()
if book_obj:
#將前端提交的資料和要修改的物件傳給序列化器partial=True允許只修改部分欄位資料
ser_obj = BookSerializer(data=request.data, instance=book_obj, partial=True)
if ser_obj.is_valid():
ser_obj.save()
return Response(ser_obj.data)
else:
return Response(ser_obj.errors)
def delete(self,request,id):
book_obj = Book.objects.filter(id=id).first()
if book_obj:
book_obj.delete()
return Response('')
return Response('沒有次物件')
模仿djngo restframe原始碼封裝各個方法
from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
import json
from SerDemo.models import Author, Publisher, Book
from django import views
from rest_framework import serializers
from rest_framework.views import APIView
from rest_framework.response import Response
from SerDemo.serializers import BookSerializer
# 把每個方法抽離出來
class GenericAPIView(APIView):
query_set = None
serializer_class = None
def _get_queryset(self):
return self.query_set
def _get_serializer(self,*args,**kwargs):
return self.serializer_class(*args,**kwargs)
class ListModelMixin:
def list(self):
query_set = self._get_queryset().all()
ser_obj = self._get_serializer(query_set, many=True)
return Response(ser_obj.data)
class CreateModelMixin:
def create(self,request):
ser_obj = self._get_serializer(data=request.data)
if ser_obj.is_valid():
ser_obj.save()
return Response(ser_obj.data)
else:
return Response(ser_obj.errors)
class RetrieveModelMixin:
def retrieve(self,id):
book_obj = self._get_queryset().filter(id=id).first()
if book_obj:
ser_obj = self._get_serializer(book_obj)
return Response(ser_obj.data)
return Response('沒有')
class UpdateModelMixin:
def update(self,request,id):
book_obj = self._get_queryset().filter(id=id).first()
if book_obj:
ser_obj = self._get_serializer(data=request.data, instance=book_obj, partial=True)
if ser_obj.is_valid():
ser_obj.save()
return Response(ser_obj.data)
else:
return Response(ser_obj.errors)
class DestroyModelMixin:
def destroy(self,id):
book_obj = self._get_queryset().filter(id=id).first()
if book_obj:
book_obj.delete()
return Response('')
return Response('沒有次物件')
class ListCreateModelMixin(GenericAPIView,ListModelMixin, CreateModelMixin):
pass
class UpdateDestroyModelMixin(GenericAPIView,DestroyModelMixin,UpdateModelMixin,RetrieveModelMixin):
pass
class BooklistView(ListCreateModelMixin):
query_set = Book.objects.all()
serializer_class = BookSerializer
def get(self, request):
# query_set = Book.objects.all()
# ser_obj = BookSerializer(query_set, many=True)
# return Response(ser_obj.data)
return self.list()
def post(self, request):
# ser_obj = BookSerializer(data=request.data)
# if ser_obj.is_valid():
# ser_obj.save()
# return Response(ser_obj.data)
# else:
# return Response(ser_obj.errors)
return self.create(request)
class EditBookView(UpdateDestroyModelMixin):
query_set = Book.objects.all()
serializer_class = BookSerializer
def get(self, request, id):
# book_obj = Book.objects.filter(id=id).first()
# if book_obj:
# ser_obj = BookSerializer(book_obj)
# return Response(ser_obj.data)
# return Response('沒有')
return self.retrieve(id)
def put(self, request, id):
# book_obj = Book.objects.filter(id=id).first()
# if book_obj:
# ser_obj = BookSerializer(data=request.data, instance=book_obj, partial=True)
# if ser_obj.is_valid():
# ser_obj.save()
# return Response(ser_obj.data)
# else:
# return Response(ser_obj.errors)
return self.update(request,id)
def delete(self,request,id):
# book_obj = Book.objects.filter(id=id).first()
# if book_obj:
# book_obj.delete()
# return Response('')
# return Response('沒有次物件')
return self.destroy(id)