Django 是一个重量级的框架,所以APIView有很多子类
APIView子类:generics
generics类里面的方法
- GenericAPIView(通用的的APIView)
- 继承自View
- get_queryset 获取查询结果集
- get_object 获取单个对象
- get_serializer 获取对象
- get_serializer_class 获取序列化的类
- get_serializer_context 获取序列化的内容
- filter_queryset 过滤查询结果集
- paginator_queryset 属性(先不说)
- get_paginate_response 获取分页后的结果
- as_view重写了,很重要,他就是入口
GenericAPIView源码
class GenericAPIView(views.APIView):
"""
Base class for all other generic views.
"""
# You'll need to either set these attributes,
# or override `get_queryset()`/`get_serializer_class()`.
# If you are overriding a view method, it is important that you call
# `get_queryset()` instead of accessing the `queryset` property directly,
# as `queryset` will get evaluated only once, and those results are cached
# for all subsequent requests.
queryset = None
serializer_class = None
# If you want to use object lookups other than pk, set 'lookup_field'.
# For more complex lookup requirements override `get_object()`.
lookup_field = 'pk'
lookup_url_kwarg = None
# The filter backend classes to use for queryset filtering
filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
# The style to use for queryset pagination.
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
def get_queryset(self):
"""
Get the list of items for this view.
This must be an iterable, and may be a queryset.
Defaults to using `self.queryset`.
This method should always be used rather than accessing `self.queryset`
directly, as `self.queryset` gets evaluated only once, and those results
are cached for all subsequent requests.
You may want to override this if you need to provide different
querysets depending on the incoming request.
(Eg. return a list of items that is specific to the user)
"""
assert self.queryset is not None, (
"'%s' should either include a `queryset` attribute, "
"or override the `get_queryset()` method."
% self.__class__.__name__
)
queryset = self.queryset
if isinstance(queryset, QuerySet):
# Ensure queryset is re-evaluated on each request.
queryset = queryset.all()
return queryset
def get_object(self):
"""
Returns the object the view is displaying.
You may want to override this if you need to provide non-standard
queryset lookups. Eg if objects are referenced using multiple
keyword arguments in the url conf.
"""
queryset = self.filter_queryset(self.get_queryset())
# Perform the lookup filtering.
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
assert lookup_url_kwarg in self.kwargs, (
'Expected view %s to be called with a URL keyword argument '
'named "%s". Fix your URL conf, or set the `.lookup_field` '
'attribute on the view correctly.' %
(self.__class__.__name__, lookup_url_kwarg)
)
filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
obj = get_object_or_404(queryset, **filter_kwargs)
# May raise a permission denied
self.check_object_permissions(self.request, obj)
return obj
def get_serializer(self, *args, **kwargs):
"""
Return the serializer instance that should be used for validating and
deserializing input, and for serializing output.
"""
serializer_class = self.get_serializer_class()
kwargs['context'] = self.get_serializer_context()
return serializer_class(*args, **kwargs)
def get_serializer_class(self):
"""
Return the class to use for the serializer.
Defaults to using `self.serializer_class`.
You may want to override this if you need to provide different
serializations depending on the incoming request.
(Eg. admins get full serialization, others get basic serialization)
"""
assert self.serializer_class is not None, (
"'%s' should either include a `serializer_class` attribute, "
"or override the `get_serializer_class()` method."
% self.__class__.__name__
)
return self.serializer_class
def get_serializer_context(self):
"""
Extra context provided to the serializer class.
"""
return {
'request': self.request,
'format': self.format_kwarg,
'view': self
}
def filter_queryset(self, queryset):
"""
Given a queryset, filter it with whichever filter backend is in use.
You are unlikely to want to override this method, although you may need
to call it either from a list view, or from a custom `get_object`
method if you want to apply the configured filtering backend to the
default queryset.
"""
for backend in list(self.filter_backends):
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset
@property
def paginator(self):
"""
The paginator instance associated with the view, or `None`.
"""
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
return self._paginator
def paginate_queryset(self, queryset):
"""
Return a single page of results, or `None` if pagination is disabled.
"""
if self.paginator is None:
return None
return self.paginator.paginate_queryset(queryset, self.request, view=self)
def get_paginated_response(self, data):
"""
Return a paginated style `Response` object for the given output data.
"""
assert self.paginator is not None
return self.paginator.get_paginated_response(data)
# Concrete view classes that provide method handlers
# by composing the mixin classes with the base view.
1.CreateAPIView
post 单个
2.ListAPIView
get 多个
3.RetrieveAPIView
get 单个
4.DestroyAPIView
delete
5.UpdateAPIView
put、patch
6.ListCreateAPIView
创建查询所有
7.RetrieveUpdateAPIView
单个get➕put,patch
8.RetrieveDestroyAPIView
delete
9.RetrieveUpdateDestroyAPIView
get、put/patch 、delete
1.CreateAPIView
继承自·
GenericAPIVie
和mixins.CreateModelMixin
实现了post
意思是:我们在开发中只要继承了CreateAPIView就可以直接post请求了
class CreateAPIView(mixins.CreateModelMixin,
GenericAPIView):
"""
Concrete view for creating a model instance.
"""
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
2.ListAPIView
继承自
GenericAPIView
和mixins.RetrieveModelMixin
>实现了get请求
class ListAPIView(mixins.ListModelMixin,
GenericAPIView):
"""
Concrete view for listing a queryset.
"""
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
3.RetrieveAPIView
继承自
GenericAPIView
和mixins.RetrieveModelMixin
>实现了get
RetrieveAPIView和ListAPIView的区别:
RetrieveAPIView
拿单个,ListAPIView
拿多个
class RetrieveAPIView(mixins.RetrieveModelMixin,
GenericAPIView):
"""
Concrete view for retrieving a model instance.
"""
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
4.DestroyAPIView
继承自
GenericAPIView
和mixins.DestroyModelMixin
实现了delete 默认支持delete请求
class DestroyAPIView(mixins.DestroyModelMixin,
GenericAPIView):
"""
Concrete view for deleting a model instance.
"""
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
5.UpdateAPIView
继承自
GenericAPIView
和mixins.UpdateModelMixin
>实现了put和patch方法
class UpdateAPIView(mixins.UpdateModelMixin,
GenericAPIView):
"""
Concrete view for updating a model instance.
"""
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
6.ListCreateAPIView
继承自
GenericAPIView
(通用类)和mixins.ListModelMinxin
和mixins.CreateModelMinxin
实现了多个 get和post请求
class ListCreateAPIView(mixins.ListModelMixin,
mixins.CreateModelMixin,
GenericAPIView):
"""
Concrete view for listing a queryset or creating a model instance.
"""
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
7.RetrieveUpdateAPIView
继承自
GenericAPIView
和mixins.RetrieveModelMinxin
和mixins.updateModelMixin
实现了单个get和put和patch请求
class RetrieveUpdateAPIView(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
GenericAPIView):
"""
Concrete view for retrieving, updating a model instance.
"""
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
8.RetrieveDestoryAPIView
继承自
GenericAPIView
和mixins.RetrieveModelMixin
和mixins.DestoryModelMixin
实现了get、delete请求
class RetrieveDestroyAPIView(mixins.RetrieveModelMixin,
mixins.DestroyModelMixin,
GenericAPIView):
"""
Concrete view for retrieving or deleting a model instance.
"""
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
9.RetrieveUpdateDestroyApiView
继承自
GenerixAPIView
和mixins.RetrieveModelMixin
和Mixins.UpdateModelMixin
和mixins.DestoryModelMixin
实现了get、put、aptch、delete
class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
GenericAPIView):
"""
Concrete view for retrieving, updating or deleting a model instance.
"""
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
总结规律:就是这几个家伙的排列组合
针对于复数操作:创建:post、获取:get
针对于单数操作:获取:get、更新:put,patch、删除delete
mixins模块
从上面可以看出来都是继承自:
mixins.RetrieveModelMixin(get请求,请求单个)
mixins.ListModelMixin(get请求,请求多个)
mixins.UpdateModelMixin(put、patch更新请求)
mixins.DestroyModelMixin(delete请求)
mixins.CreateModelMixin(post请求)
那么mixins模块又是什么呢?
mixins.py
"""
Basic building blocks for generic class based views.
We don't bind behaviour to http method handlers yet,
which allows mixin classes to be composed in interesting ways.
"""
from __future__ import unicode_literals
from rest_framework import status
from rest_framework.response import Response
from rest_framework.settings import api_settings
CreateModelMixin
有三个操作:
create方法:
1.get_serializer
获取序列化数据进行创建
2.preform_create
执行创建
get_success_headers
class CreateModelMixin(object):
"""
Create a model instance.
"""
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save()
def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}
ListModelMixin
list方法:
get_queryset,
filter_queryset(拿到queryset进行过滤),
paginate_queryset
带分页
get_paginated_response
不带分页就直接返回
get_serializer拿到进行序列化
最后return 返回
class ListModelMixin(object):
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
retrieve方法
get_object 拿到数据
get_serializer 拿到序列化工具
最后返回序列化好的数据
class RetrieveModelMixin(object):
"""
Retrieve a model instance.
"""
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
update方法
get_object 拿到对象
get_serializer 获取数据
serializer.is_valid 进行验证
perform_update方法
serializer.save() 将数据进行保存
partial_update方法
update 查量更新、部分更新
class UpdateModelMixin(object):
"""
Update a model instance.
"""
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}
return Response(serializer.data)
def perform_update(self, serializer):
serializer.save()
def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)
destroy方法
get_object拿到对象
perform_destroy
instance.delete()进行删除
class DestroyModelMixin(object):
"""
Destroy a model instance.
"""
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return Response(status=status.HTTP_204_NO_CONTENT)
def perform_destroy(self, instance):
instance.delete()
eg:
创建➕查询所有继承 generics.ListCreateAPIView
注意:
他已经把list和get写了,自己就不用手动写get,和post方法了
如果只想获取列表:generics.ListAPIView
如果只想创建post:genericsCreateAPIView
如果只想更新:RetrieveUpdateAPIView
如果只想删除:RetrieveDistoryAPIView
只需要把:
queryset = None
查询集合
serializer_class = None
需要序列化的类名
赋值就行了
获取单个
lookup_field = 'pk'
想获取单个,路径后面参数跟:pk=idNum, 如果pk值不存在:Not found不会报错
lookup_url_kwarg = None
默认为空
看源码
class GenericAPIView(views.APIView):
"""
Base class for all other generic views.
"""
# You'll need to either set these attributes,
# or override `get_queryset()`/`get_serializer_class()`.
# If you are overriding a view method, it is important that you call
# `get_queryset()` instead of accessing the `queryset` property directly,
# as `queryset` will get evaluated only once, and those results are cached
# for all subsequent requests.
queryset = None
serializer_class = None
# If you want to use object lookups other than pk, set 'lookup_field'.
# For more complex lookup requirements override `get_object()`.
lookup_field = 'pk'
lookup_url_kwarg = None
class ListCreateAPIView(mixins.ListModelMixin,
mixins.CreateModelMixin,
GenericAPIView):
"""
Concrete view for listing a queryset or creating a model instance.
"""
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
1.创建模型
models.py
from django.db import models
class Computer(models.Model):
c_name = models.CharField(max_length=16)
c_price = models.FloatField(default=1)
python manage.py makemigrations
python manage.py migrate
2.创建序列化模块
serializers.py
from rest_framework import serializers
from ViewLearn.models import Computer
class ComputerSerializer(serializers.ModelSerializer):
class Meta:
model = Computer
fields = ("id", "c_name", "c_price")
3.将查询集进行序列化
views.py
queryset
:获取数据
serializer_class
:获取自己serializer类
from ViewLearn.models import Computer
from ViewLearn.serializers import ComputerSerializer
from rest_framework import generics
class ComputerAPIView(generics.ListCreateAPIView):
queryset = Computer.objects.all()
serializer_class = ComputerSerializer
实现单个查询继承GenericAPIView
class ComputerAPIView(generics.RetrieveAPIView):
queryset = Computer.objects.all()
serializer_class = ComputerSerializer
实现删除继承DistroyAPIView
class ComperDelAPIView(generics.DistroyAPIView):
queryset = Computer.object.all()
serializer_class = ComputerSerializer
能更新、能查、能删除继承RetrieveUpdateDistoryAPIView
class ComputerUGDAPView(generics.RetrieveUpdateDistoryAPIView):
queryset = Computer.object.all()
serializer_class = ComputerSerializer
4.路由匹配:语法和类视图一样
urls.py
from django.conf.urls import url
from ViewLearn import views
urlpatterns = [
url(r'^computers/$', views.ComputersAPIView.as_view()),
url(r'^computers/(?P<pk>\d+)/', views.ComputerAPIView.as_view()),
url(r'^computerDel', views. ComperDelAPIView.as_view()),
url(r'^computerUGD', views. ComputerUGDAPView.as_view()),
]