drf 测试(车型、车场、经销商)

发布时间 2023-09-26 19:03:52作者: 凡人半睁眼

一、实现要求

1 有车型(CarModel),车厂(CarFactory),经销商(Distributor)三个表,一个车厂可以生产多种车型,一个经销商可以出售多种车型,一个车型可以有多个经销商出售

车型:车型名,车型出厂价,车厂id

车厂:车厂名,车厂地址,联系电话

经销商:经销商名,地址,联系电话

2 有用户表,基于django内置user表,扩展mobile字段

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

4 所有接口(除登录外),必须登录后才能访问

5 管理员登陆后可以增,删,单查,群查,改 车型,车厂,经销商(具备所有接口权限)

6 普通用户登陆可以查看车型,车厂,经销商单条,所有(只有查看权限)

7 所有查询所有接口带分页功能

8 查询所有车型接口,可以按车型名字精准过滤

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

注:

根据信息提取出表关系:车型和车场:一对多,车型和经销商:多对多

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视图类导入模块汇总

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 方法去比对验证加密后的密码

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、注册

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

# 车型
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、分页类

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、自定义的认证类

判断用户的角色和请求方法,普通用户只能有查看单条和查看所有的权限

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

四、管理员有用户锁定,删除用户功能

#  管理员有用户锁定,删除用户功能
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': '用户没有锁定,请勿重复操作!'})

五、序列化类

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__'

六、路由

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))
 ]