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
            ]
        }
    }
]
View Code

灵活度不高 

 

 

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

 



posted @ 2019-07-25 20:32  老李,向我开炮  阅读(379)  评论(0编辑  收藏  举报