Django REST Framework详细介绍一下不使用DRF的序列化方式
目录:
前期准备
安装和配置
添加app和安装djangorestframework
$ django-admin startproject drf
$ python manage.py startapp drfdemo
$ pip install djangorestframework
setting配置
INSTALLED_APPS = [
...
'drfdemo',
'rest_framework',
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'djangodemo',
'USER': 'root',
'PASSWORD': '123456',
'HOST': '172.16.32.32',
'PORT': 3306,
}
}
init.py
import pymysql
pymysql.install_as_MySQLdb()
models字段
models.py
from django.db import models
__all__ = ["Book", "Publisher", "Author"]
class Book(models.Model):
title = models.CharField(max_length=32)
CHOICES = ((1, "Python"), (2, "Linux"), (3, "Golang"))
category = models.IntegerField(choices=CHOICES)
pub_time = models.DateField()
publisher = models.ForeignKey(to="Publisher")
authors = models.ManyToManyField(to="Author")
class Publisher(models.Model):
title = models.CharField(max_length=32)
class Author(models.Model):
name = models.CharField(max_length=32)
admin.py
from django.contrib import admin
from . import models
for table in models.__all__:
admin.site.register(getattr(models, table))
同步数据库设计
python manage.py makemigrations
python manage.py migrate
在不使用djangorestframework的情况下
直接使用视图
创建超级用户createsuperuser然后直接添加数据
views.py
from django.http import HttpResponse
from django.views import View
from .models import Book
import json
class BookView(View):
def get(self, request):
book_queryset = Book.objects.values("id", "title")
book_list = list(book_queryset)
ret = json.dumps(book_list)
return HttpResponse(ret)
url配置
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include('drfdemo.urls'))
]
和
from django.conf.urls import url
from .views import BookView
urlpatterns = [
url(r'book/', BookView.as_view())
]
启动直接请求/api/book/
接口,返回如下结果
[{"id": 1, "title": "Django REST Framework(\u7b2c\u4e8c\u7248)"}]
只需要对对应请求方法实现对应的操作并返回数据即可
正常获取到的QuerySet类型,可以直接通过list()变为列表,通过json.dumps()序列化,然后通过HttpResponse()返回
但是会遇到很多问题
- 中文文字是ascii码的,需要在json.dumps()的时候传入
ensure_ascii=False
- 如果是datetime类型的时间,无法进行json.dumps(),需要直接使用JsonResponse()并传入
safe=False
- 直接使用JsonResponse(),中文文字还是ascii码,需要JsonResponce()的时候传入
json_dumps_params={"ensure_ascii":False}
JsonResponse继承了HttpResponse,调用了json.dumps(data, cls=encoder, **json_dumps_params)
另外加一点问什么能序列化datatime,cls不是默认jsonencoder,而是使用的DjangoJSONEncoder,DjangoJSONEncoder继承jsonencoder,而重写了default方法,使用isinstance(o, datetime)
判断数据是否为datetime.datetime类型,datetime.date类型或者datetime.time类型
所以view修改一下就是
from django.http import HttpResponse, JsonResponse
from django.views import View
from .models import Book
import json
class BookView(View):
def get(self, request):
book_queryset = Book.objects.values("id", "title")
book_list = list(book_queryset)
# ret = json.dumps(book_list, ensure_ascii=False)
# return HttpResponse(ret)
return JsonResponse(book_list, safe=False, json_dumps_params={"ensure_ascii": False})
也可以自定义解析器
class BooksView(View):
def get(self, request):
book_list = Book.objects.values("id", "title", "chapter", "pub_time", "publisher")
book_list = list(book_list)
# 如果我们需要取外键关联的字段信息 需要循环获取外键 再去数据库查然后拼接成我们想要的
ret = []
for book in book_list:
pub_dict = {}
pub_obj = Publish.objects.filter(pk=book["publisher"]).first()
pub_dict["id"] = pub_obj.pk
pub_dict["title"] = pub_obj.title
book["publisher"] = pub_dict
ret.append(book)
ret = json.dumps(book_list, ensure_ascii=False, cls=MyJson)
return HttpResponse(ret)
# json.JSONEncoder.default()
# 解决json不能序列化时间字段的问题
class MyJson(json.JSONEncoder):
def default(self, field):
if isinstance(field, datetime.datetime):
return field.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(field, datetime.date):
return field.strftime('%Y-%m-%d')
else:
return json.JSONEncoder.default(self, field)