# _*_ encoding:utf-8 _*_ __author__ = 'LYQ' __data__ = '2018/8/13 15:21' import json from django.views.generic.base import View from django.http import HttpResponse,JsonResponse from .models import * class GoodsView(View): def get(self,request): good_list=Goods.objects.all()[:10] datas=[] # for good in good_list: # json_dict = {} # json_dict['name']=good.name # json_dict['goods_desc']=good.goods_desc # json_dict['category']=good.category.name # json_dict['shop_price']=good.shop_price # #時間不是json序列化的對象 # json_dict['time']=good.add_time # datas.append(json_dict) #直接序列化 from django.forms.models import model_to_dict #用來作序列化 from django.core import serializers datas=[] for good in good_list: #image和datetime不能序列化 data=model_to_dict(good) datas.append(data) datas=serializers.serialize('json',good_list) datas=json.loads(datas) # return HttpResponse(datas,content_type='application/json') return JsonResponse(datas,safe=False)
Django REST框架是用於構建Web API的強大而靈活的工具包。git
您可能但願使用REST框架的一些緣由:github
REST框架須要如下內容:django
如下包是可選的:json
使用安裝pip
,包括您想要的任何可選包...api
pip install djangorestframework pip install markdown # Markdown support for the browsable API. pip install django-filter # Filtering support
...或者從github克隆項目。markdown
git clone git@github.com:encode/django-rest-framework.git
添加'rest_framework'
到您的INSTALLED_APPS
設置。架構
INSTALLED_APPS = ( ... 'rest_framework', )
若是您打算使用可瀏覽的API,您可能還須要添加REST框架的登陸和註銷視圖。將如下內容添加到根urls.py
文件中。app
urlpatterns = [ ... url(r'^api-auth/', include('rest_framework.urls')) ]
請注意,URL路徑能夠是您想要的任何內容。框架
讓咱們看一個使用REST框架構建一個簡單的模型支持的API的快速示例。ide
咱們將建立一個讀寫API,用於訪問有關項目用戶的信息。
REST框架API的任何全局設置都保存在名爲的單個配置字典中REST_FRAMEWORK
。首先將如下內容添加到settings.py
模塊中:
REST_FRAMEWORK = { # Use Django's standard `django.contrib.auth` permissions, # or allow read-only access for unauthenticated users. 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly' ] }
別忘了確保你也加入rest_framework
了INSTALLED_APPS
。咱們如今準備建立咱們的API了。
注:若是出現utf8 decode的錯誤,把虛擬環境中的\Lib\site-packages\pip\compat中的_init_.py的75行中的utf8改爲gbk重新安裝便可。
1.serializers:
#form對應:Serializer,modelform:ModelSerializer from rest_framework import serializers from .models import * class GoodsSerializer(serializers.Serializer): name = serializers.CharField(required=True,max_length=100) click_num = serializers.IntegerField(default=0) goods_front_image=serializers.ImageField() add_time=serializers.DateTimeField() def create(self, validated_data): return Goods.objects.create(**validated_data)
2.views:
from rest_framework.views import APIView
#狀態碼
from rest_framework import status from .models import * from .serializers import GoodsSerializer
from rest_dramework.response import Reaponse class GoodsListView(APIView): """ List all snippets, or create a new snippet. """ def get(self, request, format=None): goods = Goods.objects.all()
#many=True,goods是一個列表 goods_serializer = GoodsSerializer(goods, many=True) return Response(goods_serializer.data) def post(self,request,format=None): serializer=GoodsSerializer(data=request.data)
#驗證字段是否合法 if serializer.is_valid(): serializer.save() return Response(request.data,status=status.HTTP_201_CREATED) return Response(request.data,status=status.HTTP_400_BAD_REQUEST)
3.ModelSerializer:
class GoodsSerializer(serializers.ModelSerializer): # 替換默認的category category = GoodsCategorySerializer() # 可能有多條many=True images = GoodsImageSerializer(many=True) class Meta: model = Goods # fields=('name','click_num','market_price','add_time','goods_front_image') # 外鍵爲id,想要完整信息,嵌套Serializer fields = ('__all__')
from rest_framework import mixins from rest_framework import generics #基於mixins,必須重載get函數 class GoodsListView(mixins.ListModelMixin,generics.GenericAPIView): """ 商品詳情頁 """ queryset = Goods.objects.all()[:10] serializer_class = GoodsSerializer #必須重寫,否則默認沒法接受get請求 def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs)
1.viewset中的view:
2.GenericViewset:
繼承了ViewSetMixin和GenericAPIView,ViewSetMixin重寫了as_view方法,initialize_request方法,initialize_request方法設置了不少action,在動態使用serializer時有不少的好處
class ViewSetMixin(object): """ This is the magic. Overrides `.as_view()` so that it takes an `actions` keyword that performs the binding of HTTP methods to actions on the Resource. For example, to create a concrete view binding the 'GET' and 'POST' methods to the 'list' and 'create' actions... view = MyViewSet.as_view({'get': 'list', 'post': 'create'}) """ @classonlymethod def as_view(cls, actions=None, **initkwargs): """ Because of the way class based views create a closure around the instantiated view, we need to totally reimplement `.as_view`, and slightly modify the view function that is created and returned. """ # The suffix initkwarg is reserved for displaying the viewset type. # eg. 'List' or 'Instance'. cls.suffix = None # The detail initkwarg is reserved for introspecting the viewset type. cls.detail = None # Setting a basename allows a view to reverse its action urls. This # value is provided by the router through the initkwargs. cls.basename = None # actions must not be empty if not actions: raise TypeError("The `actions` argument must be provided when " "calling `.as_view()` on a ViewSet. For example " "`.as_view({'get': 'list'})`") # sanitize keyword arguments for key in initkwargs: if key in cls.http_method_names: raise TypeError("You tried to pass in the %s method name as a " "keyword argument to %s(). Don't do that." % (key, cls.__name__)) if not hasattr(cls, key): raise TypeError("%s() received an invalid keyword %r" % ( cls.__name__, key)) def view(request, *args, **kwargs): self = cls(**initkwargs) # We also store the mapping of request methods to actions, # so that we can later set the action attribute. # eg. `self.action = 'list'` on an incoming GET request. self.action_map = actions # Bind methods to actions # This is the bit that's different to a standard view for method, action in actions.items(): handler = getattr(self, action) setattr(self, method, handler) if hasattr(self, 'get') and not hasattr(self, 'head'): self.head = self.get self.request = request self.args = args self.kwargs = kwargs # And continue as usual return self.dispatch(request, *args, **kwargs) # take name and docstring from class update_wrapper(view, cls, updated=()) # and possible attributes set by decorators # like csrf_exempt from dispatch update_wrapper(view, cls.dispatch, assigned=()) # We need to set these on the view function, so that breadcrumb # generation can pick out these bits of information from a # resolved URL. view.cls = cls view.initkwargs = initkwargs view.suffix = initkwargs.get('suffix', None) view.actions = actions return csrf_exempt(view) def initialize_request(self, request, *args, **kwargs): """ Set the `.action` attribute on the view, depending on the request method. """ request = super(ViewSetMixin, self).initialize_request(request, *args, **kwargs) method = request.method.lower() if method == 'options': # This is a special case as we always provide handling for the # options method in the base `View` class. # Unlike the other explicitly defined actions, 'metadata' is implicit. self.action = 'metadata' else: self.action = self.action_map.get(method) return request def reverse_action(self, url_name, *args, **kwargs): """ Reverse the action for the given `url_name`. """ url_name = '%s-%s' % (self.basename, url_name) kwargs.setdefault('request', self.request) return reverse(url_name, *args, **kwargs) @classmethod def get_extra_actions(cls): """ Get the methods that are marked as an extra ViewSet `@action`. """ return [method for _, method in getmembers(cls, _is_extra_action)]
3.繼承genericviewset的view寫法:
GenericViewSet繼承於GnericAPIView,沒有重寫get,post等方法,所以還須要繼承mixin
class GoodsListViewSet(mixins.ListModelMixin,mixins.RetrieveModelMixin,viewsets.GenericViewSet): """ 商品詳情頁,分頁,搜索,過濾,排序 """ #配置ip限制訪問次數 throttle_classes = (UserRateThrottle,AnonRateThrottle) queryset = Goods.objects.all() serializer_class = GoodsSerializer #分頁 pagination_class = GoodsPagination #配置認證類,防止公開網頁(未登陸可查看)不能訪問 # authentication_classes = (TokenAuthentication,) filter_backends=(DjangoFilterBackend,filters.SearchFilter,filters.OrderingFilter) #字段過濾(DjangoFilterBackend) # filter_fields = ('name', 'shop_price') filter_class=GoodsFilter #搜索過濾(rest_framework.filters.SearchFilter) search_fields = ('name','goods_brief','goods_desc') #排序過濾(rest_frameworkfilters.OrderingFilter) ordering_fields = ('sold_num', 'shop_price') def retrieve(self, request, *args, **kwargs): instance = self.get_object() instance.click_num+=1 instance.save() serializer = self.get_serializer(instance) return Response(serializer.data)
viewset和router配套使用:
第一種:配置url:
1 #在url.py文件中 2 #配置GoodsListViewSet 3 good_list=GoodsListViewSet.as_view({ 4 #把get請求綁定到list方法上 5 'get':'list', 6 }) 7 urlpatterns = [ 8 #把good_list放入url中 9 url('^goods/$',good_list,name='good_list'), 11 ]
第二種:(使用router)
from rest_framework.routers import DefaultRouter router = DefaultRouter() # 配置goods的url router.register(r'goods', GoodsListViewSet, base_name='goods') #在調用router.urls時會自動把router中轉換爲url配置 urlpatterns = [ url('^', include(router.urls)), ]
1.View繼承關係(差別就是不一樣的mixin):
GnericViewSet(drf)【比GnericAPIView繼承增長了一個ViewSetMixin,在url中綁定了,router可使用,還有實現了initialize_request方法設置了不少action方便不一樣serializer的使用】———>GnericAPIView(drf)【增長了篩選過濾分頁,serializer等】———>APIView(drf)———>View(django)
2.mixin:
CreateModelMixin
ListModelMixin
RetrieveModelMixin
UpdateModelMixin
DestroyModelMIxin
意境定製好了的view組合(繼承GericAPIView不一樣的mixin實現不一樣的功能):