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
model.py

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"}))
]
urls.py

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}}
serializers.py

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)
views.py

 

使用路由传参实现用一个视图完成该功能

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"}))
]
urls.py

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
views.py

 

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"
}
settings.py

urls.py 文件

from django.urls import path,include
from .views import DomeView

urlpatterns = [
    path(r'',DomeView.as_view()),
]
urls.py

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('测试版本')
views.py

 

认证组件

认证组件的方法都在: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()
models.py

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()),
]
urls.py

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('认证测试')
views.py

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)
auth.py

 

权限组件

权限组件的方法都在: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
permission.py

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)
models.py

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('认证测试')
views.py

 

频率接口

 

posted @ 2023-02-10 19:50  亦双弓  阅读(29)  评论(0编辑  收藏  举报