一、快速实例

Quickstart

http://www.cnblogs.com/yuanchenqi/articles/8719520.html

  1. restful协议
  2.  
  3. ---- 一切皆是资源,操作只是请求方式
  4.  
  5. ----book表增删改查
  6. /books/ books
  7. /books/add/ addbook
  8. /books/(\d+)/change/ changebook
  9. /books/(\d+)/delete/ delbook
  10.  
  11. ----book表增删改查 url里面不能出现动词!!
  12. /books/ -----get books ----- 返回当前所有数据
  13. /books/ -----post books ----- 返回提交数据
  14.  
  15. /books/(\d+)-----get bookdetail ----- 返回当前查看的单条数据
  16. /books/(\d+)-----put bookdetail ----- 返回更新数据
  17. /books/(\d+)-----delete bookdetail ----- 返回空
  18.  
  19. http://www.cnblogs.com/yuanchenqi/articles/8719520.html
  20. http://www.django-rest-framework.org/tutorial/quickstart/#quickstart
  21.  
  22. class Books(View):
  23. def get(self,request):
  24. pass # 查看所有书籍
  25.  
  26. def post(self,request):
  27. pass # 添加书籍
  28.  
  29. class BooksDetail(View):
  30. def get(self,request,id):
  31. pass # 查看具体书籍
  32.  
  33. def put(self,request,id):
  34. pass # 更新某本书籍
  35.  
  36. def delete(self,request,id):
  37. pass # 删除某本书籍
  38.  
  39. http://www.django-rest-framework.org/tutorial/quickstart/#quickstart
  40. restframework(Django) app
  41. pip install django
  42. pip install djangorestframework
  43.  
  44. ----针对数据:json
  45.  
  46. (1)Django的原生request:
  47.  
  48. 浏览器 ------------- 服务器
  49.  
  50. "GET url?a=1&b=2 http/1.1\r\user_agent:Google\r\ncontentType:urlencoded\r\n\r\n"
  51. "POST url http/1.1\r\user_agent:Google\r\ncontentType:urlencoded\r\n\r\na=1&b=2"
  52.  
  53. request.body: a=1&b=2
  54. request.POST:
  55. if contentType:urlencoded:
  56. a=1&b=2----->{"a":1,"b":2}
  57.  
  58. (2)restframework 下的APIView
  59.  
  60. (3)
  61. class PublishSerializers(serializers.Serializer):
  62. name=serializers.CharField()
  63. email=serializers.CharField()
  64.  
  65. PublishSerializers(queryset,many=true)
  66. PublishSerializers(model_obj)
  67.  
  68. ---------------------------
  69.  
  70. 总结:
  71. 1 reuqest类----源码
  72.  
  73. 2 restframework 下的APIView--源码
  74.  
  75. url(r'^books/$', views.BookView.as_view(),name="books")# View下的view
  76.  
  77. books/一旦被访问: view(request) ------APIView: dispatch()
  78.  
  79. 3 def dispatch():
  80.  
  81. 构建request对象
  82. self.request=Request(request)
  83. self.request._request
  84. self.request.GET # get
  85. self.request.data # POST PUT
  86.  
  87. 分发----if get请求:
  88. if request.method.lower() in self.http_method_names:
  89. handler = getattr(self, request.method.lower(),
  90. self.http_method_not_allowed)
  91. else:
  92. handler = self.http_method_not_allowed
  93.  
  94. response = handler(request, *args, **kwargs) # self.get(request, *args, **kwargs)
  95.  
  96. return response
  97.  
  98. 4 序列化类
  99. # from django.core import serializers
  100. # ret=serializers.serialize("json",publish_list)
  101.  
  102. restframework下的序列类 BookModelSerializers
  103. queryset或者model对象序列成一json数据
  104. bs=BookModelSerializers(book_list,many=True,context={'request': request})
  105. bs=BookModelSerializers(book,context={'request': request})
  106.  
  107. 还可以做校验数据,json-------》queryset/model-->记录
  108.  
  109. bs=BookModelSerializers(data=request.data)
  110. if bs.is_valid():
  111. print(bs.validated_data)
  112. bs.save() # 重写create方法
  113. 5 操作数据:
  114.  
  115. Book表为例
  116. class BookView(APIView):
  117. # 查看所有书籍
  118. def get(self,request):
  119. book_list=Book.objects.all()
  120. bs=BookModelSerializers(book_list,many=True,context={'request': request})
  121. return Response(bs.data)
  122.  
  123. # 添加一本书籍
  124. def post(self,request):
  125. # post请求的数据
  126. bs=BookModelSerializers(data=request.data)
  127. if bs.is_valid():
  128. print(bs.validated_data)
  129. bs.save()# create方法
  130. return Response(bs.data)
  131. else:
  132. return Response(bs.errors)
  133.  
  134. class BookDetailView(APIView):
  135. # 查看一本书籍
  136. def get(self,request,id):
  137.  
  138. book=Book.objects.filter(pk=id).first()
  139. bs=BookModelSerializers(book,context={'request': request})
  140. return Response(bs.data)
  141. # 更新一本书籍
  142. def put(self,request,id):
  143. book=Book.objects.filter(pk=id).first()
  144. bs=BookModelSerializers(book,data=request.data)
  145. if bs.is_valid():
  146. bs.save()
  147. return Response(bs.data)
  148. else:
  149. return Response(bs.errors)
  150. # 删除某一本书籍
  151. def delete(self,request,id):
  152. Book.objects.filter(pk=id).delete()
  153.  
  154. return Response()
  155.  
  156. restframework
  157. 1 APIView
  158. 2 序列组件
  159. 3 视图、
  160. 4 组件(认证权限频率)
  161. 5 数据解析器
  162. 6 分页和Response

笔记

1、准备模型和路由

  models.py:

  1. from django.db import models
  2. # Create your models here.
  3.  
  4. class User(models.Model):
  5. name = models.CharField(max_length=32)
  6. pwd = models.CharField(max_length=32)
  7. type_choice = ((1, "普通用户"), (2, "VIP"), (3, "SVIP"))
  8. user_type = models.IntegerField(choices=type_choice, default=1)
  9.  
  10. class Token(models.Model):
  11. user = models.OneToOneField("User", on_delete=models.CASCADE)
  12. token = models.CharField(max_length=128)
  13.  
  14. def __str__(self):
  15. return self.token
  16.  
  17. class Book(models.Model):
  18. title = models.CharField(max_length=32)
  19. price = models.IntegerField()
  20. pub_date = models.DateField()
  21. publish = models.ForeignKey("Publish", on_delete=models.CASCADE)
  22. authors = models.ManyToManyField("Author")
  23.  
  24. def __str__(self):
  25. return self.title
  26.  
  27. class Publish(models.Model):
  28. name = models.CharField(max_length=32)
  29. email = models.EmailField()
  30.  
  31. def __str__(self):
  32. return self.name
  33.  
  34. class Author(models.Model):
  35. name = models.CharField(max_length=32)
  36. age = models.IntegerField()
  37.  
  38. def __str__(self):
  39. return self.name

  urls.py:

  1. from django.contrib import admin
  2. from django.urls import path
  3. from app01 import views
  4.  
  5. urlpatterns = [
  6. path('admin/', admin.site.urls),
  7. path('publishes/', views.PublishView.as_view())
  8. ]

2、安装djangorestframework

  1. pip install djangorestframework

3、添加'rest_framework'到我的settings.py中

  1. INSTALLED_APPS = (
  2. ...
  3. 'rest_framework',
  4. )

二、restframework下的APIView

1、Django的原生request

  1. class PublishView(View):
  2. def get(self, request):
  3. print('get', request.GET)
  4. return HttpResponse('123')
  5.  
  6. def post(self, request):
  7. print('post', request.POST)
  8. print('body', request.body)
  9. print(type(request))
  10. return HttpResponse('POST')

(1)request.GET

  访问地址http://127.0.0.1:8000/publishes/?a=3&c=7  ,打印得到get请求数据:<QueryDict: {'a': ['3'], 'c': ['7']}>。get请求类似形式如下:

  1. "GET url?a=1&b=2 http/1.1\r\user_agent:Google\r\ncontentType:urlencoded\r\n\r\n"

(2)request.POST和request.body

  在Postman提交post请求,打印结果如下所示:

  1. post <QueryDict: {'a': ['14'], 'b': ['9']}>
  2. body b'a=14&b=9'

  body放的是原数据,即报文,没有做任何解析。

  post会帮忙做contentType是否是urlencoded的判断,如果是的会帮忙将   a=1&b=2 转化为  {"a":1,"b":2} 。post请求类似形式如下:

  1. "POST url http/1.1\r\user_agent:Google\r\ncontentType:urlencoded\r\n\r\na=1&b=2"

(3)打印type(request)分析源码

  打印得到<class 'django.core.handlers.wsgi.WSGIRequest'>。可以引入WSGIRequest来查看源码:

  1. from django.core.handlers.wsgi import WSGIRequest

  关于post源码如下所示:

  1. class WSGIRequest(HttpRequest):
  2. def _get_post(self):
  3. if not hasattr(self, '_post'):
  4. self._load_post_and_files()
  5. return self._post
  6.  
  7. def _set_post(self, post):
  8. self._post = post
  9.  
  10. POST = property(_get_post, _set_post)

  处理请求的多种可能:

  1. def _load_post_and_files(self):
  2. """Populate self._post and self._files if the content-type is a form type"""
  3. if self.method != 'POST':
  4. self._post, self._files = QueryDict(encoding=self._encoding), MultiValueDict()
  5. return
  6. if self._read_started and not hasattr(self, '_body'):
  7. self._mark_post_parse_error()
  8. return
  9.  
  10. if self.content_type == 'multipart/form-data':...
  11.  
  12. elif self.content_type == 'application/x-www-form-urlencoded':
  13. self._post, self._files = QueryDict(self.body, encoding=self._encoding), MultiValueDict()
  14. else:
  15. self._post, self._files = QueryDict(encoding=self._encoding), MultiValueDict()

  如果content_type是urlencoded,post里面才会有QueryDict,将body里的内容做成字典的形式。

  如果content_type不是form-data也不是urlencoded,则QueryDict里没有值,一个空的字典。

2、引入APIView并分析源码

  1. from rest_framework.views import APIView

  进入rest_framework/view.py中查看APIView的源码:

(1)APIView继承的是django的View类

  1. class APIView(View):
  2. @classmethod
  3. def as_view(cls, **initkwargs):
  4. if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):...
  5.  
  6. view = super(APIView, cls).as_view(**initkwargs) # 执行父类View里的as_view方法,返回view
  7.  
  8. return csrf_exempt(view) # 返回的依然是View中的view方法

  因此访问publishes/地址后,执行views.PublishView.as_view(),返回的是view方法。VIew.view方法执行返回dispatch(),在这里优先执行子类的dispatch,因此APIView.dispatch(request)执行。

(2)APIView里的dispatch方法

  1. def initialize_request(self, request, *args, **kwargs):
  2. parser_context = self.get_parser_context(request)
  3.  
  4. # 实例化一个Request类的对象
  5. return Request(
  6. request,
  7. parsers=self.get_parsers(),
  8. authenticators=self.get_authenticators(),
  9. negotiator=self.get_content_negotiator(),
  10. parser_context=parser_context
  11. )
  12.  
  13. def dispatch(self, request, *args, **kwargs):
  14. """
  15. `.dispatch()` is pretty much the same as Django's regular dispatch,
  16. but with extra hooks for startup, finalize, and exception handling.
  17. """
  18. self.args = args
  19. self.kwargs = kwargs
  20.  
  21. # 用initialize将旧request构建为一个新的request
  22. request = self.initialize_request(request, *args, **kwargs)

  可以看到在dispatch中,使用initialize方法将旧的request构建为了一个新的request。在initialize_request中,返回实例化的Request类对象。

(3)观察Request类实例化时对request进行的操作

  1. class Request(object):
  2. def __init__(self, request, parsers=None, authenticators=None,
  3. negotiator=None, parser_context=None):
  4. self._request = request
  5. self._data = Empty
  6. self._files = Empty
  7. self._full_data = Empty # 默认为空
  8.  
  9. @property
  10. def data(self):
  11. if not _hasattr(self, '_full_data'):
  12. self._load_data_and_files()
  13. return self._full_data
  14.  
  15. def _load_data_and_files(self):
  16. """
  17. Parses the request content into `self.data`.
  18. """
  19. if not _hasattr(self, '_data'):
  20. self._data, self._files = self._parse()
  21. if self._files:
  22. self._full_data = self._data.copy()
  23. self._full_data.update(self._files)
  24. else:
  25. self._full_data = self._data
  26.  
  27. # if a form media type, copy data & files refs to the underlying
  28. # http request so that closable objects are handled appropriately.
  29. if is_form_media_type(self.content_type):
  30. self._request._post = self.POST
  31. self._request._files = self.FILES
  32.  
  33. def _parse(self):
  34. """
  35. Parse the request content, returning a two-tuple of (data, files)
  36.  
  37. May raise an `UnsupportedMediaType`, or `ParseError` exception.
  38. """
  39. media_type = self.content_type
  40. try:
  41. stream = self.stream
  42. except RawPostDataException:
  43. if not hasattr(self._request, '_post'):
  44. raise
  45. # If request.POST has been accessed in middleware, and a method='POST'
  46. # request was made with 'multipart/form-data', then the request stream
  47. # will already have been exhausted.
  48. if self._supports_form_parsing():
  49. return (self._request.POST, self._request.FILES)
  50. stream = None
  51.  
  52. if stream is None or media_type is None:
  53. if media_type and is_form_media_type(media_type):
  54. empty_data = QueryDict('', encoding=self._request._encoding)
  55. else:
  56. empty_data = {}
  57. empty_files = MultiValueDict()
  58. return (empty_data, empty_files)
  59.  
  60. parser = self.negotiator.select_parser(self, self.parsers)
  61.  
  62. if not parser:
  63. raise exceptions.UnsupportedMediaType(media_type)
  64.  
  65. try:
  66. parsed = parser.parse(stream, media_type, self.parser_context)
  67. except Exception:
  68. # If we get an exception during parsing, fill in empty data and
  69. # re-raise. Ensures we don't simply repeat the error when
  70. # attempting to render the browsable renderer response, or when
  71. # logging the request or similar.
  72. self._data = QueryDict('', encoding=self._request._encoding)
  73. self._files = MultiValueDict()
  74. self._full_data = self._data
  75. raise
  76.  
  77. # Parser classes may return the raw data, or a
  78. # DataAndFiles object. Unpack the result as required.
  79. try:
  80. return (parsed.data, parsed.files)
  81. except AttributeError:
  82. empty_files = MultiValueDict()
  83. return (parsed, empty_files)

Request类

  可以看到最终是通过_parse方法,进行解析器解析。

3、利用新的request取数据

  1. class PublishView(APIView):
  2. def get(self, request):
  3. print('request.data', request.data)
  4. print('request.data type', type(request.data))
  5. print('request._requet.GET', request._request.GET)
  6. print('request.GET', request.GET)
  7.  
  8. return HttpResponse('123')
  9.  
  10. def post(self, request):
  11. # 原生request支持的操作
  12. # print('post', request.POST)
  13. # print('body', request.body)
  14. # print(type(request))
  15. from django.core.handlers.wsgi import WSGIRequest
  16. # 新的request支持的操作
  17. print("request.data", request.data)
  18. print("request.data type", type(request.data))
  19.  
  20. return HttpResponse('POST')

(1)打印Postman发送的json格式POST请求

  

  控制台输出如下:

  1. request.data {'name': 'yuan', 'email': '123@qq.com'}
  2. request.data type <class 'dict'>

(2)打印Postman发送的urlencoded的POST请求

  

  控制台输出如下:

  1. request.data <QueryDict: {'a': ['14'], 'b': ['9']}>
  2. request.data type <class 'django.http.request.QueryDict'>

(3)打印Postman发送的get请求

  

  控制台输出如下:

  1. request.data <QueryDict: {}>
  2. request.data type <class 'django.http.request.QueryDict'>
  3. request._requet.GET <QueryDict: {'a': ['3'], 'c': ['7']}>
  4. request.GET <QueryDict: {'a': ['3'], 'c': ['7']}>

  说明只处理了POST请求的request.data,get请求获取数据必须通过request._request.GET,rest为了方便用户使用,也为request.GET做了重新赋值,因此也可以使用requet.GET获取数据。

  request.body只放请求体里的数据,get请求没有请求体,因此输出的是<QueryDict: {}>。

三、序列化

  python中的json包主要提供了dump,load来实现dict与字符串之间的序列化与反序列化。

  但是json包不能序列化django的models里面的对象实例。

1、序列化方式一:将QuerySet对象转化为数组套字典

  1. from django.shortcuts import render, HttpResponse
  2. from django.views import View
  3. from .models import Publish
  4. import json
  5.  
  6. class PublishView(View):
  7. def get(self, request):
  8. # QuerySet对象不能进行json序列化
  9. # 方式1:values(*field):调用者是queryset对象,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列
  10. # 再使用list()方法强转为列表,组成列表里面放字典的数据结构
  11. publish_list = list(Publish.objects.all().values("name", "email"))
  12.  
  13. return HttpResponse(json.dumps(publish_list))
  14.  
  15. def post(self, request):
  16. pass

  注意:

(1)values(*field):

  调用者是queryset对象,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列:

  <QuerySet [{'name': '橘子出版社', 'email': '456@qq.com'}, {'name': '苹果出版社', 'email': '123@qq.com'}]>

(2)list():

  将序列强行转化为数组:

  [{'name': '橘子出版社', 'email': '456@qq.com'}, {'name': '苹果出版社', 'email': '123@qq.com'}]

(3)json.dumps():

  json.dumps 用于将 Python 对象编码成 JSON 字符串。以下是python 原始类型向 json 类型的转化对照表:

  

2、序列化方式二:model_to_dict(obj)

(1)循环QuerySet构建可序列化数据结构

  1. from django.views import View
  2. from .models import Publish
  3. import json
  4.  
  5. class PublishView(View):
  6. def get(self, request):
  7. # QuerySet对象不能进行json序列化
  8. # 方式2:
  9. publish_list = Publish.objects.all()
  10. temp = []
  11. for obj in publish_list:
  12. temp.append({
  13. "name": obj.name,
  14. "name": obj.email
  15. })
  16. print(temp) # [{'name': '456@qq.com'}, {'name': '123@qq.com'}]
  17.  
  18. return HttpResponse(json.dumps(temp))
  19.  
  20. def post(self, request):
  21. pass

  这样写的问题是有多少字段就要加多少个字段,而且如果不知道是哪张表或者有哪些字段,就无法构建数据。

(2)引入model_to_dict完成改写

  model_to_dict是用于将model对象转换为字典的方法。

  1. from django.views import View
  2. from .models import Publish
  3. import json
  4.  
  5. class PublishView(View):
  6. def get(self, request):
  7. # QuerySet对象不能进行json序列化
  8. # 方式2:
  9. from django.forms.models import model_to_dict
  10. publish_list = Publish.objects.all()
  11. temp = []
  12. for obj in publish_list:
  13. temp.append(model_to_dict(obj))
  14. print(temp) # [{'name': '456@qq.com'}, {'name': '123@qq.com'}]
  15.  
  16. return HttpResponse(json.dumps(temp))

(3)测试理解model_to_dict方法

  在pycharm的python console测试:

  1. >>>from django.forms.models import model_to_dict
  2. >>>from app01 import models
  3. >>>print(models)
  4. <module 'app01.models' from '/Users/hqs/PycharmProjects/restDemo/app01/models.py'>
  5. >>>obj = models.Publish.objects.all()
  6. >>>print(obj)
  7. <QuerySet [<Publish: 橘子出版社>, <Publish: 苹果出版社>]>
  8. >>>obj = models.Publish.objects.filter(pk=2).first()
  9. >>>obj # obj是一个model对象
  10. <Publish: 橘子出版社>
  11.  
  12. >>>model_to_dict(obj)
  13. {'id': 2, 'name': '橘子出版社', 'email': '456@qq.com'}

  由此可见有几个字段就转化为几个键值对的字典。

3、序列化方式三:serializers.serizlize("json",publish_list)

  serializers是django的序列化组件。

  1. from django.views import View
  2. from .models import Publish
  3. import json
  4.  
  5. class PublishView(View):
  6. def get(self, request):
  7. # QuerySet对象不能进行json序列化
  8. # 方式3:
  9. from django.core import serializers
  10. publish_list = Publish.objects.all()
  11. ret = serializers.serialize("json", publish_list)
  12.  
  13. return HttpResponse(json.dumps(ret))
  14.  
  15. def post(self, request):
  16. pass

  注意:

(1)__init__.py中serialize函数原型

  1. def serialize(format, queryset, **options):
  2. """
  3. Serialize a queryset (or any iterator that returns database objects) using
  4. a certain serializer.
  5. """
  6. s = get_serializer(format)()
  7. s.serialize(queryset, **options)
  8. return s.getvalue()

  传递给 serialize 方法的参数有二:一个序列化目标格式,另外一个是序列化的对象QuerySet. (事实上,第二个参数可以是任何可迭代的Django Model实例,但它很多情况下就是一个QuerySet).

(2)序列化后数据组织形式

  1. "[{\"model\": \"app01.publish\", \"pk\": 2, \"fields\": {\"name\": \"\\u6a58\\u5b50\\u51fa\\u7248\\u793e\", \"email\": \"456@qq.com\"}}, {\"model\": \"app01.publish\", \"pk\": 3, \"fields\": {\"name\": \"\\u82f9\\u679c\\u51fa\\u7248\\u793e\", \"email\": \"123@qq.com\"}}]"

4、序列化方式四:(推荐)rest_framework  serializers

  1. from django.views import View
  2. from .models import Publish
  3. import json
  4. from rest_framework import serializers
  5.  
  6. class PublishSerializers(serializers.Serializer):
  7. """为QuerySet做序列化"""
  8. name = serializers.CharField()
  9. email = serializers.CharField()
  10.  
  11. class PublishView(View):
  12. def get(self, request):
  13. # 方式4:
  14. publish_list = Publish.objects.all()
  15. ret = PublishSerializers(publish_list, many=True) # 描述是model对象还是QuerySet True:queryset
  16. return HttpResponse(json.dumps(ret))
  17.  
  18. def post(self, request):
  19. pass

  注意:

(1)分析继承了Serializers的子类PublishSerializers

  1. >>>from app01.views import PublishSerializers
  2. >>>publish_list = models.Publish.objects.all()
  3. >>>PublishSerializers(publish_list, many=True) # 描述是model对象还是QuerySet
  4. PublishSerializers(<QuerySet [<Publish: 橘子出版社>, <Publish: 苹果出版社>]>, many=True):
  5. name = CharField()
  6. email = CharField()
  7. >>>ps = PublishSerializers(publish_list, many=True)
  8. >>>ps.data
  9. [OrderedDict([('name', '橘子出版社'), ('email', '456@qq.com')]), OrderedDict([('name', '苹果出版社'), ('email', '123@qq.com')])]

(2)Serializer是对QuerySet和model对象做序列化的

  在序列化时,第一个参数传递要序列化的对象,第二个参数many是向组件声明到底是model对象还是QuerySet。

  many=True:QuerySet      many=False:model对象(默认)

四、restframe序列化

1、序列化get请求

  1. from django.shortcuts import render, HttpResponse
  2. from django.views import View
  3. from .models import *
  4. import json
  5. from rest_framework import serializers
  6. from rest_framework.views import APIView
  7. from rest_framework.response import Response
  8.  
  9. class BookSerializers(serializers.Serializer):
  10. title = serializers.CharField(max_length=32)
  11. price = serializers.IntegerField()
  12. pub_date = serializers.DateField()
  13. publish = serializers.CharField(source="publish.name")
  14. # authors = serializers.CharField(source="authors.all")
  15. authors = serializers.SerializerMethodField()
  16.  
  17. def get_authors(self, obj):
  18. temp = []
  19. for author in obj.authors.all():
  20. temp.append(author.name)
  21. return temp
  22.  
  23. class BookView(APIView):
  24. def get(self, request):
  25. book_list = Book.objects.all()
  26. bs = BookSerializers(book_list, many=True) # 序列化结果
  27.  
  28. # return HttpResponse(bs.data)
  29. return Response(bs.data)
  30.  
  31. def post(self):
  32. pass

注意:

(1)一对多、多对多字段配置source参数

  1. class BookSerializers(serializers.Serializer):
  2. title = serializers.CharField(max_length=32)
  3. price = serializers.IntegerField()
  4. pub_date = serializers.DateField()
  5. publish = serializers.CharField(source="publish.name")
  6. authors = serializers.CharField(source="authors.all")
  7.  

  配置了source='publish.name'参数后,BookSerializers在序列化时,"publish"不再是取str(obj.publish),而是取obj.publish.name。页面显示如下所示:

  

  可以看到source字段在一对多字段比较好用,多对多字段显示为QuerySet,显示不够美观。

(2)引入rest_framework避免浏览器访问报错

  在settings.py引入应用rest_framework:

  1. INSTALLED_APPS = [
  2. 'django.contrib.admin',
  3. ......
  4. 'app01.apps.App01Config',
  5. 'rest_framework',
  6. ]

  显示效果:

  

(3)针对多对多字段使用SerializerMethodField

  source字段在一对多字段比较好用,多对多字段显示为QuerySet,显示不够美观。

  1. class BookSerializers(serializers.Serializer):
  2.  
  3. authors = serializers.SerializerMethodField()
  4.  
  5. def get_authors(self, obj):
  6. temp = []
  7. for author in obj.authors.all():
  8. temp.append(author.name)
  9. return temp

  BookSerializers在序列化时,"authors"不再是取obj.authors或者obj.authors.all(),而是取get_authors(obj)的返回值。注意这个方法必须是“get_"拼接配置了SerializerMethodField的字段。显示效果如下:

  

2、ModelSerializer(类似ModelForm)

  需要对django model 的实例进行序列化。ModelSerializer 类提供了一个捷径让你可以根据 Model 来创建 Serializer。

  1. class BookModelSerializers(serializers.ModelSerializer):
  2. class Meta:
  3. # 帮忙转换没有自己写的字段
  4. model = Book
  5. fields = "__all__"
  6.  
  7. publish = serializers.CharField(source="publish.name")
  8. authors = serializers.SerializerMethodField()
  9.  
  10. def get_authors(self, obj):
  11. temp = []
  12. for author in obj.authors.all():
  13. temp.append(author.name)
  14. return temp
  15.  
  16. class BookView(APIView):
  17. def get(self, request):
  18. book_list = Book.objects.all()
  19. bs = BookModelSerializers(book_list, many=True) # 序列化结果
  20. return Response(bs.data)
  21.  
  22. def post(self):
  23. pass

注意:

(1)ModelSerializer 类和 Serializer 类一样,不过添加了以下功能:

  • 它会基于 model 自动创建一些字段
  • 它会自动生成一些验证,比如 unique_together 验证。
  • 它包含简单的默认的 create() 和 update()

(2)fileds="__all__"帮忙转换所有字段

  1. class BookModelSerializers(serializers.ModelSerializer):
  2. class Meta:
  3. # 帮忙转换没有自己写的字段
  4. model = Book
  5. fields = "__all__"

  显示效果:

  

(3)给publish和authors字段做自定义配置

  1. class BookModelSerializers(serializers.ModelSerializer):
  2. class Meta:
  3. # 帮忙转换没有自己写的字段
  4. model = Book
  5. fields = "__all__"
  6.  
  7. publish = serializers.CharField(source="publish.name")
  8. authors = serializers.SerializerMethodField()
  9.  
  10. def get_authors(self, obj):
  11. temp = []
  12. for author in obj.authors.all():
  13. temp.append(author.name)
  14. return temp

  显示效果如下所示:

  

3、提交POST请求

  BookModelSerializers也可以将json数据转为QuerySet.

  1. class BookView(APIView):
  2. def get(self, request):...
  3.  
  4. def post(self, request):
  5. # POST请求的数据
  6. bs = BookModelSerializers(data=request.data)
  7. if bs.is_valid(): # 验证数据是否合格
  8. print(bs.validated_data)
  9. bs.save() # create方法
  10. return Response(bs.data) # 当前添加的数据
  11. else:
  12. return Response(bs.errors)

(1)不做自定义配置情况下提交

  1. class BookModelSerializers(serializers.ModelSerializer):
  2. class Meta:
  3. # 帮忙转换没有自己写的字段
  4. model = Book
  5. fields = "__all__"

  在Postman提交json POST请求:

  

  注意多对多字段一定要用列表组织数据。

(2)return Response(bs.data)返回的是当前添加数据

  提交POST请求后,当前添加数据显示如下:

  

4、重写save中的create方法

  前面提交POST请求时,将BookModelSerializers去除了自定义配置。这因为ModelSerializer的create方法不支持source的用法。因此必须还自定义一个create方法。

  1. class BookModelSerializers(serializers.ModelSerializer):
  2. class Meta:
  3. # 帮忙转换没有自己写的字段
  4. model = Book
  5. fields = "__all__"
  6.  
  7. publish = serializers.CharField(source="publish.pk")
  8.  
  9. def create(self, validated_data):
  10. print(validated_data) # {'publish': {'name': '1'}, 'title': 'go', 'price': 123, 'pub_date': datetime.date(2012, 12, 12)}
  11. authors = validated_data['authors']
  12. # 添加记录
  13. book_obj = Book.objects.create(title=validated_data["title"], price=validated_data["price"],
  14. pub_date=validated_data["pub_date"], publish_id=validated_data["publish"]["pk"])
  15. book_obj.authors.add(*authors) # 添加多对多的方式
  16. return book_obj
  17.  
  18. class BookView(APIView):
  19. def get(self, request):
  20. book_list = Book.objects.all()
  21. bs = BookModelSerializers(book_list, many=True) # 序列化结果
  22.  
  23. # return HttpResponse(bs.data)
  24. return Response(bs.data)
  25.  
  26. def post(self, request):
  27. # POST请求的数据
  28. bs = BookModelSerializers(data=request.data)
  29. if bs.is_valid(): # 验证数据是否合格
  30. print(bs.validated_data)
  31. bs.save() # create方法
  32. return Response(bs.data) # 当前添加的数据
  33. else:
  34. return Response(bs.errors)

  提交POST请求显示效果如下:

  

5、单条数据的GET\PUT\DELETE请求

  1. class BookDetailView(APIView):
  2.  
  3. def get(self, request, id):
  4. book_obj = Book.objects.filter(pk=id).first()
  5. print(book_obj)
  6. bs = BookModelSerializers(book_obj)
  7. return Response(bs.data) # 查看的单条数据
  8.  
  9. def put(self, request, id):
  10. book_obj = Book.objects.filter(pk=id).first()
  11. bs = BookModelSerializers(book_obj, data=request.data) # 做更新操作
  12. if bs.is_valid(): # 校验更新数据是否有问题
  13. bs.save() # ModelSerializer类的update方法
  14. return Response(bs.data) # 查看更新的数据
  15. else:
  16. return HttpResponse(bs.errors)
  17.  
  18. def delete(self, reqeust, book_id):
  19. Book.objects.filter(pk=book_id).delete()
  20. return Response() # 删除操作返回空

  注意:

(1)配置url

  1. from django.contrib import admin
  2. from django.urls import path, re_path
  3. from app01 import views
  4.  
  5. urlpatterns = [
  6. path('admin/', admin.site.urls),
  7. path('publishes/', views.PublishView.as_view()),
  8. re_path(r'^books/$', views.BookView.as_view()),
  9. re_path(r'^books/(\d+)/$', views.BookDetailView.as_view())
  10. ]

(2)将BookModelSerializers迁移到新建文件夹解耦

  1. from rest_framework import serializers
  2. from .models import *
  3.  
  4. class BookModelSerializers(serializers.ModelSerializer):
  5. class Meta:
  6. # 帮忙转换没有自己写的字段
  7. model = Book
  8. fields = "__all__"
  9.  
  10. # publish = serializers.CharField(source="publish.pk")
  11. # authors = serializers.SerializerMethodField()
  12.  
  13. # def get_authors(self, obj):
  14. # temp = []
  15. # for author in obj.authors.all():
  16. # temp.append(author.name)
  17. # return temp
  18.  
  19. # def create(self, validated_data):
  20. # print(validated_data) # {'publish': {'name': '1'}, 'title': 'go', 'price': 123, 'pub_date': datetime.date(2012, 12, 12)}
  21. # authors = validated_data['authors']
  22. # # 添加记录
  23. # book_obj = Book.objects.create(title=validated_data["title"], price=validated_data["price"],
  24. # pub_date=validated_data["pub_date"], publish_id=validated_data["publish"]["pk"])
  25. # book_obj.authors.add(*authors) # 添加多对多的方式
  26. # return book_obj

(3)/books/(\d+)  —— get请求 :返回当前查看的单条数据

  

(4)/books/(\d+)——put请求:返回更新数据

  

(5)/book/(\d+)——delete请求:返回空

  

  再次发送get请求可以发现id=4的这条数据已经删除了。

6、超链接API:Hyperlinked

  1. class PublishModelSerializers(serializers.ModelSerializer):
  2. class Meta:
  3. model = Publish
  4. fields = "__all__"
  5.  
  6. publish = serializers.HyperlinkedIdentityField(
  7. view_name='detail_publish', # detail_publish:url别名
  8. lookup_field="publish_id", # publish_id:url中(\d+)的值
  9. lookup_url_kwarg="pk") # pk:命名分组名称

(1)urls.py配置修改:用name取别名

  1. from django.contrib import admin
  2. from django.urls import path, re_path
  3. from app01 import views
  4.  
  5. urlpatterns = [
  6. path('admin/', admin.site.urls),
  7. re_path(r'^publishes/$', views.PublishView.as_view(), name="publish"),
  8. re_path(r'^publishes/(\d+)/$', views.PublishDetailView.as_view(), name="detail_publish"),
  9.  
  10. re_path(r'^books/$', views.BookView.as_view(), name="books"),
  11. re_path(r'^books/(\d+)/$', views.BookDetailView.as_view(), name="detail_book")
  12. ]

(2)urls.py配置修改:命名分组

  命名分组就是给具有默认分组编号的组另外再给一个别名。命名分组的语法格式如下:

  1. (?P<name>正则表达式) #name是一个合法的标识符

  在这里给(\d+)做命名分组:

  1. from django.contrib import admin
  2. from django.urls import path, re_path
  3. from app01 import views
  4.  
  5. urlpatterns = [
  6. path('admin/', admin.site.urls),
  7. re_path(r'^publishes/$', views.PublishView.as_view(), name="publish"),
  8. re_path(r'^publishes/(?P<pk>\d+)/$', views.PublishDetailView.as_view(), name="detail_publish"),
  9.  
  10. re_path(r'^books/$', views.BookView.as_view(), name="books"),
  11. re_path(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view(), name="detail_book")
  12. ]

(3)添加context={"request": request}参数解决报错

  在使用了HyperlinkedIdentityField后,要求BookModelSerializers序列化时必须添加context={"request": request}

  1. class BookView(APIView):
  2. def get(self, request):
  3. book_list = Book.objects.all()
  4. bs = BookModelSerializers(book_list, many=True, context={"request": request}) # 序列化结果
  5.  
  6. # return HttpResponse(bs.data)
  7. return Response(bs.data)
  8.  
  9. def post(self, request):
  10. # POST请求的数据
  11. bs = BookModelSerializers(data=request.data)
  12. if bs.is_valid(): # 验证数据是否合格
  13. print(bs.validated_data)
  14. bs.save() # create方法
  15. return Response(bs.data) # 当前添加的数据
  16. else:
  17. return Response(bs.errors)
  18.  
  19. class BookDetailView(APIView):
  20.  
  21. def get(self, request, pk):
  22. book_obj = Book.objects.filter(pk=pk).first()
  23. print(book_obj)
  24. bs = BookModelSerializers(book_obj, context={"request": request})
  25. return Response(bs.data) # 查看的单条数据
  26.  
  27. def put(self, request, pk):
  28. book_obj = Book.objects.filter(pk=pk).first()
  29. bs = BookModelSerializers(book_obj, data=request.data)
  30. if bs.is_valid():
  31. bs.save()
  32. return Response(bs.data)
  33. else:
  34. return HttpResponse(bs.errors)
  35.  
  36. def delete(self, reqeust, book_id):
  37. Book.objects.filter(pk=book_id).delete()
  38. return Response() # 删除操作返回空

(4)测试验证

  

五、反序列化

  接收前端传过来的json处理是由Parser解析器执行,反序列化只进行验证和保存。

  当前端给DRF发post的请求的时候,前端给我们传过来的数据,要进行一些校验再保存到数据库。

  这些校验以及保存工作,DRF的Serializer也给我们提供了一些方法了。首先要写反序列化用的一些字段,这些字段要跟序列化区分开。Serializer提供了.is_valid()  和.save()方法。

1、反序列化create示例

  SerDemo/serializers.py文件:

  1. class BookSerializer(serializers.Serializer):
  2. """Book序列化类,注意与models对应"""
  3. id = serializers.IntegerField(required=False) # required=False设置该字段无需校验
  4. title = serializers.CharField(max_length=32)
  5.  
  6. # ChoiceField字段处理
  7. CHOICES = ((1, "Python"), (2, "Go"), (3, "Linux"))
  8. # choice字段配置source参数,显示对应名,read_only设置只读,只在序列化时使用
  9. category = serializers.ChoiceField(choices=CHOICES, source='get_category_display', read_only=True) # 图书的类别
  10. # write_only设置只写,只反序列化时使用
  11. w_category = serializers.ChoiceField(choices=CHOICES, write_only=True)
  12.  
  13. pub_time = serializers.DateField( )
  14.  
  15. # 当序列化与反序列化的类型不同时,需要分别生成read_only和write_only两个字段
  16. # 外键字段处理
  17. publisher = PublisherSerializer(read_only=True)
  18. publisher_id = serializers.IntegerField(write_only=True)
  19.  
  20. # 多对多字段处理(通过many字段与ForeignKey区分)
  21. author = AuthorSerializer(many=True, read_only=True)
  22. author_list = serializers.ListField(write_only=True)
  23.  
  24. def create(self, validated_data):
  25. # 重写save中的create方法
  26. book_obj = Book.objects.create(
  27. title = validated_data['title'],
  28. category=validated_data['w_category'], # 注意取反序列化字段
  29. pub_time=validated_data['pub_time'],
  30. publisher_id=validated_data['publisher_id']
  31. )
  32. book_obj.author.add(*validated_data['author_list']) # 添加多对多
  33. return book_obj

  SerDemo/views.py文件:

  1. # 方式三:基于rest_framework框架实现序列化(pip install djangorestframework)
  2. from rest_framework.views import APIView
  3. from rest_framework.response import Response
  4. from .serializers import BookSerializer # 自定义序列化类
  5.  
  6. class BookView(APIView):
  7. def get(self, request):
  8. # 第一个图书对象
  9. # book_obj = Book.objects.first()
  10. # ret = BookSerializer(book_obj)
  11.  
  12. book_list = Book.objects.all()
  13. ret = BookSerializer(book_list, many=True) # 使用序列化器序列化
  14. """
  15. 序列化的数据保存在ret.data中
  16. """
  17. return Response(ret.data)
  18. """
  19. 得出来的结果会使用Django REST framework模板,在serializers.py中定制好序列化类后,显示效果如下所示:
  20. HTTP 200 OK
  21. Allow: GET, HEAD, OPTIONS
  22. Content-Type: application/json
  23. Vary: Accept
  24.  
  25. [
  26. {
  27. "id": 1,
  28. "title": "python开发",
  29. "category": "Python",
  30. "pub_time": "2011-08-27",
  31. "publisher": {
  32. "id": 1,
  33. "title": "人民日报社"
  34. },
  35. "author": [
  36. {
  37. "id": 1,
  38. "name": "阿萨德"
  39. },
  40. {
  41. "id": 2,
  42. "name": "阿加莎"
  43. }
  44. ]
  45. },
  46. {
  47. "id": 2,
  48. "title": "go开发",
  49. "category": "Go",
  50. "pub_time": "2015-09-30",
  51. "publisher": {
  52. "id": 2,
  53. "title": "湖北日报社"
  54. },
  55. "author": [
  56. {
  57. "id": 2,
  58. "name": "于华吉"
  59. }
  60. ]
  61. },
  62. {
  63. "id": 3,
  64. "title": "Linux开发",
  65. "category": "Linux",
  66. "pub_time": "2008-08-27",
  67. "publisher": {
  68. "id": 3,
  69. "title": "长江日报设"
  70. },
  71. "author": [
  72. {
  73. "id": 1,
  74. "name": "阿萨德"
  75. },
  76. {
  77. "id": 3,
  78. "name": "阿迪力"
  79. }
  80. ]
  81. }
  82. ]
  83. """
  84.  
  85. def post(self, request):
  86. print(request.data)
  87. serializer = BookSerializer(data=request.data) # 序列化器校验前端传回来的数据
  88. if serializer.is_valid():
  89. serializer.save() # 验证成功后保存数据库
  90. # 因为ModelSerializer的create方法不支持source的用法。因此必须还自定义一个create方法。
  91. return Response(serializer.validated_data) # validated_data存放验证通过的数据
  92. else:
  93. return Response(serializer.errors) # errors存放错误信息
  94.  
  95. '''
  96. 发送post请求接口设计
  97. POST /books/list
  98. {
  99. "title": "nodejs的使用教程",
  100. "w_category": "1",
  101. "pub_time": "2018-10-27",
  102. "publisher_id": 1,
  103. "author_list": [1,2,3]
  104. }
  105. '''

2、PATCH请求示例(更新操作)

  SerDemo/serializers.py文件:

  1. class BookSerializer(serializers.Serializer):
  2. """Book序列化类,注意与models对应"""
  3. id = serializers.IntegerField(required=False) # required=False设置该字段无需校验
  4. title = serializers.CharField(max_length=32)
  5.  
  6. # ChoiceField字段处理
  7. CHOICES = ((1, "Python"), (2, "Go"), (3, "Linux"))
  8. # choice字段配置source参数,显示对应名,read_only设置只读,只在序列化时使用
  9. category = serializers.ChoiceField(choices=CHOICES, source='get_category_display', read_only=True) # 图书的类别
  10. # write_only设置只写,只反序列化时使用
  11. w_category = serializers.ChoiceField(choices=CHOICES, write_only=True)
  12.  
  13. pub_time = serializers.DateField( )
  14.  
  15. # 当序列化与反序列化的类型不同时,需要分别生成read_only和write_only两个字段
  16. # 外键字段处理
  17. publisher = PublisherSerializer(read_only=True)
  18. publisher_id = serializers.IntegerField(write_only=True)
  19.  
  20. # 多对多字段处理(通过many字段与ForeignKey区分)
  21. author = AuthorSerializer(many=True, read_only=True)
  22. author_list = serializers.ListField(write_only=True)
  23.  
  24. def create(self, validated_data):
  25. # 重写save中的create方法
  26. book_obj = Book.objects.create(
  27. title = validated_data['title'],
  28. category=validated_data['w_category'], # 注意取反序列化字段
  29. pub_time=validated_data['pub_time'],
  30. publisher_id=validated_data['publisher_id']
  31. )
  32. book_obj.author.add(*validated_data['author_list']) # 添加多对多
  33. return book_obj
  34.  
  35. def update(self, instance, validated_data):
  36. # 判断对应项是否更新,如果更新则替换
  37. instance.title = validated_data.get('title', instance.title)
  38. instance.category = validated_data.get('category', instance.category)
  39. instance.pub_time = validated_data.get('pub_time', instance.pub_time)
  40. instance.publisher_id = validated_data.get('publisher_id', instance.publisher_id)
  41.  
  42. if validated_data.get("author_list"):
  43. instance.author.set(validated_data["author_list"])
  44. instance.save() # 保存
  45. return instance

  SerDemo/views.py文件:

  1. class BookEditView(APIView):
  2. def get(self, request, id):
  3. """
  4. 查看单条数据
  5. :param request:
  6. :param id:
  7. :return:
  8. """
  9. book_obj = Book.objects.filter(id=id).first()
  10. ret = BookSerializer(book_obj)
  11. return Response(ret.data)
  12.  
  13. '''
  14. GET /books/retrieve/3
  15. {
  16. "id": 3,
  17. "title": "Linux开发",
  18. "category": "Linux",
  19. "pub_time": "2008-08-27",
  20. "publisher": {
  21. "id": 3,
  22. "title": "长江日报社"
  23. },
  24. "author": [
  25. {
  26. "id": 1,
  27. "name": "阿萨德"
  28. },
  29. {
  30. "id": 3,
  31. "name": "阿斯达"
  32. }
  33. ]
  34. }
  35. '''
  36.  
  37. def put(self, request, id):
  38. """更新操作"""
  39. book_obj = Book.objects.filter(id=id).first()
  40. serializer = BookSerializer(
  41. book_obj, # 待更新对象
  42. data=request.data, # 要更新的数据
  43. partial=True # 重点:进行部分验证和更新
  44. )
  45. if serializer.is_valid():
  46. serializer.save() # 保存
  47. return Response(serializer.validated_data) # 返回验证通过的数据
  48. else:
  49. return Response(serializer.errors) # 返回验证错误的数据

3、对字段自定义验证

  如果需要对一些字段进行自定义的验证,DRF也提供了钩子方法。

(1)单个字段的验证

  1. class BookSerializer(serializers.Serializer):
  2. """Book序列化类,注意与models对应"""
  3. id = serializers.IntegerField(required=False) # required=False设置该字段无需校验
  4. title = serializers.CharField(max_length=32)
  5. # 代码省略
  6. def validated_title(self, value): # 对字段进行验证:校验title字段
  7. if "python" not in value.lower(): # 如果python不在value字段中
  8. raise serializers.ValidationError("标题必须含有python") # 自定义错误信息
  9. return value

  在提交put请求时,如果提交{"title": “go语言开发”},没有包含python则会返回错误提示。

(2)多个字段的验证

  1. class BookSerializer(serializers.Serializer):
  2. """Book序列化类,注意与models对应"""
  3. id = serializers.IntegerField(required=False) # required=False设置该字段无需校验
  4. title = serializers.CharField(max_length=32)
  5. # 代码省略
  6. def validate(self, attrs): # 对多个字段进行比较验证
  7. # 执行更新操作:{"w_category": 1,"publisher_id": 1}
  8. # 注意JSON中,标准语法中,不支持单引号,属性或者属性值,都必须是双引号括起来
  9. if attrs['w_category'] == 1 and attrs['publisher_id'] == 1: # 联合校验分类和标题
  10. return attrs
  11. else:
  12. raise serializers.ValidationError('分类以及出版社不符合要求') # 抛出异常

  效果如下所示:

  

(3)验证器 validators

  1. def my_validate(value):
  2. # 自定义验证器
  3. if "fuck" in value.lower():
  4. raise serializers.ValidationError("不能含有敏感信息")
  5. else:
  6. return value
  7.  
  8. class BookSerializer(serializers.Serializer):
  9. """Book序列化类,注意与models对应"""
  10. id = serializers.IntegerField(required=False) # required=False设置该字段无需校验
  11. title = serializers.CharField(max_length=32, validators=[my_validate]) # 添加自定义验证器
  12. # 代码省略

  此时title字段不仅有了自定义的验证器,又有了单个字段验证,如果执行一个不满足两个条件的更新请求:{"title":"fuck"}

  返回结果如下所示:

  

rest-framework框架——APIView和序列化组件的更多相关文章

  1. DRF框架之 serializers 序列化组件

    1. 什么是序列化,其实在python中我们就学了序列化工具json工具,就是吧信息存为类字典形式 2. DRF框架自带序列化的工具: serializers 3. DRF框架 serializers ...

  2. 【DRF框架】利用序列化组件操作

    使用序列化组件进行操作 不带参数:查+增 带参数:查.改.删 不带参数的操作 # url路由 url(r'^book_list/$',Search_book.as_view()), # views.p ...

  3. 2 APIView与序列化组件

    1.入门 1.1 参考blog 官方文档:http://www.django-rest-framework.org/tutorial/quickstart/#quickstart yuan的Blog: ...

  4. Django rest framework框架——APIview源码分析

    一.什么是rest REST其实是一种组织Web服务的架构,而并不是我们想象的那样是实现Web服务的一种新的技术,更没有要求一定要使用HTTP.其目标是为了创建具有良好扩展性的分布式系统. 可用一句话 ...

  5. Django-rest framework框架的三大认证组件

    源码分析:三大认证组件的封装 组件的认证配置: 模型层:models.py class User(BaseModel): username = models.CharField(verbose_nam ...

  6. django rest framework框架中都有那些组件

    1.权限 2.认证 3.访问频率 4.序列化 5.路由 6.视图 7.分页 8.解析器 9.渲染器 规定页面显示的效果(无用) https://www.cnblogs.com/Rivend/p/118 ...

  7. 基于Django的Rest Framework框架的序列化组件

    本文目录 一 Django自带序列化组件 二 rest-framework序列化之Serializer 三 rest-framework序列化之ModelSerializer 四 生成hypermed ...

  8. DRF框架(二)——解析模块(parsers)、异常模块(exception_handler)、响应模块(Response)、三大序列化组件介绍、Serializer组件(序列化与反序列化使用)

    解析模块 为什么要配置解析模块 1)drf给我们提供了多种解析数据包方式的解析类 form-data/urlencoded/json 2)我们可以通过配置来控制前台提交的哪些格式的数据后台在解析,哪些 ...

  9. 【DRF框架】序列化组件

    DRF框架的序列化组件 在前后端分离的应用模式中,后端仅返回前端所需的数据,返回的数据类似是JSON,因此需要使用序列化组件进行序列化再将数据返回 使用JsonResponse做序列化 #  使用Js ...

随机推荐

  1. Python——requests的安装及入门-贴吧爬虫

    一.windows平台下requests的安装 1.win+R,输入cmd,打开命令行窗口,输入命令:pip install requests ,即可自动安装库成功 2.输入命令:pip list,即 ...

  2. checkbox的常见问题

    1.在使用checkbox时,最好不要阻止他原有的事件,要利用它原有的事件进行控制 2.尽量使用label for属性,不要对input元素的父元素或者input本身绑定事件,这样不能有效的避免冒泡事 ...

  3. Unity---高度解耦和

    介绍 先举一个简单的例子: 在UGUI中新建一个Button和Text,要求实现点击Button改变Text中的文字. 我的第一反应就是在Button上添加一个脚本,获取点击事件来改变Text的内容. ...

  4. HBASE常用操作增删改查

    http://javacrazyer.iteye.com/blog/1186881 http://www.cnblogs.com/invban/p/5667701.html

  5. 通过文件路径读取CSV表格内的数据

    ReadDataFromCSV.h UCLASS() class MYPROJECT_API UReadDataFromCSV : public UBlueprintFunctionLibrary { ...

  6. vscode 遇到设置问题

    // 控制是否在新窗口中打开文件. // - default: 除了从软件内部选择的文件 (如,从“文件”菜单选择),其他所有文件都将在新窗口中打开 // - on: 文件将在新窗口中打开 // - ...

  7. mfix添加文件后重新生成configure文件

    mfix给了一些程序接口,大部分时候只用修改现有程序即可满足要求,这种情况不用修改configure文件,但是如果添加了新文件就需要做一些修改. 我用了Jian Cai的程序尝试了一下编译,该学者在2 ...

  8. 119th LeetCode Weekly Contest K Closest Points to Origin

    We have a list of points on the plane.  Find the K closest points to the origin (0, 0). (Here, the d ...

  9. HDU 1232 (畅通工程) 并查集经典模板题

    Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅通工程"的目标是使全省任何两个城镇间都可以实现交通 ...

  10. hdu2588 GCD

    GCD Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...