rest_framwork框架的简单使用
发布日期:2021-10-24 14:20:23 浏览次数:2 分类:技术文章

本文共 10656 字,大约阅读时间需要 35 分钟。

from django.http.response import JsonResponseclass BookListView(View):    def get(self, request, *args, **kwargs):        # 返回的 是json格式        all_books = models.Book.objects.all().values('id', 'title', 'pub_date')        return JsonResponse(all_books)

错误:

In order to allow non-dict objects to be serialized set the safe parameter to False. 为了一个非字典的对象可以被序列化需要设置  safe=False
return JsonResponse(all_books,safe=False)

错误:

Object of type 'QuerySet' is not JSON serializable all_books是QuerSet类型
return JsonResponse(list(all_books),safe=False)

得到的文字是ascii类型

return JsonResponse(list(all_books), safe=False, json_dumps_params={'ensure_ascii': False})

 

django中的序列化器

from django.core import serializersclass BookListView(View):    def get(self, request, *args, **kwargs):        all_books = models.Book.objects.all()        data = serializers.serialize('json', all_books)        return HttpResponse(data)

得到的结果

 
View Code

灵活度不高 

 

 

django的rest_framwork框架 做序列化 

get请求

需要有djangorestframework包

from rest_framework.views import APIViewfrom rest_framework.response import Responseclass BookListView(APIView):    def get(self, request, *args, **kwargs):        all_books = models.Book.objects.all()        return Response(all_books)

错误

rest_framework/api.html 没有注册   在settings中注册app
'rest_framework'

错误

Object of type 'Book' is not JSON serializable 不能被序列化
all_books = models.Book.objects.all().values()

得到页面 里面的内容就是book表中的数据   还需要得到 表中关联的数据   

需要序列化器  去序列化出想得到的结果

现在的问题是 一本书有多个作者   拿到的all_books的 是一本书对应一个作者  多个作者就有多条数据  这种情况是 默认序列化导致的

现在需要自己 创建序列化器  然后序列化之后的值再传给前端

创建一个序列化文件 serializer并在里面写   需要与models中'大体一样'

from rest_framework import serializersclass BookSerializers(serializers.Serializer):    title = serializers.CharField()    price = serializers.DecimalField(max_digits=6, decimal_places=2)    pub_data = serializers.DateTimeField()

在views中

from app01.serializer import BookSerializersclass BookListView(APIView):    def get(self, request, *args, **kwargs):        all_books = models.Book.objects.all()        ser_obj = BookSerializers(all_books)            #ser_obj是对象        return Rseponse(ser_obj.data)                     #ser_obj是序列化的结果

报错

'QuerySet' object has no attribute 'title'. queryset对象没有title的属性 因为all_books中是多个对象
ser_obj = BookSerializers(all_books, many=True)

all_books = models.Book.objects.all().first()#这样就值拿到了第一个  只序列化一个对象

这样就拿到了这些普通的字段

然后 在serializer中写    pub是外键关联的是出版社    author是多对多 关联作者表

pub= serializers.IntegerField()

报错

int() argument must be a string, a bytes-like object or a number, not 'Publisher'
pub_id = serializers.IntegerField()

这样的到的还是出版社的id

class PublisherSerializers(serializers.Serializer):    name = serializers.CharField()class BookSerializers(serializers.Serializer):    title = serializers.CharField()    price = serializers.DecimalField(max_digits=6, decimal_places=2)    pub_date = serializers.DateTimeField()    pub = PublisherSerializers()

这样就得到了

{        "title": "没事就念经",        "price": "999.99",        "pub_date": "2019-01-01T10:10:10Z",        "pub": {            "name": "冰棍"        }    },

再写authors

authors = serializers.SerializerMethodField()

报错

'BookSerializers' object has no attribute 'get_authors'
pub = PublisherSerializers()    authors = serializers.SerializerMethodField()    def get_authors(self, obj):        print(obj)

authors是 null  但是print(obj) 是Book object

pub = PublisherSerializers()    authors = serializers.SerializerMethodField()   #.Ser之后就去调用get_字段名的方法    def get_authors(self, obj):       #obj是当前循环book的对象        ser_obj = AuthorSerializers(obj.authors.all(),many=True)   #进行序列化        return ser_obj.data
 
结果

 

post请求

def post(self, request, *args, **kwargs):        print(request.data)

注意的是 在添加时 需要将外键和多对多 添加的数据变为id    

request.data得到的就是 提交的所有护数据

 

def post(self, request, *args, **kwargs):        ser_obj = BookSerializers(data=request.data)        if ser_obj.is_valid():            ser_obj.save()            return Response(ser_obj.data)        else:            return Response(ser_obj.errors)

 

 
添加

报错

HTTP 200 OKAllow: GET, POST, HEAD, OPTIONSContent-Type: application/jsonVary: Accept{    "pub": {        "non_field_errors": [            "Invalid data. Expected a dictionary, but got int."        ]    }}

这个错误是因为 添加的时的数据是int型  但是pub不是int类型字段 

所以需要在serializer的Book中添加

post_pub = serializers.IntegerField()   #写入时   post    post_authors = serializers.ListField()

报错

'Book' object has no attribute 'post_pub'. 在发出get请求时 没有post_pub字段 这时需要在字段里填写
read_only=True   #在读的时候   get
write_only=True  #在写入的时候  post
pub = PublisherSerializers(read_only=True)    authors = serializers.SerializerMethodField(read_only=True)   #读的时候   get    post_pub = serializers.IntegerField(write_only=True)   #写入时   post    post_authors = serializers.ListField(write_only=True)

再继续添加  

 
添加

报错

`create()` must be implemented. 需要执行'create'方法
def create(self, validated_data):          #validated_data 是传过来的所有数据        book_obj = models.Book.objects.create(            title=validated_data['title'],            price=validated_data['price'],            pub_date=validated_data['pub_date'],            pub_id=validated_data['post_pub'],        )        book_obj.authors.set(validated_data['post_authors'])        return book_obj

 

put请求

先设计urls地址   因为需要知道是需要修改的具体id  需要再单独写一个视图

class BookView(APIView):    def get(self, request, pk, *args, **kwargs):        book_obj = models.Book.objects.filter(pk=pk).first()        ser_obj = BookSerializers(book_obj)        return Response(ser_obj.data)

这是拿到的一个对象   然后

def put(self, request, pk, *args, **kwargs):        book_obj = models.Book.objects.filter(pk=pk).first()        ser_obj = BookSerializers(instance=book_obj,data=request.data)        if ser_obj.is_valid():            ser_obj.save()            return Response(ser_obj.data)        return Response(ser_obj.errors)
 
更新

报错

`update()` must be implemented. 需要'update'这个方法来更新 在serializer中写
def update(self, instance, validated_data): #instance 是要修改的数据                                                                        #validated_data是提交的数据        instance.title = validated_data['title']        instance.price = validated_data['price']        instance.pub_date = validated_data['pub_date']        instance.pub_id = validated_data['post_pub']        instance.save()        instance.authors.set(validated_data['post_authors'])        return instance

这样是只能修改所有数据  

我想要的是提交我想要修改的数据就没办法改了

允许部分进行修改

ser_obj = BookSerializers(instance=book_obj, data=request.data, partial=True)

还是报错

这就可以用get取  取不到 就添加一个默认值

def update(self, instance, validated_data):  # instance 是要修改的数据   validated_data是提交的数据        instance.title = validated_data.get('title', instance.title)        instance.price = validated_data.get('price', instance.price)        instance.pub_date = validated_data.get('pub_date', instance.pub_date)        instance.pub_id = validated_data.get('post_pub', instance.pub_id)        instance.save()        instance.authors.set(validated_data.get('post_authors', instance.authors.all()))        return instance

然后修改数据

{

"title": "没事就念念经77777",
}

报错

 "detail": "JSON parse error - Expecting property name enclosed in double quotes: line 3 column 1 (char 30)"

原因就是因为 修改的数据后面有一个逗号

delete请求

def delete(self, request, pk, *args, **kwargs):        obj = models.Book.objects.filter(pk=pk).first()        if obj:            obj.delete()            return Response({'smg': '删除成功'})        return Response({'error': '删除的数据不存在'})

 

在BookListView中有 get post

在BookView中有 get put delete

 

较简洁的使用方法

在写serializer时的serializers.Serializer, 感觉就和 forms.form比较相似  

那有forms.ModelForm也就是有serializers.ModelSerializer            

对上面进行补充   is_valid()是对数据进行校验

在这里可以自己来设置校验的约束

def validate_title(value):    if 'li' in value:        raise serializers.ValidationError

然后在title放约束条件 也就是上面我自己定义的这个

title = serializers.CharField(validators=[validate_title])

这样就可以了 

修改数据

{    "title": "没事li就念经"}

这样就报错了  因为在修改的数据中有li 当.is_valid()的时候就会调用validate_title方法  发现里面有li就抛出错误.

HTTP 200 OKAllow: GET, PUT, DELETE, HEAD, OPTIONSContent-Type: application/jsonVary: Accept{    "title": [        "Invalid input."    ]}

这就是一个简单的

局部钩子   

用上局部钩子会 更灵活

在class中定义局部钩子   title是字段名

def validate_title(self, value):        if 'li' in value:            raise serializers.ValidationError

修改数据 title中有li

报错

NOT NULL constraint failed: app01_book.title 为空
def validate_title(self, value):        if 'li' in value:            raise serializers.ValidationError        return value

给钩子一个返回值就可以正常使用了

全局钩子

def validate(self, attrs):        return attrs

接下里就是ModelSerializer

ModelSerializer的基础使用

class BookSerializer(serializers.ModelSerializer):    class Meta:        model = models.Book        fields = '__all__'

这样就 直接拿到了 Book表中的 所有信息   但是外键和多对多的字段 拿到的都是id

class BookSerializer(serializers.ModelSerializer):    class Meta:        model = models.Book        fields = '__all__'        depth = 1

depth是深度的意思   这样就拿到了 所有的数据

虽然拿到了 但是也只是能在 显示中方便使用   在提交数据时是没办法使用的

所以这种方法不好用     去掉这个这个方法  还是拿到的是id  id就是book表中数据库的数据  

可以把这些特殊的字段 重写一下

class BookSerializer(serializers.ModelSerializer):    pub_info = PublisherSerializers()     #重写pub字段    class Meta:        model = models.Book        fields = '__all__'        # depth = 1

报错

'Book' object has no attribute 'pub_info'. 是因为没有pub_info的这个字段   之前重写字段的时候可以使用是因为在 重写的字段后面加上了write_only=True
class BookSerializer(serializers.ModelSerializer):    pub_info = serializers.SerializerMethodField()     #重写pub字段    def get_pub_info(self,obj):        return PublisherSerializers(obj.pub).data    class Meta:        model = models.Book        fields = '__all__'        # depth = 1

这样就可以了

在继续重写 多对多字段

class BookSerializer(serializers.ModelSerializer):    pub_info = serializers.SerializerMethodField()  # 重写pub字段    authors_info = serializers.SerializerMethodField()    def get_pub_info(self, obj):        return PublisherSerializers(obj.pub).data    def get_authors_info(self, obj):        return AuthorSerializers(obj.authors.all(), many=True).data    class Meta:        model = models.Book        fields = '__all__'        # depth = 1

这样就可以了  但是显示的时候 pub和authors字段还显示   pub_info 和authors_info应该在read是使用  pub和authors应该在write时使用

class BookSerializer(serializers.ModelSerializer):    pub_info = serializers.SerializerMethodField(read_only=True)  # 重写pub字段    authors_info = serializers.SerializerMethodField(read_only=True)    def get_pub_info(self, obj):        return PublisherSerializers(obj.pub).data    def get_authors_info(self, obj):        return AuthorSerializers(obj.authors.all(), many=True).data    class Meta:        model = models.Book        fields = '__all__'        # depth = 1        extra_kwargs = {            'pub': {
'write_only': True}, 'authors': {
'write_only': True}, }

这样就可以了  比较上一种方法 这种相对简单一些  不用再写那么多方法了  

但是最后要注意的是  与之前相比在添加的时候  post_pub就应该换成pub了  

 

转载于:https://www.cnblogs.com/lzlllll/p/11247156.html

转载地址:https://blog.csdn.net/weixin_30791095/article/details/97944430 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:The account '' has no team with ID ''
下一篇:青蛙的约会

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年03月12日 16时04分19秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

mplayer-php,mplayer+smplayer 前后端播放器安装 2019-04-21
oracle昨日时间,。。今日,昨日,上周,本月,本年,按时间统计总金额 2019-04-21
php验证卡号,PHP验证信用卡卡号是否正确函数 2019-04-21
mpvue微信小程序动画_推荐两个微信小程序开发框架 2019-04-21
固态硬盘分为哪几种_零基础玩转固态硬盘 深度排雷 买SSD掌握这些就够了 2019-04-21
调python返回图片_Python异常处理,3个好习惯分享给你 2019-04-21
15拆解_收藏:15款劲芯微芯片无线充产品拆解 2019-04-21
弹出u盘_都说:U盘直接拔出不会丢失文件,“安全弹出”形同虚设,对吗? 2019-04-21
怎么查看elementui版本_2021新年 Vue3.0 + Element UI 尝鲜小记 2019-04-21
adreno630gpu参数_小米8搭载Adreno 630图形处理器 比荣耀play上的GPU Turbo更成熟 2019-04-21
带bitlocker解密的pe_如何在PE下解锁bitlocker 2019-04-21
lj245a引脚功能图_谁找到74254,74LS245芯片引脚的功能和功能图啊? 2019-04-21
sts 创建webservice项目_通过eclipse将Java生成webservice | 学步园 2019-04-21
python数字字符串和数字相加_数字和字符串 2019-04-21
python风控模型举例_一文搞定风控模型6大核心指标(附代码) 2019-04-21
java arraylist 写入文件_java-将自定义对象的ArrayList写入文件 2019-04-21
ice glacier2 java_ICE提纲之demo/Glacier2/callback(跨网回调) 2019-04-21
java 转发上传文件_java 后台请求其他接口转发文件 2019-04-21
Java get set 同步_java – getResultSet()“每个结果只能调用一次” 2019-04-21
java jmx 配置_为什么在配置JMX时Java打开3个端口? 2019-04-21