Day 89 Django_视图封装 & 路由 & 版本控制组件
视图封装
model.py 文件
from django.db import models # Create your models here. class Book(models.Model): title = models.CharField(max_length=32, verbose_name='图书名称') CHOICES = ((1, 'Java'), (2, 'MySQL'), (3, 'Python'),) category = models.IntegerField(choices=CHOICES, verbose_name='图书分类') pub_time = models.DateField(verbose_name='出版社日期') publisher = models.ForeignKey(to='Publisher',on_delete=callable,db_constraint=False) author = models.ManyToManyField(to='Author') def __str__(self): return self.title class Meta: verbose_name_plural = '01_图书表' db_table = verbose_name_plural class Publisher(models.Model): title = models.CharField(max_length=32,verbose_name='出版社信息') def __str__(self): return self.title class Meta: verbose_name_plural = '02_出版社表' db_table = verbose_name_plural class Author(models.Model): Author_name = models.CharField(max_length=32, verbose_name='作者') def __str__(self): return self.Author_name class Meta: verbose_name_plural = '03_作者表' db_table = verbose_name_plural
urls.py 文件
from django.urls import path, include from .views import BookView, BookEditView, BookTwoEditView urlpatterns = [ path('list',BookView.as_view()), path('EditBook/<int:id>',BookEditView.as_view()) # path('list', BookTwoEditView.as_view({"get": "list", "post": "create"})), # path('EditBook/<int:id>', BookTwoEditView.as_view({"get": "retrieve", "put": "edit_View", "delete": "eidt_delete"})) ]
serializers.py 文件
from rest_framework import serializers from .models import Book class BookSerializer(serializers.ModelSerializer): category_display = serializers.SerializerMethodField(read_only=True) publisher_info = serializers.SerializerMethodField(read_only=True) authors = serializers.SerializerMethodField(read_only=True) def get_category_display(self, obj): return obj.get_category_display() # 通过自定义 get_publisher 与 get_author 来获取我们想要的指定字段 def get_publisher_info(self, obj): # obj 是我们序列化的每个 Book 对象 publisher_obj = obj.publisher return {"id": publisher_obj.id, "title": publisher_obj.title} def get_authors(self, obj): author_obj = obj.author.all() return [{'id': author.id, 'Author_name': author.Author_name} for author in author_obj] class Meta: model = Book # fields = ['id','title','pub_time'] # 拿到指定信息 fields = '__all__' # 拿到所有信息,但存在关联字段 id 信息,不利于阅读,需要单独处理 # depth = 1 # 获取关联表中的字段,数字代表 深度,但这样回取出所有数据 # extra_kwargs 添加字段的属性信息 extra_kwargs = {"category": {"write_only": True}, "publisher": {"write_only": True}, "author": {"write_only": True}}
views.py 文件
from .models import Book, Publisher from .serializers import BookSerializer from rest_framework.views import APIView from rest_framework.response import Response class GenericAPIView(APIView): query_set = None serializers_class = None def get_queryset(self): return self.query_set def get_serializer(self, *args, **kwargs): return self.serializers_class(*args, **kwargs) class GetListModelMixin(object): def list(self, request): queryset = self.get_queryset() ret = self.get_serializer(queryset, many=True) return Response(ret.data) class PostCreateModeMixin(object): def create(self, request): serializers = self.get_serializer(data=request.data) if serializers.is_valid(): serializers.save() return Response(serializers.data) else: return Response(serializers.errors) class RetrieveModeMixin(object): def retrieve(self, request, id): book_obj = self.get_queryset().filter(id=id).first() ret = self.get_serializer(book_obj) return Response(ret.data) class EditViewModeMixin(object): def edit_View(self, request, id): book_obj = self.get_queryset().filter(id=id).first() ret = self.get_serializer(book_obj, data=request.data, partial=True) # partial 是否允许部分更新 if ret.is_valid(): ret.save() return Response(ret.data) else: return Response(ret.errors) class EditDeleteModeMixin(object): def eidt_delete(self, request, id): book_obj = self.get_queryset().filter(id=id).first() book_obj.delete() return Response('已删除') class BookViewListClass(GenericAPIView, GetListModelMixin, PostCreateModeMixin): pass class BookView(BookViewListClass): # 继承 GenericAPIView 这个通用类 query_set = Book.objects.all() serializers_class = BookSerializer def get(self, request): return self.list(request) # Post 请求 def post(self, request): return self.create(request) class BookEditListClass(GenericAPIView, RetrieveModeMixin, EditViewModeMixin, EditDeleteModeMixin): pass class BookEditView(BookEditListClass): query_set = Book.objects.all() serializers_class = BookSerializer def get(self, request, id): return self.retrieve(request, id) def put(self, request, id): return self.edit_View(request, id) def delete(self, request, id): return self.eidt_delete(request, id)
使用路由传参实现用一个视图完成该功能
urls.py 文件,实现路由传参 views.py 中类必须继承 ViewSetMixin
from django.urls import path, include from .views import BookView, BookEditView, BookTwoEditView urlpatterns = [ # path('list',BookView.as_view()), # path('EditBook/<int:id>',BookEditView.as_view()) path('list', BookTwoEditView.as_view({"get": "list", "post": "create"})), path('EditBook/<int:id>', BookTwoEditView.as_view({"get": "retrieve", "put": "edit_View", "delete": "eidt_delete"})) ]
views.py 文件,新建类继承 ViewSetMixin
from rest_framework.viewsets import ViewSetMixin # 框架提供的类 所在包位置 from rest_framework.viewsets import ModelViewSet # 这个是框架提供的 ManyViewClass 类 from rest_framework import views from rest_framework import generics from rest_framework import mixins from rest_framework import viewsets class ManyViewClass(ViewSetMixin, GenericAPIView, GetListModelMixin, PostCreateModeMixin, RetrieveModeMixin, EditViewModeMixin, EditDeleteModeMixin): pass class BookTwoEditView(ManyViewClass): query_set = Book.objects.all() serializers_class = BookSerializer
DRF 路由组件
from rest_framework.routers import DefaultRouter
版本控制组件介绍
settings.py 文件,新增 REST_FRAMEWORK 参数,使用 rest_framework.versioning.QueryParameterVersioning
REST_FRAMEWORK = { # "DEFAULT_VERSIONING_CLASS": "utils.version.MyVersion", "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.QueryParameterVersioning", "DEFAULT_VERSION": "v1", "ALLOWED_VERSIONS": "v1, v2", "VERSION_PARAM": "ver" }
urls.py 文件
from django.urls import path,include from .views import DomeView urlpatterns = [ path(r'',DomeView.as_view()), ]
views.py 文件
from rest_framework.views import APIView from rest_framework.response import Response class DomeView(APIView): def get(self,request): print(request.version) print(request.versioning_scheme) if request.version == 'v1': return Response('V1 版本') if request.version == 'v2': return Response('V2 版本') return Response('测试版本')
认证组件
认证组件的方法都在:import rest_framework.authentication
models.py
from django.db import models # Create your models here. from django.db import models class User(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=32) token = models.UUIDField()
urls.py
from django.urls import path,include from .views import authDome,LoginDome,TestDome urlpatterns = [ path(r'',authDome.as_view()), path(r'login',LoginDome.as_view()), path(r'test',TestDome.as_view()), ]
views.py
import uuid # Create your views here. from rest_framework.views import APIView from rest_framework.response import Response from utils.auth import MyAuth from .models import User class authDome(APIView): def get(self,request): return Response('认证视图') class LoginDome(APIView): def post(self,request): username = request.data.get('username') password = request.data.get('password') token = uuid.uuid4() User.objects.create(username=username,password=password,token=token) return Response('创建成功') class TestDome(APIView): # 局部视图配置 在需要做验证的类中配置 authentication_class = [MyAuth,] def get(self,request): print(request.user) print(request.auth) return Response('认证测试')
auth.py 认证文件
from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from authDome.models import User class MyAuth(BaseAuthentication): def authenticate(self,request): token = request.query_params.get("token","") if not token: raise AuthenticationFailed("没有携带 token") user_obj = User.objects.filter(token=token).first() if not user_obj: raise AuthenticationFailed("携带的 token 不合法") return (user_obj,token)
权限组件
权限组件的方法都在:import rest_framework.permissions
新建 permission.py 文件
from rest_framework.permissions import BasePermission class MyPermission(BasePermission): message = '没有权限' def has_permission(self, request, view): # 判断用户是否有权限 user_obj = request.user if user_obj.type == 3: return False else: return True
models.py 文件
from django.db import models class User(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=32) token = models.UUIDField() type = models.IntegerField(choices=((1, "vip"), (2, "VVIP"), (3, "普通用户"),), default=3)
views.py 文件
from django.shortcuts import render import uuid # Create your views here. from rest_framework.views import APIView from rest_framework.response import Response from utils.auth import MyAuth from utils.permission import MyPermission from .models import User class authDome(APIView): def get(self,request): return Response('认证视图') class LoginDome(APIView): def post(self,request): username = request.data.get('username') password = request.data.get('password') token = uuid.uuid4() User.objects.create(username=username,password=password,token=token) return Response('创建成功') class TestDome(APIView): # 局部视图配置 在需要做验证的类中配置 authentication_classes = [MyAuth, ] permission_classes = [MyPermission, ] # 添加权限类 def get(self,request): print(request.user) print(request.auth) return Response('认证测试')
频率接口