drf 测试(车型、车场、经销商)
一、实现要求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 1 有车型(CarModel),车厂(CarFactory),经销商(Distributor)三个表,一个车厂可以生产多种车型,一个经销商可以出售多种车型,一个车型可以有多个经销商出售 车型:车型名,车型出厂价,车厂 id 车厂:车厂名,车厂地址,联系电话 经销商:经销商名,地址,联系电话 2 有用户表,基于django内置user表,扩展mobile字段 3 编写登陆接口,jwt方式返回token, 格式为{status: 100 ,msg:登陆成功,token:safasdfa} 4 所有接口(除登录外),必须登录后才能访问 5 管理员登陆后可以增,删,单查,群查,改 车型,车厂,经销商(具备所有接口权限) 6 普通用户登陆可以查看车型,车厂,经销商单条,所有(只有查看权限) 7 所有查询所有接口带分页功能 8 查询所有车型接口,可以按车型名字精准过滤 加分项: 用户注册接口 管理员有用户锁定,删除用户功能 |
注:
根据信息提取出表关系:车型和车场:一对多,车型和经销商:多对多
Models:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): mobile = models.IntegerField(null = True ) # 车型表 class CarModel(models.Model): carmodel_name = models.CharField(max_length = 64 ) carfact_price = models.IntegerField(null = True ) carfact = models.ForeignKey(to = 'CarFactory' , on_delete = models.CASCADE, null = True ) distributor = models.ManyToManyField(to = 'Distributor' , null = True ) # 定义返回字段 # 车场信息 def factory_info( self ): return { 'name' : self .carfact.carfact_name, 'addr' : self .carfact.carfact_addr, 'phone' : self .carfact.carfact_phone} # 经销商信息 def dealers_info( self ): dealers_info_list = [] for dealer in self .distributor. all (): dealers_info_list.append({ 'name' : dealer.dist_name, 'addr' : dealer.dist_addr, 'phone' : dealer.dist_phone}) # 车厂表 class CarFactory(models.Model): carfact_name = models.CharField(max_length = 64 ) carfact_addr = models.CharField(max_length = 64 ) carfact_phone = models.IntegerField(null = True ) # 经销商表 class Distributor(models.Model): dist_name = models.CharField(max_length = 64 ) dist_addr = models.CharField(max_length = 64 ) dist_phone = models.IntegerField(null = True ) |
views视图类导入模块汇总
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | from rest_framework.response import Response from rest_framework_jwt.settings import api_settings from django.contrib.auth import authenticate from rest_framework.viewsets import ViewSet, ModelViewSet from rest_framework.generics import GenericAPIView from rest_framework.mixins import CreateModelMixin, DestroyModelMixin from .models import CarModel, CarFactory, Distributor from .serializer import CarModelSerializer, CarFactorySerializer, DistributorSerializer, UserSerializer from .page import CommonPageNumberPagination from django_filters.rest_framework import DjangoFilterBackend from rest_framework.permissions import IsAuthenticated, IsAdminUser from rest_framework_jwt.authentication import JSONWebTokenAuthentication from .permissions import UserPermission from .models import User from rest_framework.views import APIView from rest_framework.decorators import action jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER |
二、注册登录接口
1、登录
使用authenticate 方法去比对验证加密后的密码
1 2 3 4 5 6 7 8 9 10 11 | class LoginView(APIView): def post( self , request): username = request.data.get( 'username' ) password = str (request.data.get( 'password' )) user_obj = authenticate(request, username = username, password = password) if user_obj: payload = jwt_payload_handler(user_obj) token = jwt_encode_handler(payload) return Response({ 'status' : 100 , 'msg' : '登录成功' , 'token' : token, 'username' : user_obj.username}) else : return Response({ 'status' : 101 , 'msg' : '用户名或密码错误' }) |
2、注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class UserView(ViewSet, GenericAPIView, CreateModelMixin): # ViewSet =ViewSetMixin + APIView queryset = User.objects. all () serializer_class = UserSerializer def create( self , request, * args, * * kwargs): ser = self .get_serializer(data = request.data) if ser.is_valid(): ser.save() return Response({ 'code' : 100 , 'msg' : '注册成功!' , 'result' : ser.data}) return Response({ 'status' : 101 , 'msg' : '注册失败!' , 'erros' : ser.errors}) ###### class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = [ 'username' , 'password' , 'mobile' ] extra_kwargs = { 'password' : { 'write_only' : True } } def create( self , validated_data): user = User.objects.create_user( * * validated_data) return user |
三、权限管理、分页、JWT、过滤
1、views
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # 车型 class CarModelView(ModelViewSet): queryset = CarModel.objects. all () serializer_class = CarModelSerializer pagination_class = CommonPageNumberPagination # 分页 authentication_classes = [JSONWebTokenAuthentication] # 签发token permission_classes = [IsAuthenticated, UserPermission] # IsAuthenticated 只有token认证通过的可以访问视图。 UserPermission验证用户的权限 filter_backends = [DjangoFilterBackend] # 过滤 filterset_fields = [ 'carmodel_name' , 'carfact_price' ] # 车厂 class CarFactoryView(ModelViewSet): queryset = CarFactory.objects. all () serializer_class = CarFactorySerializer pagination_class = CommonPageNumberPagination # 分页 # authentication_classes = [JSONWebTokenAuthentication] # permission_classes = [IsAuthenticated, UserPermission] filter_backends = [DjangoFilterBackend] # 过滤 filterset_fields = [ 'carfact_name' , 'carfact_phone' ] # 经销商 class DistributorView(ModelViewSet): queryset = Distributor.objects. all () serializer_class = DistributorSerializer pagination_class = CommonPageNumberPagination # 分页 authentication_classes = [JSONWebTokenAuthentication, ] permission_classes = [IsAuthenticated, UserPermission] filter_backends = [DjangoFilterBackend] # 过滤 filterset_fields = [ 'dist_name' , 'dist_phone' ] |
2、分页类
1 2 3 4 5 6 7 8 | from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination class CommonPageNumberPagination(PageNumberPagination): # 重写几个类属性 page_size = 3 # 每页显示多少条 page_query_param = 'page' # 指定第几页的key值 http://127.0.0.1:8000/books/?page=3 page_size_query_param = 'size' # 可以指定每页显示多少条 size=300000 max_page_size = 5 |
3、自定义的认证类
判断用户的角色和请求方法,普通用户只能有查看单条和查看所有的权限
1 2 3 4 5 6 7 8 | from rest_framework.permissions import BasePermission from rest_framework.exceptions import AuthenticationFailed class UserPermission(BasePermission): def has_permission( self , request, view): if not request.user.is_superuser and request.method ! = 'GET' : # 如果是普通用户,只能查看所有或者单条,没修改、更新、创建权限 raise AuthenticationFailed( 'You must be a superuser' ) return True |
四、管理员有用户锁定,删除用户功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | # 管理员有用户锁定,删除用户功能 class AdminView(ViewSet, GenericAPIView, DestroyModelMixin): queryset = User.objects. all () authentication_classes = [JSONWebTokenAuthentication] permission_classes = [IsAuthenticated, IsAdminUser] # IsAdminUser普通用户不能使用这个接口 @action (methods = [ 'DELETE' ], detail = True ) # 重写于DestroyModelMixin的delete方法 def delete_user( self , request, * args, * * kwargs): return self .destroy(request, * args, * * kwargs) @action (methods = [ 'GET' ], detail = True ) def lock( self , request, * args, * * kwargs): user = self .get_object() if user is None : return Response({ 'status' : 101 , 'msg' : '用户不存在!' }) if user.is_active: user.is_active = False user.save() return Response({ 'status' : 100 , 'msg' : '用户锁定成功!' }) else : # is_active为0的情况 return Response({ 'status' : 102 , 'msg' : '用户已经锁定,请勿重复操作!' }) @action (methods = [ 'GET' ], detail = True ) def unlock( self , request, * args, * * kwargs): user = self .get_object() if user is None : return Response({ 'status' : 101 , 'msg' : '用户不存在!' }) if user.is_active is False : user.is_active = True user.save() return Response({ 'status' : 100 , 'msg' : '用户解锁成功!' }) else : return Response({ 'status' : 102 , 'msg' : '用户没有锁定,请勿重复操作!' }) |
五、序列化类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | from rest_framework import serializers from .models import CarModel, CarFactory, Distributor from .models import User class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = [ 'username' , 'password' , 'mobile' ] extra_kwargs = { 'password' : { 'write_only' : True } } def create( self , validated_data): user = User.objects.create_user( * * validated_data) return user class CarModelSerializer(serializers.ModelSerializer): class Meta: model = CarModel fields = '__all__' extra_kwargs = { 'carmodel_name' : { 'max_length' : 8 , 'min_length' : 3 }, 'distributor' : { 'write_only' : True }, 'carfact' : { 'write_only' : True } } carfact_detail = serializers.SerializerMethodField() def get_carfact_detail( self , obj): return { 'name' : obj.carfact.carfact_name, 'addr' : obj.carfact.carfact_addr} distributor_detail = serializers.SerializerMethodField() def get_distributor_detail( self , obj): l = [] for i in obj.distributor. all (): l.append({ 'name' : i.dist_name, 'addr' : i.dist_addr, 'phone' : i.dist_phone}) return l class CarFactorySerializer(serializers.ModelSerializer): class Meta: model = CarFactory fields = '__all__' class DistributorSerializer(serializers.ModelSerializer): class Meta: model = Distributor fields = '__all__' |
六、路由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | from django.urls import path, include from rest_framework.routers import SimpleRouter from app01.views import CarModelView, CarFactoryView, DistributorView, UserView, AdminView,LoginView route = SimpleRouter() route.register( 'user' , UserView, 'user' ) route.register( 'admin' , AdminView, 'admin' ) route.register( 'carmodel' , CarModelView, 'carmodel' ) route.register( 'carfact' , CarFactoryView, 'carfact' ) route.register( 'dict' , DistributorView, 'dict' ) urlpatterns = [ path( 'login/' , LoginView.as_view()), path('', include(route.urls)) ] |