【2022-10-08】 DRF从入门到入土(六)

drf之路由组件

自动生成路由

# drf提供了两个路由类,只要继承了ViewSetMixin及其子类的视图类,就可以使用这两个路由类来自动生成路由

# 使用步骤如下:
    1 导入模块:from rest_framework.routers import SimpleRouter, DefaultRouter
    2 实例化对象:router = SimpleRouter()
    3 注册路由:router.register('user',views.UserView,'user')    # 第一个参数是路径,第二个参数是视图类,第三个参数是别名,可以注册多个哦
    4 添加到urlpatterns中(有两种方式)
        urlpatterns+=router.urls
        path('', include(router.urls)),

    
# SimpleRouter和DefaultRouter
	DefaultRouter比SimpleRouter多一个根路径,显示所有注册过的路由

action装饰器

# 在视图函数中,会有一些其它名字的方法,必须要使用action装饰器做映射
    # methods:支持的请求方式,列表
    # detail:默认是False 控制生成的路由是 /user/login/ 还是 /user/pk/login  如果值是True则带pk,反之则不带
    # url_path: 控制生成的/user/后面的路径是什么,如果不写,默认以方法名命名   /user/login/,一般跟函数名同名即可
    # url_name:别名,用于反向解析
    	
    @action(methods=['GET','POST'], detail=True, url_path='login')
    def login(self, request,pk):

# 这样写了以后可以:自动生成路由

drf之认证组件

创建认证类

# 通过认证类完成用户登录认证,使用步骤如下:
	1 写一个认证类,继承BaseAuthentication
    2 重写authenticate方法,在内部做认证
    3 如果认证通过,返回2个值
    4 认证不通过抛AuthenticationFailed异常
    5 只要返回了两个值,在后续的request.user 就是当前登录用户
    6 如果想让某个视图类登录后才能访问
    	-方式一:局部配置
        	class BookView(ModelViewSet):
    			authentication_classes = [LoginAuth,]
                
        -方式二:全局配置
        	REST_FRAMEWORK={
            'DEFAULT_AUTHENTICATION_CLASSES':['app01.auth.LoginAuth',]
        }
            
         -局部禁用:
        	authentication_classes = []

代码示例

from rest_framework.authentication import BaseAuthentication
from .models import BookToken
from rest_framework.exceptions import AuthenticationFailed


class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        token = request.GET.get('token')
        book_token = BookToken.objects.filter(token=token).first()
        if book_token:
            return book_token.book, token
        else:
            raise AuthenticationFailed('您还没有进行认证,请认证后进行登录')

自主练习

登录接口编写

urls.py
from django.contrib import admin
from django.urls import path, include
from app01 import views
from rest_framework.routers import SimpleRouter

router = SimpleRouter()
router.register('user', views.UserView, 'user')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(router.urls)),
]

models.py
from django.db import models


# Create your models here.


class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)

    def __str__(self):
        return self.username


class UserToken(models.Model):
    user = models.OneToOneField(to='User', on_delete=models.CASCADE)
    token = models.CharField(max_length=32, null=True)

views.py
from django.shortcuts import render
from rest_framework.viewsets import ViewSet
from rest_framework.decorators import action
from .models import User, UserToken
import uuid
from rest_framework.response import Response


# Create your views here.


class UserView(ViewSet):

    @action(methods=['POST', ], detail=False, url_path='login')
    def login(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        user = User.objects.filter(username=username, password=password).first()
        if user:
            token = str(uuid.uuid4())  
            UserToken.objects.update_or_create(defaults={'token': token}, user=user)
            return Response({'code': 100, 'msg': '登录成功', 'token': token})
        else:
            return Response({'code': 101, 'msg': '用户名或密码错误'})

验证

图书和出版社接口编写

urls.py
from django.contrib import admin
from django.urls import path, include
from app01 import views


urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>', views.BookDetailView.as_view()),
    path('publish/', views.PublishView.as_view()),
    path('publish/<int:pk>', views.PublishDetailView.as_view()),
]

models.py
from django.db import models


class Book(models.Model):
    "书籍表"
    book_name = models.CharField(max_length=32)
    book_price = models.CharField(max_length=32)
    book_publish = models.CharField(max_length=32)

    def __str__(self):
        return self.book_name


class Publish(models.Model):
    "出版社表"
    publish_name = models.CharField(max_length=32)
    publish_address = models.CharField(max_length=128)
    book = models.ForeignKey(to='Book', on_delete=models.CASCADE)

    def __str__(self):
        return self.publish_name


class BookToken(models.Model):
    book = models.ForeignKey(to='Book', on_delete=models.CASCADE)
    token = models.CharField(max_length=32, null=True)

serializer.py
from rest_framework import serializers
from .models import Book, Publish


class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'


class PublishModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Publish
        fields = '__all__'

views.py
from django.shortcuts import render

from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
from .models import Book, Publish
from .serializer import BookModelSerializer, PublishModelSerializer
from rest_framework.viewsets import ViewSet


class BookView(ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer


class BookDetailView(RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer


class PublishView(ListCreateAPIView):

    authentication_classes = []
    queryset = Publish.objects.all()
    serializer_class = PublishModelSerializer


class PublishDetailView(RetrieveUpdateDestroyAPIView):
    authentication_classes = []
    queryset = Publish.objects.all()
    serializer_class = PublishModelSerializer

auth.py
from rest_framework.authentication import BaseAuthentication
from .models import BookToken
from rest_framework.exceptions import AuthenticationFailed


class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        token = request.GET.get('token')
        book_token = BookToken.objects.filter(token=token).first()
        if book_token:
            return book_token.book, token
        else:
            raise AuthenticationFailed('您还没有进行认证,请认证后进行登录')

settings.py
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': ['app01.auth.LoginAuth', ]
}
验证

级联删除的其他字段参数

1、models.CASCADE
    级联操作,当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时被删除
2、models.SET_NULL
    当主表中的一行数据删除时,从表中所有与之关联的数据的相关字段设置为null,此时注意定义外键时,这个字段必须可以允许为空
3、models.PROTECT
    当主表中的一行数据删除时,由于从表中相关字段是受保护的外键,所以都不允许删除
4、models.SET_DEFAULT
    当主表中的一行数据删除时,从表中所有相关的数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值
5、models.SET()
    当主表中的一条数据删除时,从表中所有的关联数据字段设置为SET()中设置的值,与models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数
6、models.DO_NOTHING
    什么都不做,一切都看数据库级别的约束,注数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似
posted @   dy12138  阅读(53)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示