考试要求:
1 有车型(CarModel),车厂(CarFactory),经销商(Distributor)三个表,一个车厂可以生产多种车型,一个经销商可以出售多种车型,一个车型可以有多个经销商出售
车型:车型名,车型出厂价,车厂id
车厂:车厂名,车厂地址,联系电话
经销商:经销商名,地址,联系电话
2 有用户表,基于django内置user表,扩展mobile字段
3 编写登陆接口,jwt方式返回token,
格式为{status:100,msg:登陆成功,token:safasdfa}
3 有管理员登陆后可以新增,删除车型,车厂,经销商
2 普通用户登陆可以查看车型(群查分页,单查)
查车型:返回车型信息,车厂名字,经销商名字和电话
加分项:
用户注册接口
管理员有用户锁定,删除功能
models.py:
from django.db import models
# Create your models here.
from django.contrib.auth.models import AbstractUser
#python 中定义变量,文件,都用 下划线
# 除了类名以外,不要用驼峰,大小写
# 全大写表示常量
class User(AbstractUser): # 配置文件中配置
mobile = models.CharField(max_length=32)
class CarModel(models.Model):
# 车型名,车型出厂价,车厂id
name = models.CharField(max_length=32)
price = models.CharField(max_length=32)
car_factory = models.ForeignKey(to='CarFactory',on_delete=models.CASCADE)
distributor = models.ManyToManyField(to='Distributor')
def car_factory_detail(self):
return {'name': self.car_factory.name, 'addr': self.car_factory.address}
def distributor_detail(self):
l = []
for item in self.distributor.all():
l.append({'name': item.name, 'addr': item.address, 'mobile': item.mobile})
return l
class CarFactory(models.Model):
# 车厂名,车厂地址,联系电话
name = models.CharField(max_length=32)
address = models.CharField(max_length=32)
mobile = models.CharField(max_length=32)
class Distributor(models.Model):
# 经销商名,地址,联系电话
name = models.CharField(max_length=32)
address = models.CharField(max_length=32)
mobile = models.CharField(max_length=32)
views.py:
from rest_framework.viewsets import ModelViewSet
from .models import *
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.views import APIView
from rest_framework.viewsets import ViewSet
from rest_framework.decorators import action
from django.contrib.auth import authenticate
from rest_framework_jwt.settings import api_settings
from rest_framework.response import Response
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
class UserView(ViewSet):
@action(methods=['POST'], detail=False)
def login(self, request):
username = request.data.get('username')
password = request.data.get('password')
user = authenticate(username=username, password=password)
if user:
# 通过user拿到payload
payload = jwt_payload_handler(user)
# 通过payload拿到token
token = jwt_encode_handler(payload)
return Response({'code': 100, 'msg': '登录成功', 'token': token})
else:
return Response({'code': 101, 'msg': '用户名或密码错误'})
class CarModelView(ModelViewSet):
authentication_classes = [JSONWebTokenAuthentication]
permission_classes = [IsAuthenticated, AdminPermission]
queryset = CarModel.objects.all()
serializer_class = CarModelSerializer
pagination_class = MyPageNumberPagination
"""
authentication_classes = [JSONWebTokenAuthentication]:校验token有没有传,如果传错则无法校验,不传则会正常通过拿到数据。
permission_classes = [IsAuthenticated]:校验是否登陆,配合这个方法必须要上传token(拿到token说明已经登陆)
"""
class CarFactoryView(ModelViewSet):
authentication_classes = [JSONWebTokenAuthentication]
permission_classes = [IsAuthenticated, AdminPermission]
queryset = CarFactory.objects.all()
serializer_class = CarFactorySerializer
class DistributorView(ModelViewSet):
authentication_classes = [JSONWebTokenAuthentication]
permission_classes = [IsAuthenticated, AdminPermission]
queryset = Distributor.objects.all()
serializer_class = DistributorSerializer
"""
用postman向后端传数据时,不能带任何形式的注释。如果将json格式字符串复制到https://www.json.cn/ 中json格式数据不能显示,那么也无法像后端发送。
"""
permission.py:
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
urls.py:
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), # 快速签发
# path('user/', views.UserView.as_view()), # /user/login--->post请求
]
urlpatterns += router.urls
utils.py:
def jwt_response_payload_handler(token, user=None, request=None):
return {
'status': 100,
'msg': '登录成功',
'username':user.username,
'token': token,
}
serializer.py:
from .models import *
from rest_framework import serializers
class CarModelSerializer(serializers.ModelSerializer):
class Meta:
model = CarModel
fields = ['id', 'name', 'price', 'car_factory', 'distributor', 'car_factory_detail', 'distributor_detail'] # CarModel中有两个只读字段所以要全写出来
extra_kwargs = {
'car_factory': {'write_only': True},
'distributor': {'write_only': True},
}
car_factory_detail = serializers.DictField(read_only=True)
distributor_detail = serializers.ListField(read_only=True)
class CarFactorySerializer(serializers.ModelSerializer):
class Meta:
model = CarFactory
fields = '__all__'
class DistributorSerializer(serializers.ModelSerializer):
class Meta:
model = Distributor
fields = '__all__'
page.py:
from rest_framework.pagination import PageNumberPagination
class MyPageNumberPagination(PageNumberPagination):
page_size = 2
page_query_param = 'page'
page_size_query_param = 'size'
max_page_size = 5