drf考试题目,及解题代码

考试

1 有车型(CarModel),车厂(CarFactory),经销商(Distributor)三个表,一个车厂可以生产多种车型,一个经销商可以出售多种车型,一个车型可以有多个经销商出售
  车型:车型名,车型出厂价,车厂id
  车厂:车厂名,车厂地址,联系电话
  经销商:经销商名,地址,联系电话
2 有用户表,基于django内置user表,扩展mobile字段

3 编写登陆接口,jwt方式返回token,
	格式为{status:100,msg:登陆成功,token:safasdfa}

3 只有管理员登陆后可以新增,修改,删除(车型,车厂,经销商)

2 普通用户登陆可以查看车型(群查所有的都要有分页,单查)

	注:查车型:返回车型名字价格,车厂名字与地址,经销商名字和电话

加分项:
用户注册接口
管理员有用户锁定,删除功能

.
.

# 模型表代码
from django.db import models
from django.contrib.auth.models import AbstractUser


# Create your models here.

class UserInfo(AbstractUser):
    mobile = models.BigIntegerField(verbose_name='手机号', null=True, blank=True)


class CarModel(models.Model):
    name = models.CharField(max_length=32)
    price = models.IntegerField()
    factory = models.ForeignKey(to='CarFactory', on_delete=models.CASCADE, null=True, blank=True)

    distributors = models.ManyToManyField(to='Distributor')

    @property
    def factory_detail(self):
        return {'name': self.factory.name, 'addr': self.factory.addr}

    @property
    def distribute_detail(self):
        return [{'name': distributor.name, 'phone': distributor.phone} for distributor in self.distributors.all()]


class CarFactory(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)
    phone = models.BigIntegerField()


class Distributor(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)
    phone = models.BigIntegerField()

.
.
纯手动,烦一点的写法

路由层代码
from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import SimpleRouter
from app01 import views


router = SimpleRouter()
router.register('user', views.UserView, 'user')
# token签发也就是登录自己写视图类来完成

# 查车
router.register('set_car', views.SetCarView, 'set_car')
router.register('search_car', views.SearchCarView, 'search_car')

# 查经销商
router.register('set_distributor', views.SetDistributorView, 'c_d_distributor')
router.register('search_distributor', views.SearchDistributorView, 'search_distributor')

# 查工厂
router.register('set_factory', views.SetFactoryView, 'c_d_factory')
router.register('search_factory', views.SearchFactoryView, 'search_factory')

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

]

--------------------------------------------------
# 视图层代码
from rest_framework.decorators import action
from app01.models import UserInfo, CarModel, CarFactory, Distributor
from rest_framework_jwt.settings import api_settings

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
jwt_decode_handler = api_settings.JWT_DECODE_HANDLER
from rest_framework.response import Response
from django.contrib import auth
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin
from rest_framework.generics import DestroyAPIView, RetrieveAPIView
from rest_framework.viewsets import ViewSetMixin, ViewSet, GenericViewSet
from app01.serializer import CarSerializer, FactorySerializer, DistributorSerializer


class UserView(ViewSet):
    @action(methods=['POST'], detail=False)
    def login(self, request, *args, **kwargs):
        username = request.data.get('username')
        password = request.data.get('password')
        user_obj = auth.authenticate(request, username=username, password=password)
        if user_obj:
            # 通过user_obj 得到payload
            payload = jwt_payload_handler(user_obj)
            # 生成token
            token = jwt_encode_handler(payload)
            return Response({'status': 1000, 'msg': '登录成功', 'token': token})
        else:
            return Response({'status': 1001, 'msg': '用户名或密码错误'})


from app01.authentication import JsonWebTokenAuthentication
from app01.page import CommonPageNumberPagination
from app01.permissions import CommonPermission

# 删车,新增车,修改车
class SetCarView(ViewSetMixin, DestroyAPIView, CreateModelMixin, UpdateModelMixin):
    queryset = CarModel.objects.all()
    serializer_class = CarSerializer
    # token认证,兼确认请求头里面有没有带token
    authentication_classes = [JsonWebTokenAuthentication]
    # 是否是管理员权限认证,如果不是没有权限执行该视图类下的接口函数
    permission_classes = [CommonPermission]


# 查单个,查所有,只要登录了就行了
class SearchCarView(ViewSetMixin, RetrieveAPIView, ListModelMixin):
    # token认证
    authentication_classes = [JsonWebTokenAuthentication]

    queryset = CarModel.objects.all()
    serializer_class = CarSerializer
    # 再加个分页功能
    pagination_class = CommonPageNumberPagination


# 删厂,新增厂,修改厂
class SetFactoryView(ViewSetMixin, DestroyAPIView, CreateModelMixin, UpdateModelMixin):
    authentication_classes = [JsonWebTokenAuthentication]
    permission_classes = [CommonPermission]

    queryset = CarFactory.objects.all()
    serializer_class = FactorySerializer


# 查单个,查所有
class SearchFactoryView(ViewSetMixin, RetrieveAPIView, ListModelMixin):
    # token认证
    authentication_classes = [JsonWebTokenAuthentication]

    queryset = CarFactory.objects.all()
    serializer_class = FactorySerializer
    # 再加个分页功能
    pagination_class = CommonPageNumberPagination


# 删,新增,修改经销商
class SetDistributorView(ViewSetMixin, DestroyAPIView, CreateModelMixin, UpdateModelMixin):
    authentication_classes = [JsonWebTokenAuthentication]
    permission_classes = [CommonPermission]

    queryset = Distributor.objects.all()
    serializer_class = DistributorSerializer


# 查单个,查所有
class SearchDistributorView(ViewSetMixin, RetrieveAPIView, ListModelMixin):
    # token认证
    authentication_classes = [JsonWebTokenAuthentication]

    queryset = Distributor.objects.all()
    serializer_class = DistributorSerializer
    # 再加个分页功能
    pagination_class = CommonPageNumberPagination

--------------------------------------------------
--------------------------------------------------

# 序列化类代码如下:
from rest_framework import serializers
from app01.models import UserInfo, CarModel, CarFactory, Distributor

class CarSerializer(serializers.ModelSerializer):
    class Meta:
        model = CarModel

        fields = ['id', 'name', 'price', 'factory', 'distributors', 'factory_detail', 'distribute_detail']

        extra_kwargs = {
            'factory_detail': {'read_only': True},
            'distribute_detail': {'read_only': True},

            'factory': {'write_only': True},
            'distributors': {'write_only': True}
        }


class FactorySerializer(serializers.ModelSerializer):
    class Meta:
        model = CarFactory
        fields = ['id', 'name', 'addr', 'phone']


class DistributorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Distributor
        fields = ['id', 'name', 'addr', 'phone']

--------------------------------------------------
--------------------------------------------------

# 自定义登录认证类代码

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
import jwt
from rest_framework_jwt.utils import jwt_decode_handler
from app01.models import UserInfo


class JsonWebTokenAuthentication(BaseAuthentication):
    def authenticate(self, request):
        # 取出token
        token = request.META.get('HTTP_TOKEN')

        if token:
            try:
                payload = jwt_decode_handler(token)  # 重点代码 用token获取荷载

                user_obj = UserInfo.objects.get(pk=payload.get('user_id'))
                # 得到当前用户对象,get是filter与first的结合,但是如果拿不到直接报错

            # 只要访问一次登录接口,就会去Userinfo表中查一次用户---优化操作
                # user_obj = Userinfo(id=payload.get('user_id'),username=payload.get('username'))
                # 或者user_obj={'id':payload.get('user_id')}
                return user_obj,token

            except jwt.ExpiredSignature:
                raise AuthenticationFailed('token过期')

            except jwt.DecodeError:
                raise AuthenticationFailed('token认证失败')

            except jwt.InvalidTokenError:
                raise AuthenticationFailed('token无效')
            except Exception as e:
                raise AuthenticationFailed('未知错误')

        raise AuthenticationFailed('token没有传,认证失败')

---------------------------------------------
# 自己写的权限类,新建个permissions.py文件  代码如下:
# 是超级管理员就有权限执行,不是就没有权限执行视图函数

from rest_framework.permissions import BasePermission

class CommonPermission(BasePermission):
    def has_permission(self, request, view):
        if request.user.is_superuser == 1:
            return True
        else:
            self.message = '您没有权限'
            return False

---------------------------------------------
---------------------------------------------

# 自定义分页类
from rest_framework.pagination import PageNumberPagination

class CommonPageNumberPagination(PageNumberPagination):
    page_size = 2  # 每页显示2条
    page_query_param = 'page'  # page = 10   查询第10页的数据,每页显示2条
    page_size_query_param = 'size'  # 定制每页显示条数的参数 page=2&size=3  每页显示3条,并查询第10页的数据,不写&size=3就还是每页显示2条
    max_page_size = 4  # 每页最大显示4条,上面定制的page=2&size=5 就变成了 每页显示4条 查询第10页的数据

---------------------------------------------
# 配置文件代码

import datetime
JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),  # token过期时间
}
---------------------------------------------

.
.
.
.
.
.

# 全自动,不用写登录接口签发token,也不要写自定义认证类来校验请求头带的token是否正确
# 自定义权限类换一种方法来写,原来只判断是不是超级管理员,如果不是,就直接返回false,
# 就没有权限执行视图类里面对应的函数了,那么也就必须要把增删改 与查单个查所有
# 分到两个视图类里面来写,
# 现在在权限类里面,判断完是不是超级管理员后,如果不是再继续判断是不是get请求,
# 如果是也返回true,最后else返回false
# 这样就可以写在一个视图类里面了

.
.

-----------------------------------------------
# 路由层代码

from django.contrib import admin
from django.urls import path
from app01 import views
from rest_framework_jwt.views import obtain_jwt_token
from rest_framework.routers import SimpleRouter

router = SimpleRouter()
router.register('user', views.UserView, 'user')  # /user/login--->post请求

router.register('car_model', views.CarModelView, 'car_model')
router.register('car_factory', views.CarFactoryView, 'car_factory')
router.register('distributor', views.DistributorView, 'distributor')
urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', obtain_jwt_token),  # 基于auth表及扩展表,快速签发token
]

urlpatterns += router.urls

# 登录签发token接口视图类不用写了
-----------------------------------------------
-----------------------------------------------
# 对于快速签发的token的返回格式可以设置一下
配置里面
JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.utils.jwt_response_payload_handler',
}

创一个utils.py文件
def jwt_response_payload_handler(token, user=None, request=None):
    return {
        'status': 100,
        'msg': '登录成功',
        'username':user.username,
        'token': token,
    }

-----------------------------------------------
-----------------------------------------------

# 视图层代码 车,厂,经销商 都只需要一个视图类

from rest_framework.viewsets import ModelViewSet   # 用它5个接口全有了
from .serializer import *
from .page import MyPageNumberPagination     # 自定义分页类
from rest_framework.permissions import IsAuthenticated
from rest_framework_jwt.authentication import JSONWebTokenAuthentication  # 自带的
from .permission import AdminPermission  # 自定义权限类
from rest_framework_jwt.settings import api_settings

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER  # 定义token的返回格式用的
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

# 类名都是驼峰
# 函数名,方法名,变量名,文件名用下划线


class CarModelView(ModelViewSet):
    authentication_classes = [JSONWebTokenAuthentication]
    permission_classes = [IsAuthenticated, AdminPermission]
    queryset = CarModel.objects.all()
    serializer_class = CarModelSerializer
    pagination_class = MyPageNumberPagination  # 分页类


class CarFactoryView(ModelViewSet):
    authentication_classes = [JSONWebTokenAuthentication]
    permission_classes = [IsAuthenticated, AdminPermission]
    queryset = CarFactory.objects.all()
    serializer_class = CarFactorySerializer
    pagination_class = MyPageNumberPagination  # 分页类

class DistributorView(ModelViewSet):
    authentication_classes = [JSONWebTokenAuthentication]
    permission_classes = [IsAuthenticated, AdminPermission]
    queryset = Distributor.objects.all()
    serializer_class = DistributorSerializer
    pagination_class = MyPageNumberPagination  # 分页类

# 用jet自带的认证类,就必须要配合django自带的确认是否登录的权限类一起用
# 因为jwt自带的认证类,对于请求不带token的直接就让过了,
# 所以要用IsAuthenticated权限类,再确认请求是否没带token
-----------------------------------------------
-----------------------------------------------

# 权限类,代码

from rest_framework.permissions import BasePermission

class AdminPermission(BasePermission):
    def has_permission(self, request, view):
        if request.user.is_superuser:
            return True
        else:
            # 不是超级用户,只能访问get
            if request.method == 'GET':
                return True
            else:
                return False
-----------------------------------------------

序列化类和纯手动的一样的代码,分页类代码也是一样

-----------------------------------------------
posted @   tengyifan  阅读(55)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示