美文网首页
Vue+Django REST framework生鲜电商项目笔

Vue+Django REST framework生鲜电商项目笔

作者: 朝鹿志 | 来源:发表于2020-07-23 22:08 被阅读0次

一、商品列表页

为了更好的区分Django Restful Framework和Django中的View,我们先使用Django的View来实现商品列表页json数据返回

Django

#goods/base_view.py

import json

from django.http import HttpResponse
from django.views.generic.base import View
from .models import Goods


#CBV方式编码

class GoodsListView(View):
    def get(self,request):
        """
        通过Django的View实现商品列表页
        :param request:
        :return:
        """
        goods=Goods.objects.all()[:10]
        json_data=[]
        for good in goods:
            json_dict={}
            # 取出商品的每个字段,键值存储
            json_dict['name']=good.name
            json_dict['category']=good.category.name
            json_dict['market_price']=good.market_price
            json_data.append(json_dict)
        # 返回json数据,一定要指定类型content_type='application/json'
        return HttpResponse(json.dumps(json_data),content_type='application/json')
from apps.goods.base_view import GoodsListView

urlpatterns = [
    #基于Django实现的商品列表页
    url(r'goods/$',GoodsListView.as_view(),name='goods-list')
]

访问http://127.0.0.1:8000/goods/ 可以获取商品列表信息的json数据

image.png
  • django的serializer序列化
    当字段比较多时,一个字段一个字段的提取很麻烦,可以使用model_to_dict,将model字段整个转化为dict
import json
from django.http import HttpResponse
from django.views.generic.base import View
from .models import Goods



#CBV方式编码

class GoodsListView(View):
    def get(self,request):
        """
        通过Django的View实现商品列表页
        :param request:
        :return:
        """
        goods=Goods.objects.all()[:10]
        json_data=[]
        # for good in goods:
        #     json_dict={}
        #     # 取出商品的每个字段,键值存储
        #     json_dict['name']=good.name
        #     json_dict['category']=good.category.name
        #     json_dict['market_price']=good.market_price
        #     json_data.append(json_dict)


        from django.forms.models import model_to_dict
        for good in goods:
            json_dict = model_to_dict(good)
            json_data.append(json_dict)
            
        #Object of type ImageFieldFile is not JSON serializable
        # 返回json数据,一定要指定类型content_type='application/json'
        return HttpResponse(json.dumps(json_data),content_type='application/json')

但是这里有个问题json.dums和loads方法不能将datetime和ImageFieldFile字段序列化成json数据


image.png

如何才能将所有字段序列化呢?就要用到django的serializers

import json
from django.http import HttpResponse,JsonResponse
from django.views.generic.base import View
from .models import Goods

#CBV方式编码

class GoodsListView(View):
    def get(self,request):
        """
        通过Django的View实现商品列表页
        :param request:
        :return:
        """
        goods=Goods.objects.all()[:10]
        json_data=[]
        # for good in goods:
        #     json_dict={}
        #     # 取出商品的每个字段,键值存储
        #     json_dict['name']=good.name
        #     json_dict['category']=good.category.name
        #     json_dict['market_price']=good.market_price
        #     json_data.append(json_dict)


        # from django.forms.models import model_to_dict
        # for good in goods:
        #     json_dict = model_to_dict(good)
        #     json_data.append(json_dict)
        #
        # # Object of type ImageFieldFile is not JSON serializable
        # # 返回json数据,一定要指定类型content_type='application/json'
        # return HttpResponse(json.dumps(json_data), content_type='application/json')

        from django.core import serializers
        # serialize序列化成json
        json_data=serializers.serialize('json',goods)
        json_data=json.loads(json_data)

        # In order to allow non-dict objects to be serialized set the safe parameter to False.
        #JsonResponse类中定义了json.dumps()和content_type='application/json')
        return JsonResponse(json_data,safe=False)

DRF

#GoShop\settings.py

INSTALLED_APPS = [
    'rest_framework',
]

#GoShop\urls.py

from rest_framework.documentation import include_docs_urls

urlpatterns = [
    url(r'^docs/',include_docs_urls(title='Django REST API Docs')),
    url(r'^api-auth/', include('rest_framework.urls')),
    url(r'goods/$',GoodsListView.as_view(),name='goods')
]

goods/serializers.py

from rest_framework import serializers


class GoodsSerializer(serializers.Serializer):
    #手动添加字段
    name=serializers.CharField(required=True,max_length=100)
    click_num=serializers.IntegerField(default=0)
    goods_front_image = serializers.ImageField()

goods/views.py

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Goods
from .serializers import GoodsSerializer

class GoodsListView(APIView):
    """
    商品列表API
    """
    def get(self, request, format=None):
        goods = Goods.objects.all()[:10]
        goods_serializer = GoodsSerializer(goods, many=True)
        return Response(goods_serializer.data)
image.png

DRF的serializers会自动帮我们添加media到URL路径中,GoodsListView是APIView的子类,会识别请求类型生成可浏览的API接口。

  • serializers类似Django中的form处理HTML,而serializers用来处理Json,我们使用ModelSerializer来添加字段将会更方便,直接用"all"方法可以全部序列化。
from rest_framework import serializers
from .models import Goods,GoodsCategory


#ModelSerializer实现商品列表数据序列化
class GoodsSerializer(serializers.ModelSerializer):

    class Meta:
        model=Goods
        fields='__all__'
image.png

category是一张外键表,DRF的serializers序列化只显示了分类id,serializers还可以嵌套使用,像Django中的form一样,覆盖外键字段。

from rest_framework import serializers
from .models import Goods,GoodsCategory


class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model=GoodsCategory
        fields='__all__'


#ModelSerializer实现商品列表数据序列化
class GoodsSerializer(serializers.ModelSerializer):
    # 嵌套使用 覆盖外键字段
    category=CategorySerializer()
    class Meta:
        model=Goods
        fields='__all__'
image.png

使用mixins和GenericAPIView实现商品列表页

generics.GenericAPIView继承APIView,封装了很多方法,比APIView的功能更加强大又方便。generics和mixins一起使用只需要配置

#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

mixins.ListModelMixin类里面list方法帮我们做好了分页和序列化的逻辑,我们只需要在get方法中调用就可以。

class GoodsListView(mixins.ListModelMixin,generics.GenericAPIView):
    """
    商品列表API
    """
    #GenericAPIView使用配置queryset和serializer_class
    queryset = Goods.objects.all()[:10]
    serializer_class = GoodsSerializer

    #重载get方法,调用ListModelMixin下的list方法做序列化、分页
    def get(self,request,*args,**kwargs):
        return self.list(request,*args,**kwargs)

上面的代码优化,mixins和generics还可以组合使用,可以直接继承ListAPIView,ListAPIView主要做了两件事:

  • ListAPIView(mixins.ListModelMixin,GenericAPIView) 继承了这两个类
  • 重载get方法
class GoodsListView(generics.ListAPIView):
    """
    商品列表API
    """
    queryset = Goods.objects.all()
    serializer_class = GoodsSerializer

相关文章

网友评论

      本文标题:Vue+Django REST framework生鲜电商项目笔

      本文链接:https://www.haomeiwen.com/subject/thaclktx.html