drf 测试(车型、车场、经销商)
一、实现要求
1 有车型(CarModel),车厂(CarFactory),经销商(Distributor)三个表,一个车厂可以生产多种车型,一个经销商可以出售多种车型,一个车型可以有多个经销商出售
车型:车型名,车型出厂价,车厂id
车厂:车厂名,车厂地址,联系电话
经销商:经销商名,地址,联系电话
2 有用户表,基于django内置user表,扩展mobile字段
3 编写登陆接口,jwt方式返回token,
格式为{status:100,msg:登陆成功,token:safasdfa}
4 所有接口(除登录外),必须登录后才能访问
5 管理员登陆后可以增,删,单查,群查,改 车型,车厂,经销商(具备所有接口权限)
6 普通用户登陆可以查看车型,车厂,经销商单条,所有(只有查看权限)
7 所有查询所有接口带分页功能
8 查询所有车型接口,可以按车型名字精准过滤
加分项:
用户注册接口
管理员有用户锁定,删除用户功能
注:
根据信息提取出表关系:车型和车场:一对多,车型和经销商:多对多
Models:
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))
]

浙公网安备 33010602011771号