当前位置: 代码迷 >> 综合 >> django+restframework 基础
  详细解决方案

django+restframework 基础

热度:70   发布时间:2024-02-20 09:52:29.0

 

Django 基础

MTV模型

Model(模型)、Template(模板)、View(视图)、额外URL分发器

安装:pip install django
创建django 项目 django-admin.py  startproject 名称
创建django app python3 manage.py startapp blog(应用名称)
启动 python3 manage.py runserver  8080
创建表 
python3 manage.py makemigrations
python3 manage.py migrate
只有方法视图 
 

Rest-framework 基础

认证和权限自定义

认证基类 BaseAuthentication 

自定义认证需要重写authenticate方法

权限基类 BasePermission

自定义权限需要重写has_permission方法
例子:
from rest_framework.authentication import BaseAuthentication
class MyAuth(BaseAuthentication):
    def authenticate(self, request):
        '''
        自定义的权限中必须要有此方法以及如下的判断和两个返回值
        :param request:
        :return:
        '''
        #1获取token
        # token=request.query_params.get('token')
        token=request.META['HTTP_TOKEN']
        # # print(json.dumps(dict(request.META),ensure_ascii=False))
        # print(dict(request.META))
        #2判断是否成功获取token
        if not token:
            raise AuthenticationFailed('缺少token')
        #3判断是否合法
        try:
            user_obj=UserInfo.objects.filter(token=token).first()
        except Exception:
            raise AuthenticationFailed('token不合法')
        #判断token在数据库中是否存在
        if not user_obj:
            raise AuthenticationFailed('token 不存在')
        if user_obj.expire_date < datetime.datetime.now():
                # datetime.timedelta(hours=24 * 14) :
            raise AuthenticationFailed('认证信息过期')
        #5认证通过
        # print(user_obj)
        return (user_obj.user_code,user_obj)
        #注意 权限组件会用到这两个返回值
 
from rest_framework.permissions import BasePermission
class MyPermission(BasePermission):
    message = "必须是SVIP才能访问"
    def has_permission(self, request, view):
        if request.auth.user_type in (1,2):
            return True
        else:
            return False

 

settings:

REST_FRAMEWORK={
    
    "DEFAULT_AUTHENTICATION_CLASSES":["backend.utils.MyAuth.MyAuth",],
    'DEFAULT_PAGINATION_CLASS' : 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE' : 100,
    'DEFAULT_PERMISSION_CLASSES':['backend.utils.MyPermission.MyPermission',],
    # 'DEFAULT_PERMISSION_CLASSES':['rest_framework.permissions.AllowAny',],
    # 'DEFAULT_PERMISSION_CLASSES':['rest_framework.permissions.IsAuthenticated','backend.utils.MyPermission.MyPermission'],
}

 

序列化serializers

普通序列化serializers.Serializer

需要挨个字段序列化,需要重写create或者update方法,比较麻烦

例子:

class OrderInfoSerializer(serializers.Serializer):
    tenantNo=serializers.CharField(required=False,allow_blank=True,max_length=32)
    userCode=serializers.ReadOnlyField(source='userCode.orderCode')
    orderCode=serializers.CharField(read_only=True,max_length=32)
    orderType=serializers.ChoiceField(choices=OrderInfo._orderType,default=1)
    storeCode=serializers.CharField(required=False,allow_blank=True,max_length=32)
    customerCode=serializers.CharField(required=True,allow_blank=False,max_length=32)
    customerName=serializers.CharField(required=True,allow_blank=False,max_length=128)
    status=serializers.ChoiceField(choices=OrderInfo._status,default=10)
    createBy=serializers.CharField(read_only=True,max_length=32)
    createName=serializers.CharField(read_only=True,max_length=128)
    # createName=serializers.CharField(required=True,allow_blank=False,max_length=128)
    createTime=serializers.DateTimeField(read_only=True)
    updateBy=serializers.CharField(required=True,allow_blank=True,max_length=32)
    updateTime=serializers.DateTimeField(read_only=True)
 
    def create(self, validated_data):
        # maxOrderCode=basicCode().getNextMerchantCode()
        # print(maxOrderCode)
        # print(type(maxOrderCode))
        return OrderInfo.objects.create(**validated_data)
 
    def update(self, instance, validated_data):
        instance.tenantNo=validated_data.get('tenantNo',instance.tenant_no)
        # instance.orderCode=validated_data.get('orderCode',instance.order_code)
        instance.orderType=validated_data.get('orderType',instance.order_type)
        instance.storeCode=validated_data.get('storeCode',instance.store_code)
        instance.customerCode=validated_data.get('customerCode',instance.customer_code)
        instance.customerName=validated_data.get('customerName',instance.customer_name)
        instance.status=validated_data.get('status',instance.status)
        # instance.create_by=validated_data.get('createBy',instance.create_by)
        # instance.createName=validated_data.get('createName',instance.create_name)
        instance.updateBy=validated_data.get('updateBy',instance.update_by)
        instance.save()
        return instance

模型序列化 serializers.ModelSerializer

比较方便,只需要设置需要序列化的字段和只读字段既可 推荐使用

例子:

class OrderInfoModelSerializer(serializers.ModelSerializer):
    class Meta:
        model=OrderInfo
        fields='__all__'
        read_only_fields=('userCode','createTime','updateTime','orderCode')

 

视图

方法视图:

get获取列表post提交新记录

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
@api_view(['GET','POST'])
def orderInforList(request,format=None):
    print(request.user)
    print(request.auth)
    if request.method=='GET':
        act=OrderInfo.objects.all()
        ser=OrderInfoSerializer(act,many=True)
        return Response(ser.data)
    elif request.method=='POST':
        print(request.data)
        ser=OrderInfoSerializer(data=request.data)
        if ser.is_valid():
            ser.save(userCode=request.user,createBy=request.user,createName=request.auth.user_name,orderCode=basicCode().getNextMerchantCode())
            return Response(ser.data,status=status.HTTP_201_CREATED)
        return Response(ser.errors,status=status.HTTP_400_BAD_REQUEST)

单记录操作,get获取详情,put修改,delete删除

@api_view(['GET','PUT','DELETE'])def orderInfoDetail(request,orderCode,format=None):print(orderCode)try:orderInfo=OrderInfo.objects.get(orderCode=orderCode)except OrderInfo.DoesNotExist:return Response(status=status.HTTP_404_NOT_FOUND)if request.method=='GET':ser=OrderInfoModelSerializer(orderInfo)return Response(ser.data)elif request.method=='PUT':ser=OrderInfoModelSerializer(orderInfo,data=request.data)if ser.is_valid():ser.save()return Response(ser.data)return Response(ser.errors,status=status.HTTP_400_BAD_REQUEST)elif request.method=='DELETE':orderInfo.delete()return Response(status=status.HTTP_204_NO_CONTENT)

url

re_path(r'^orderInforList/$',OrderInfo.orderInforList),re_path(r'^orderInfoDetail/(?P<orderCode>[-A-Za-z0-9]+)$',OrderInfo.orderInfoDetail),

 

 

 

 

类视图

基本 直接继承APIView

 

例子:

 
from rest_framework.views import APIView
class LoginView(APIView):
    '''
    登录视图
    '''
    authentication_classes = []
    permission_classes = []
    def post(self,request):
        name=request.data.get('name')
        pwd=request.data.get('pwd')
        user_obj=UserInfo.objects.filter(user_code=name,pwd=pwd).first()
        if user_obj:
            u4=uuid.uuid4() #生成uuid4 随机数
            print(u4)
            user_obj.token=u4
            user_obj.expire_date=datetime.datetime.now()+datetime.timedelta(hours=1)
            user_obj.save()
            data={"code":9999,"msg":"成功","data":{"token":u4,"name":name}}
            return Response(data)
        return Response({"code":8888,"msg":"用户名或密码错误","data":""})

 

升级版GenericAPIView+5种MIXIN类(CreateModelMixin、ListModelMixin、RetrieveModelMixin、UpdateModelMixin、DestroyModelMixin)

只要继承GenericAPIView 如果涉及到单条记录的操作,需要重新定义lookup_field=’pk’,拼接到url后作为单条记录的唯一标识字段,默认为id也就是主键

例子:

class LoginRegister(CreateModelMixin,GenericAPIView):
    authentication_classes = []
    permission_classes = []
    queryset = UserInfo.objects.all()
    serializer_class = LoginRegisterSerializer
    # def get(self,request,*args,**kwargs):
    #     return self.list(request,*args,**kwargs)
 
    def post(self,request,*args,**kwargs):
        return self.create(request,*args,**kwargs)
 
    # def create(self, request, *args, **kwargs) :
    #     serializer = self.get_serializer(data=request.data)
    #     serializer.is_valid(raise_exception=True)
    #     self.perform_create(serializer)
    #     headers = self.get_success_headers(serializer.data)
    #     print(f'headers{headers}')
    #     return JsonResponse({"data":serializer.data, "code":201, "msg":"创建成功"})
 
    def perform_create(self,serializer):
        serializer.save(user_type=2)

 

高阶版 generics封装好的9个常用APIView

1)CreateAPIView:(mixins.CreateModelMixin,GenericAPIView)

2)ListAPIView:(mixins.ListModelMixin,GenericAPIView)

3)RetrieveAPIView、(mixins.RetrieveModelMixin,GenericAPIView)

4)DestroyAPIView、(mixins.DestroyModelMixin,GenericAPIView)

5)UpdateAPIView、(mixins.UpdateModelMixin,GenericAPIView)

6)ListCreateAPIView、(mixins.ListModelMixin,mixins.CreateModelMixin,GenericAPIView)

7)RetrieveUpdateAPIView、(mixins.RetrieveModelMixin,mixins.UpdateModelMixin,GenericAPIView)

8)RetrieveDestroyAPIView、(mixins.RetrieveModelMixin,mixins.DestroyModelMixin,GenericAPIView)

9)RetrieveUpdateDestroyAPIView: (mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,GenericAPIView)

 

例子:

from rest_framework.generics import GenericAPIView,RetrieveUpdateDestroyAPIView
from rest_framework.mixins import CreateModelMixin,UpdateModelMixin,DestroyModelMixin,ListModelMixin,RetrieveModelMixin
class LoginInfo1(RetrieveUpdateDestroyAPIView):
    queryset = UserInfo.objects.all()
    serializer_class = LoginRegisterSerializer
    lookup_field = 'user_code'

视图集viewsets

list  #get 请求 返回全部查询
create  #post 请求 处理表单提交数据
retrieve #get 请求 通过pk 查询单个信息+
update  #patch 请求 通过pk 修改数据
destroy  #delete 请求 通过pk 删除数据

 

 

class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,mixins.ListModelMixin,GenericViewSet):"""A viewset that provides default `list()` and `retrieve()` actions.

 

class ModelViewSet(mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin,GenericViewSet):"""A viewset that provides default `create()`, `retrieve()`, `update()`,`partial_update()`, `destroy()` and `list()` actions."""

 

 

from rest_framework import viewsets