Django Rest_framework 10(使用进化史)

一、继承View类[CBV与类结合,需要自定义方法将对象转为json对象]

urls.py[CBV与类结合]
CBV提供了一个as_view()静态方法(也就是类方法),调用这个方法,会创建一个类的实例,
然后通过实例调用dispatch()方法,dispatch()方法会根据request的method的不同调用相应的方法来处理request(如get() , post()等)

#[不带参数的请求]UsersResouces,get请求全部用户信息,post添加用户信息,
#[带参数的请求]UsersResource,user/2  get请求id为2的信息,delete删除,put/patch更新信息
urlpatterns = [
    path('index', UserView.as_view(), name='index'),
    path('modify/<int:id>', UserModifyView.as_view(), name='modify'),
]
views.py[CBV与类结合]
## 定义一个User类
class User:
    def __init__(self, id, username, password):
        self.id = id
        self.username = username
        self.password = password

    def to_dict(self):#[返回的格式需要时json格式]
        return {'id': self.id, 'username': self.username, 'password': self.password}

    def __str__(self):
        return self.username
user_list = []
id = 0

# CBV与类结合,不需要传参
class UserView(View):
    def get(self, request):
        if len(user_list) > 0:
            data = {'status': 200,'users': user_list}
        else:
            data = {'status': 200,'msg': "还没有用户"}
        return JsonResponse(data)

    def post(self, request):
        username = request.POST.get('username')
        password = request.POST.get('password')
        global id
        id += 1
        if username not in user_list:
            user = User(id, username, password)
            user_list.append(user.to_dict())  #需要将json格式放在list中返回
            data = {'status': 201,'msg': "用户%s添加成功" % username,'users': user_list}
        else:
            data = {'status': 201,'msg': "用户%s已存在" % username}
        return JsonResponse(data)


# put,patch,delete需要传参单独定义一个view类
class UserModifyView(View):
    def put(self, request, id):
        pass

    def patch(self, request, id):
        flag = False
        for user in user_list:
            if id == user['id']:
                user['password'] = "111111"
                flag = True
                break
        if flag:
            data = {'status': 400,'msg': "用户%s的密码修改成功" % id,'users': user_list}
        else:
            data = {'status': 400,'msg': "用户%s不存在,修改失败" % id,'users': user_list}

        return JsonResponse(data)

    def delete(self, request, id):
        pass

二、继承View类[CBV与数据库结合,需要自定义方法将对象转为json对象]

urls.py
urlpatterns = [
    path('mindex',UserModelView.as_view(),name='mindex'),
    path('mmodify/<int:id>',UserModelModifyView.as_view(),name='mmodify')
]
models.py
class UserModel(models.Model):
    username=models.CharField(max_length=100)
    password=models.CharField(max_length=100)

    def to_dict(self):#将模型转为json对象
        return {'id':self.id,'username':self.username,'password':self.password}

    def __str__(self):
        return self.username

    class Meta:
        db_table="user"
views[CBV和数据库结合]
# CBV和数据库结合,不需要传参
class UserModelView(View):
    def get(self, request):
        users = UserModel.objects.all()
        user_list = []
        for user in users:
            user_list.append(user.to_dict())
        if len(user_list) > 0:

            data = {'status': 200,'msg': '获取全部用户','users': user_list}
        else:
            data = {'status': 200,'msg': '还没有用户',}
        return JsonResponse(data)

    def post(self, request):
        username = request.POST.get('username')
        password = request.POST.get('password')
        userisexist = UserModel.objects.filter(username=username)
        if userisexist:
            data = {'status': 400,'msg': '用户%s已存在' % username}
        else:
            user = UserModel.objects.create(username=username, password=password)
            if user:
                data = {'status': 201,'msg': '用户%s添加成功' % username,
                		'user': user.to_dict()}
            else:
                data = {'status': 400,'msg': '用户%s添加失败' % username}

        return JsonResponse(data)

# put,patch,delete需要传参单独定义一个view类
class UserModelModifyView(View):
    def get(self, request, id):
        user = UserModel.objects.filter(id=id).first()
        if user:
            data = {'status': 200,'msg': 'id%s用户获取成功' % id,'user': user.to_dict()}
        else:
            data = {'status': 201,'msg': 'id%s用户不存在' % id}
        return JsonResponse(data)

    def patch(self, request, id):
        user = UserModel.objects.filter(id=id).first()
        if user:
            user.password = "11111"
            user.save()
            data = {'status': 201,'msg': 'id%s的用户密码修改成功' % id,
                'user': user.to_dict()
            }
        else:
            data = {
                'status': 400,'msg': 'id%s的用户不存在,修改失败' % id
            }
        return JsonResponse(data)

    def delete(self, request, id):
        user = UserModel.objects.filter(id=id).first()
        if user:
            user.delete()
            data = {'status': 204,'msg': 'id%s的用户删除成功' % id}
        else:
            data = {'status': 400,'msg': 'id%s的用户不存在,删除失败' % id}
        return JsonResponse(data)

三、序列化与反序列化[继承Serializer,APIView]

解决模型需要转为json返回前端,前端数据处理之后放进数据库的问题,引入序列化与反序列化
为了方便拿到前端传过来的数据,引入APIView,使用request.data,什么类型数据都能拿到
APIView和View
# REST framework提供了一个APIView类,它是Django的View类的子类。
APIView比View更为强高级之处就是APIView的dispatch()比View的dispatch()高级

APIView与View的不同之处
    传入到视图方法中的是Request对象,而不是Django的HttpRequest对象
    视图方法可以返回Response对象,会为响应数据处理(render)为符合前端要求的格式
    任何APIException异常都会被捕获到,并且处理成合适的响应信息
    在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制
    
Django之DRF-一个请求的前世今生:https://blog.youkuaiyun.com/weixin_47454485/article/details/107505904
Django之DRF-APIView:
https://blog.youkuaiyun.com/weixin_47454485/article/details/107461486
Django之DRF-APIView、View源码对比:
https://www.pianshen.com/article/30771764378/

1.概念
为优化 自定义方法将对象转为json 的过程,引入序列化与反序列化
2.使用步骤
作用:提高RestAPI接口开发的效率
关键功能:
	序列化器:序列化和反序列化
	类视图,MiXin扩展类:简化视图代码的编写

文档地址:https://www.django-rest-framework.org/
1.pip install djangorestframework
2.将‘rest_framework’添加在installed_apps中
3.在需要的app中新建serializers.py文件
3.实例
urls.py
urlpatterns = [
    path('index', GameResources.as_view(), name='index'),
    path('aindex', GameResoucesAPI.as_view(), name='aindex'),
    path('amodify/<int:id>',GameResourcesModifyAPI.as_view(),name='amodify')
]
models.py
class Game(models.Model):
    name=models.CharField(max_length=100)
    role=models.CharField(max_length=100)
    company=models.CharField(max_length=100)
    publish_date=models.DateField(auto_now=True)

    def __str__(self):
        return self.name

    class Meta:
        db_table="game"
serialziers.py[新建serializers.py文件,字段和model字段一样]
#继承Serializer
from rest_framework import serialziers
class GameSerializer(Serializer):
    name = serializers.CharField(max_length=100)
    role = serializers.CharField(max_length=100)
    company = serializers.CharField(max_length=100)
    publish_date = serializers.DateField()

	#继承Serializer,反序列化需要手动实现create,update方法
	#传参根据是否传递了instance自动区分调用create还是update
    def create(self, validated_data):
        return Game.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.name = validated_data.get('name', instance.name)
        instance.role = validated_data.get('role', instance.role)
        instance.company = validated_data.get('company', instance.company)
        instance.save()
        return instance
3.1序列化方法及实例:序列化对象(将模型实例或者结果集转成json的格式)
得到模型实例-->转为json-->结果gameserlizer.data

单个:
game=Game.objects.create(name=name,role=role,company=company)
gameserlizer=GameSerializer(game)

多个:
games=Game.objects.all()
gamesSerializer=GameSerializer(games,many=True)
views.py
class GameResources(View):
    def get(self,request):
        games=Game.objects.all()
        gamesSerializer=GameSerializer(games,many=True)
        if games.count()>0:
            data={'status':200,'count':games.count(),
                'games':gamesSerializer.data}
        else:
            data = {'status': 200,'count': games.count(),'msg':'还没有数据'}
        return JsonResponse(data)

    def post(self,request):
        name=request.POST.get('name')
        role=request.POST.get('role')
        company=request.POST.get('company')
        game=Game.objects.create(name=name,role=role,company=company)
        gameserlizer=GameSerializer(game)
        if game:
            data={'status':201,'msg':'游戏%s添加成功'%name,
                'game':gameserlizer.data}
        else:
            data = {'status': 400,'msg': '游戏%s添加失败' % name}
        return JsonResponse(data)
4.反序列化方法及实例
数据校验
 1.使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。
 2.在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False。
 3.验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。
 4.验证成功,可以通过序列化器对象的validated_data属性获取数据。
 5.在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为
   
数据入库:
    1.数据保存 save方法
    2.序列化器中传入两个参数,即数据的更新操作,
        继承自Serializer的类,需要手动实现create,update方法   
views.py[需要通过request.data获取传过来的数据,继承APIView]
class GameResoucesAPI(APIView):
	# 此时的request是rest_framework的request对象
    def get(self,request):
        games=Game.objects.all()
        print(request.GET.get('username'))  # 获取get请求提交的参数
        serializergames=GameSerializer(games,many=True)
        data={'count':games.count(),'games':serializergames.data}
        return JsonResponse(data)

    def post(self,request):
    	print(request.POST.get('username'))  # 无法获取POST请求提交的参数使用此方式
    	#反序列化,拿数据通过request.data
        serializer=GameSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            #验证成功,可以通过序列化器对象的validated_data属性获取数据。
            print("%%",serializer.validated_data)
            return JsonResponse({'status':'Success'})
        else:
            return JsonResponse({'status': 'fail'})

class GameResourcesModifyAPI(APIView):
    def get(self,request,id):
        game=Game.objects.get(pk=id)
        serializer=GameSerializer(game)
        return JsonResponse(serializer.data)

    def patch(self,request,id):
        game=Game.objects.get(pk=id)
        #序列化器中传入两个参数,即数据的更新操作,部分更新partial=True
        serializer=GameSerializer(game,data=request.data,partial=True)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse({'msg':'修改成功'})
        else:
            return JsonResponse({'msg': '修改失败'})

    def delete(self,request,id):
        game=Game.objects.get(pk=id)
        game.delete()
        return JsonResponse({'msg': '删除成功'})

四、序列化与反序列化[继承ModelSerializer,APIView]

为了避免继承serializer需要自定义字段,手动重写create,update方法的繁琐,
引入继承ModelSerializer
#学生和班级两个模型,班级->学生(一对多)
class Classes(models.Model):
    classname=models.CharField(max_length=50,verbose_name="班级")
    school=models.CharField(max_length=50,verbose_name="学校")
    admission_date=models.DateField(auto_now=True,verbose_name="入学时间")

    def __str__(self):
        return self.classname

    class Meta:
        db_table="classes"

class Students(models.Model):
    name=models.CharField(max_length=50,verbose_name="学生姓名")
    gender=models.CharField(max_length=30,choices=(("boy","boy"),('girl','girl')),default='boy',verbose_name="性别")

    sclass=models.ForeignKey(to=Classes,on_delete=models.CASCADE,verbose_name="学生班级")


    def __str__(self):
        return self.name

    class Meta:
        db_table="students"

serializers.py

class StudentsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Students
        fields = "__all__"


class ClassesSerializer(serializers.ModelSerializer):
	#详细字段用法见DRF4(Django之serializer-主从表数据关联查询)
    # students_set=serializers.StringRelatedField(read_only=True,many=True)
    # students_set=serializers.PrimaryKeyRelatedField(read_only=True,many=True)
    students_set = serializers.HyperlinkedRelatedField(read_only=True, many=True, view_name='classes:mstudent',lookup_field='id')

    class Meta:
        model = Classes
        fields = "__all__"

urls.py

urlpatterns=[
	#get 和 post学生信息
    path('student',StudentsResources.as_view(),name='student'),
    #对单个学生信息操作
    path('mstudent/<int:id>',StudentResource.as_view(),name='mstudent'),
    #班级
    path('classess',ClassesResources.as_view(),name="classess")
]

views.py

class StudentsResources(APIView):
    def get(self, request):
        students = Students.objects.all()
        serializer = StudentsSerializer(students, many=True)
        if students.count() > 0:
            data = {'status': 200,'count': students.count(),
                'students': serializer.data}
            return JsonResponse(data)
        else:
            data = {'status': 200,'count': students.count(),
                'msg': '还没有学生信息'}
            return JsonResponse(data)

    def post(self, request):
        serializer = StudentsSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse({'status': 201,'msg': "学生信息添加成功"})
        return JsonResponse({'status': 400,'msg': "学生信息添加失败"})


class StudentResource(APIView):
    def get(self, request, id):
        student = Students.objects.get(pk=id)
        serializer = StudentsSerializer(student)
        return JsonResponse(serializer.data)

    def patch(self, request, id):
        student = Students.objects.filter(id=id).first()
        serializer = StudentsSerializer(student, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse({'msg': '修改成功'})
        return JsonResponse({'msg': '修改成功'})

    def delete(self, request, id):
        student = Students.objects.filter(id=id).first()
        if student:
            student.delete()
            return JsonResponse({'msg': '删除成功'})
        return JsonResponse({'msg': '删除失败'})


class ClassesResources(APIView):
    def get(self, request):
        classes = Classes.objects.all()
        #使用HyperlinkedRelatedField需要添加context={'request': request}
        serializer = ClassesSerializer(classes, many=True, context={'request': request})
        data = {'status': 200,'data': serializer.data}
        return JsonResponse(data)

五、继承ListCreateAPIView和RetrieveUpdateDestoryAPIView

每次写不同表的数据的接口,总是需要重复的写这些方法,get,post,delete,put
有没有更好的封装,连这些方法都不用写了呢???
ListCreateAPIView和RetrieveUpdateDestoryAPIView出场

urls.py

urlpatterns=[
    path('users',UsersResouces.as_view(),name="users"),
    path('users/<int:pk>',UsersResource.as_view(),name='users-detail'),
]

views.py

#写两个类视图,一个带参数的,一个不带参数的
#queryset  指明视图需要的数据(model查询数据)
#serializer_class  指明视图使用的序列化器 
class UsersResouces(ListCreateAPIView):
    queryset = Users.objects.all()
    serializer_class = UsersSerializer

class UsersResource(RetrieveUpdateDestroyAPIView):
    queryset = Users.objects.all()
    serializer_class = UsersSerializer

六、ModelViewSet

上面还是有冗余代码,并且需要两个路由
https://www.jianshu.com/p/c3a439f0d5b8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
router=DefaultRouter()
router.register('user',UserResourceOther)

app_name="users"
urlpatterns=[
    path('',include(router.urls))
]

#集合了get,post,retrieve,delete,put所有的方法
class UserResourceOther(ModelViewSet):
    queryset = Users.objects.all()
    serializer_class = UsersSerializer

七、基于mixins来封装的视图(MIxin+GenericViewSet)

使用类视图需要写两个类,一个用于没有参数,另一个用于传递参数
使用视图集可以将所有的方法写在一个里面,提高开发效率,并且用到哪个导入哪个
ListModelMixin,CreateModelMixin,Retrieve,Update,Destroy 结合GenericViewSet使用

在这里插入图片描述

数据库操作之前的应该重写CreateModelMixin的create方法
比如拿到前端传过来的密码应该加密后存放到数据库中
路由:
router.register('banners', BannerViewSet, basename="banners")

# 首页轮播图
class BannerViewSet(ListModelMixin, GenericViewSet):
    queryset = Banner.objects.all()
    serializer_class = BannerSerializer
    
# 首页轮播图序列化
class BannerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Banner
        fields = "__all__"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值