飞行的猪哼哼

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一:获取用户列表数据:

接口分析:首先,“lists”,要返回一个列表套字典的格式,需要序列化查询,所以要自定义一个序列化器。
在这里插入图片描述

1:定义一个序列化器:
新建并编辑apps/meiduo_admin/serializers/user_serializers.py

from rest_framework import serializers
from apps.users.models import User
class UserModelSerializer(serializers.ModelSerializer):
    
    class Meta:
        model = User
        fields = ["id", "username", "mobile", "email"]

2:定义一个视图:
新建并编辑apps/meiduo_admin/views/user_views.py

from rest_framework.generics import ListAPIView
from apps.meiduo_admin.serializers.user_serializers import UserModelSerializer
from apps.users.models import User

class UserView(ListAPIView):
    queryset = User.objects.filter(is_staff=True)
    serializer_class = UserModelSerializer
    

3:自定义分页器:
新建并编辑apps/meiduo_admin/paginations.py自定义分分页器

from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response

class MyPage(PageNumberPagination):
    page_query_param = 'page' # ?page=1
    page_size_query_param = 'pagesize' # ?pagesize=5
    max_page_size = 10
    page_size = 5

    def get_paginated_response(self, data):
        return Response({
            'counts': self.page.paginator.count, # 总数量
            'lists': data, # 查询集分页的子集(当前页数据)
            'page': self.page.number, # 当前页
            'pages': self.page.paginator.num_pages, # 总页数
            'pagesize': self.page_size
        })

在视图中指定分页器:

pagination_class = MyPage

4:对查询集进行过滤:
如果前端传入查询字符串参数keyword,那么我们要根据这个keyword进行过滤,如果前端没有传入我们要返回所有的数据。

需要提前解决的问题,我们自己定义的get_queryset()不是视图的get方法,也就是没有request参数,那么我们如何拿到我的keyword数据呢?????

答:在django/drf中,每次请求的时候,框架除了把请求对象request传入视图函数以外,还会把请求对象封装到self.request中(self指的是视图对象)。

from rest_framework.generics import ListAPIView

from apps.meiduo_admin.paginations import MyPage
from apps.meiduo_admin.serializers.user_serializers import UserModelSerializer
from apps.users.models import User
class UserView(ListAPIView):
    queryset = User.objects.filter(is_staff=True)
    serializer_class = UserModelSerializer
    # 指定分页器
    pagination_class = MyPage

    def get_queryset(self):
        keyword = self.request.query_params.get("keyword")

        if keyword:
            # 返回过滤后的数据---名字包含这个keyword的
            return self.queryset.filter(username__contains=keyword)
        else:
            return self.queryset.all()

二:新建用户:

<一>分析:新建用户肯定是一个反序列化的过程,所以首先考虑我的当前的序列化器,能不能满足我们的反序列化呢?
这个是当前的序列化器。

class UserModelSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ["id", "username", "mobile", "email"]

前端的需求:对比可以发现:id,mobile,email都需要设置必传,而 新建用户必须有密码,对于密码需要新增如fields ,并且密码只作用于反序列化。
在这里插入图片描述
所以:需要增加限制条件:

extra_kwargs = {
            "password": {"write_only": True, "required": True},
            "username": {"required": True},
            "mobile": {"required": True},
            "email": {"required": True}
        }

<二>: 再次分析:对于前端视图,我们这个时候需要新建用户,所以要增加继承CretaeAPIView,由于之气那有一个ListAPIView,所以有一个他们的子类: ListCreateView,只需要继承这个就可以了。

此时出现两个问题:
问题一:新建用户的密码在数据库中没有加密。
问题二:新建用户的的is_staff属性没有设置成True。
如下图:在这里插入图片描述
在这里插入图片描述

<三>如何解决这两个问题???
分析:第一:谁负责用户密码的加密??—> 创建用户的函数—>序列化器的create方法。回顾整个反序列化的流程,我们可以发现,可以从cretae方法入手,自定义create方法。也可以在校验过程中,对有效数据中的明文密码加密,以及在返回的有效数据中添加is_staff=True —— 后续create方法完成新建对象就是使用调整之后的有效数据!

当且仅当校验成功
字典
校验
有效数据
create方法新建
约束条件
类型校验
validate_<字段>校验
validate校验

方案一:重写create方法:
一: 编辑apps/meiduo_admin/serializers/user_serializers.py

class UserModelSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ["id", "username", "mobile", "email", "password"]

        extra_kwargs = {
            "password": {"write_only": True, "required": True},
            "username": {"required": True},
            "mobile": {"required": True},
            "email": {"required": True}
        }

    def create(self, validated_data):
        # 原来create方法默认是false
        validated_data["is_staff"] = True
        return User.objects.create_user(**validated_data)

在这里插入图片描述

方案二:我在自定义校验的时候, 自定义validate方法,对密码进行加密,并且将is_staff设置成True。

问题:django如何对字符串进行加密的呢???

from django.contrib.auth.hashers import make_password
make_password方法进行加密
class UserModelSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ["id", "username", "mobile", "email", "password"]

        extra_kwargs = {
            "password": {"write_only": True, "required": True},
            "username": {"required": True},
            "mobile": {"required": True},
            "email": {"required": True}
        }


    def validate(self, attrs):
        password = attrs.pop("password")
        password = make_password(password)
        attrs['password'] = password
        attrs['is_staff'] = True
        return attrs
posted on 2020-09-27 19:09  飞行的猪哼哼  阅读(21)  评论(0)    收藏  举报