rest_framwork框架的简单使用
from django.http.response import JsonResponse class 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 serializers class BookListView(View): def get(self, request, *args, **kwargs): all_books = models.Book.objects.all() data = serializers.serialize('json', all_books) return HttpResponse(data)
得到的结果
[ { "model": "app01.book", "pk": 1, "fields": { "title": "\u6ca1\u4e8b\u5c31\u5ff5\u7ecf", "price": "999.99", "pub_date": "2019-01-01T10:10:10Z", "pub": 1, "authors": [ 1, 4 ] } }, { "model": "app01.book", "pk": 2, "fields": { "title": "\u4e09\u6253\u767d\u9aa8\u7cbe", "price": "666.66", "pub_date": "2019-01-01T10:10:10Z", "pub": 2, "authors": [ 1 ] } }, { "model": "app01.book", "pk": 3, "fields": { "title": "\u5077\u5403\u4eba\u53c2\u679c", "price": "2323.23", "pub_date": "2019-01-01T10:10:10Z", "pub": 3, "authors": [ 2 ] } }, { "model": "app01.book", "pk": 4, "fields": { "title": "\u5927\u6218\u6d41\u6c99\u6cb3", "price": "0.88", "pub_date": "2019-01-01T10:10:10Z", "pub": 1, "authors": [ 3 ] } } ]
灵活度不高
django的rest_framwork框架 做序列化
get请求
需要有djangorestframework包
from rest_framework.views import APIView from rest_framework.response import Response class 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 serializers class BookSerializers(serializers.Serializer): title = serializers.CharField() price = serializers.DecimalField(max_digits=6, decimal_places=2) pub_data = serializers.DateTimeField()
在views中
from app01.serializer import BookSerializers class 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
{ "title": "没事就念经", "price": "999.99", "pub_date": "2019-01-01T10:10:10Z", "pub": { "name": "冰棍" }, "authors": [ { "name": "唐僧" }, { "name": "沙和尚" } ] },
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)
{ "title": "没事就念经", "price": "999.99", "pub_date": "2019-01-01T10:10:10Z", "pub": 1, "authors": [ 1, 2 ] }
报错
HTTP 200 OK Allow: GET, POST, HEAD, OPTIONS Content-Type: application/json Vary: 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)
再继续添加
{ "title": "没事就念经", "price": "999.99", "pub_date": "2019-01-01T10:10:10Z", "post_pub": 1, "post_authors": [ 1, 2 ] }
报错
`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)
{ "title": "没事就念经", "price": "999.99", "pub_date": "2019-01-01T10:10:10Z", "post_pub": 1, "post_authors": [ 1, 2 ] }
报错
`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