一、settings.py注册restframework
'''
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',
'rest_framework'
]
如果没有注册,则网页报错:
TemplateDoesNotExist:rest_framework/api.html
'''
二、drf的简单使用
django2.2 + python3.6.8
# app01
# models.py
from django.db import models
class Book(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
author = models.CharField(max_length=32)
# __init__.py
import pymysql
pymysql.install_as_MySQLdb()
# urls.py
from app01 import views
from rest_framework.routers import DefaultRouter
urlpatterns = []
router = DefaultRouter() # 可以处理视图的路由器
router.register('book', views.BooksViewSet) # 向路由器中注册视图集
# 将路由器中的所以路由信息追到到django的路由列表中
urlpatterns += router.urls
# ser.py
from rest_framework.serializers import ModelSerializer
from app01.models import Book
class BookModelSerializer(ModelSerializer):
class Meta:
model = Book
fields = "__all__"
# views.py
from rest_framework.viewsets import ModelViewSet
from .models import Book
from .ser import BookModelSerializer
class BooksViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookModelSerializer
# djangoProject
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'app01.apps.App01Config',
'rest_framework',
]
# urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('book/', include('app01.urls'))
]
三、Request对象
self.parsers = parsers or ()
self.authenticators = authenticators or ()
self.negotiator = negotiator or self._default_negotiator()
self.parser_context = parser_context
self._data = Empty
self._files = Empty
self._full_data = Empty
self._content_type = Empty
self._stream = Empty
# Empty 相当于一个字典
1、_request
'''
只要继承了APIView,那么最终 原生request 都会被加工成 新request,即Request对象
'''
# 原生request:Request对象的_request存储
self._request = request
'''
对于后续使用原生request方法并不影响,因为Request对象内部重写了__getattr__方法
'''
def __getattr__(self, attr):
try:
'''
如果你使用request.POST/GET/META/FILES/...
那么最终都会返回原生request对象中对应的方法
'''
return getattr(self._request, attr)
except AttributeError:
'''
如果原生request中不存在该方法,那么会继续从__getattribute__中寻找
def __getattribute__(self, *args, **kwargs):
pass
'''
return self.__getattribute__(attr)
2、request.data
'''
post请求,不管传入什么编码,如urlencoded、json、form-data,
都在request.data中,以字典的形式显示
'''
@property
def data(self):
if not _hasattr(self, '_full_data'):
self._load_data_and_files()
return self._full_data
# 判断对象中是否存在对应的属性/方法名
def _hasattr(obj, name):
return not getattr(obj, name) is Empty
3、request.query_params
'''
query_params就是给原生request对象的GET方法换了个名字
'''
@property
def query_params(self):
return self._request.GET
四、Response对象
'''
用于后端服务器响应前端请求,发送给前端数据
如果是字典数据(request.data),则会以JSON格式发送给前端
并根据如果为浏览器,则渲染成精美的HTML页面(Accept参数)
否则为纯JSON数据
如果不适用Response,那么必须要使用JsonResponse,返回纯JSON数据
'''
def __init__(
self,
data=None, # 传入发送给前端的数据,需要是一个字典
status=None, # 传入状态码,默认200
# from rest_framework import status在这个路径下,它把所有使用到的状态码都定义成了常量
template_name=None, # 自定义API HTML模板
headers=None, # 设置响应头,需要一个字典
exception=False, # 异常
content_type=None # 响应编码类型(text/html、application/json)
)
常用属性:
.data # 未渲染的字典数据
.status_code # 传入数字,设置状态码
.content # 经由渲染后的响应数据
'''
Response会根据请求头中的Accept参数来进行对应操作(浏览器:渲染返回API HTML页面;postman:返回JSON数据)
如果请求头中不存在Accept参数,那么就会采用默认的方式来处理响应数据,我们可以通过配置修改默认响应格式:
from rest_framework import settings 中存在设置案例
'''
全局配置(项目settings.py中增加):
REST_FRAMEWORK = {
# 设置默认响应渲染类
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer', # json渲染器
'rest_framework.renderers.BrowsableAPIRenderer', # 浏览API渲染器
)
}
局部配置(在视图类中增加):
from rest_framework.renderers import JSONRenderer
renderer_classes=[JSONRenderer,]