Vue+Django REST framework 打造生鲜电商项目(1)

3-1项目初始化

虚拟环境目录

C:\Users\Lv_Shine\Envs\VueShop\Scripts\python.exe

*设置数据库

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': "mxshop",
        'USER': 'root',
        'PASSWORD': "root",
        'HOST': "127.0.0.1",
        'PORT': '3306',
        'OPTIONS': {'init_command': 'SET storage_engine=INNODB;'},
    }
}

options后面第三方登录要用.
运行提示

ImproperlyConfigured: Error loading MySQLdb module: No module named 'MySQLdb'.
Did you install mysqlclient or MySQL-python?

需要安装mysqlclient

坑1 运行的时候会报错

django.db.utils.OperationalError: (1193, "Unknown system variable 'storage_engine'")

解决,名字改成default_storage_engine
I have found in the following links that indeed the variable "storage_engine" has been renamed to "default_storage_engine", which has caused some software to start getting issues with recent versions of MySql.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': "mxshop",
        'USER': 'root',
        'PASSWORD': "root",
        'HOST': "127.0.0.1",
        'OPTIONS': { 'init_command': 'SET default_storage_engine=INNODB;' }
    }
}

用于下载各种库的win兼容版本网址
www.lfd.uci.edu/~gohlke/pythonlibs/

  • 把新建的目录加入setting,可以直接form引用
import os
import sys
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, BASE_DIR)
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
sys.path.insert(0, os.path.join(BASE_DIR, 'extra_apps'))
微信截图_20171201165209.png

3-2

3-7 xadmin

微信截图_20171202125759.png

微信截图_20171202130117.png

安装依赖包,xadmin复制的extra_apps下.
setting添加app.

5-1 django的view方法实现商品列表

views_base.py

class GoodsListView(View):
    def get(self,request):
        json_list = []
        goods = Goods.objects.all()[:10]
        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_list.append(json_dict)

        from django.http import HttpResponse
        import json
        return HttpResponse(json.dumps(json_list), content_type="application/json")
  1. url配置
url(r'goods/$', GoodsListView.as_view(), name="goods-list"),

5-2 django的serializer序列化

  • 可以用这个代替会出错,图片不能序列化.
class GoodsListView(View):
    def get(self,request):
        json_list = []
        goods = Goods.objects.all()[:10]
        # 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_list.append(json_dict)

        for good in goods:
            json_dict = model_to_dict(good)
            json_list.append(json_dict)
        from django.http import HttpResponse
        import json
        return HttpResponse(json.dumps(json_list), content_type="application/json")


  • 序列化的方式,还是不够灵活.
 json_list = []
        goods = Goods.objects.all()[:10]
        # 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_dict["add_time"] = good.add_time
        #     json_list.append(json_dict)

        # from django.forms.models import model_to_dict
        # for good in goods:
        #     json_dict = model_to_dict(good)
        #     json_list.append(json_dict)

        import json
        from django.core import serializers
        json_data = serializers.serialize('json', goods)
        json_data = json.loads(json_data)
        from django.http import HttpResponse, JsonResponse
        return JsonResponse(json_data, safe=False)


5-3 apiview方式实现商品列表页-1

微信截图_20171203110238.png
pip install django-guardian
pip install coreapi

如果MarkupSafe出现错误,就需要去虚拟环境把utf-8改成gbk.
evns/vueshop/lib/site-packages/pip/compat/__init这个文件75行.

** 配置setting.添加app.

INSTALLED_APPS = {
'rest_framework',
}
  • 配置urls路径
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))![微信截图_20171204213202.png](http://upload-images.jianshu.io/upload_images/1716830-74c71acdef9bc6ae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

5-4自定义serializer

1.urls上节配置成功了.
2.views

from rest_framework.response import Response

from rest_framework.views import APIView

from goods.models import Goods
from goods.serializers import GoodsSerializer


class GoodsListView(APIView):

    def get(self, request, format=None):
        goods = Goods.objects.all()[:10]
        goods_serializer = GoodsSerializer(goods, many=True)
        return Response(goods_serializer.data)
  1. serializers
from rest_framework import serializers

__author__ = 'lv'
__date__ = '2017/12/4 21:39'


class GoodsSerializer(serializers.Serializer):
    name = serializers.CharField(required=True, max_length=100)
    click_num = serializers.IntegerField(default=0)

成果:

微信截图_20171204214637.png

点击OPTIONS会变成:


微信截图_20171204215844.png
serializers增加一个字段,浏览器请求的json就增加一个字段.
  1. serializers
from rest_framework import serializers

__author__ = 'lv'
__date__ = '2017/12/4 21:39'


class GoodsSerializer(serializers.Serializer):
    name = serializers.CharField(required=True, max_length=100)
    click_num = serializers.IntegerField(default=0)
    goods_front_image = serializers.ImageField()

成果:


微信截图_20171204220221.png

目标: 使用serializers.ModelSerializer改写serializers

from rest_framework import serializers

from goods.models import Goods

__author__ = 'lv'
__date__ = '2017/12/4 21:39'


# class GoodsSerializer(serializers.Serializer):
#     name = serializers.CharField(required=True, max_length=100)
#     click_num = serializers.IntegerField(default=0)
#     goods_front_image = serializers.ImageField()

class GoodsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Goods
        fields = ('name', 'click_num', 'market_price', 'add_time')

成果:

微信截图_20171204223236.png

目标:请求所有字段

from rest_framework import serializers

from goods.models import Goods

class GoodsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Goods
        fields = "__all__"

成果:


微信截图_20171204223736.png

目标:解析goods类中的外键category

  • 在serializers中添加GoodsCategorySerializer
from rest_framework import serializers

from goods.models import Goods, GoodsCategory

__author__ = 'lv'
__date__ = '2017/12/4 21:39'

class GoodsCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = "__all__"


class GoodsSerializer(serializers.ModelSerializer):
    category = GoodsCategorySerializer()
    class Meta:
        model = Goods
        # fields = ('name', 'click_num', 'market_price', 'add_time')
        fields = "__all__"


5-6

*RUN-1重写view-GoodsListView,继承mixins.ListModelMixin,generics.GenericAPIView

from django.shortcuts import render

# Create your views here.
from rest_framework import mixins, generics
from rest_framework.response import Response

from rest_framework.views import APIView

from goods.models import Goods
from goods.serializers import GoodsSerializer


# class GoodsListView(APIView):
#
#     def get(self, request, format=None):
#         goods = Goods.objects.all()[:10]
#         goods_serializer = GoodsSerializer(goods, many=True)
#         return Response(goods_serializer.data)

class GoodsListView(mixins.ListModelMixin, generics.GenericAPIView):

    queryset = Goods.objects.all()[:10]
    serializer_class = GoodsSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

成果:


微信截图_20171204230357.png
微信截图_20171204230639.png
  • 继续简写views.py
    因为:


    微信截图_20171204231143.png
  • 所以views.py可以写成:

from django.shortcuts import render

# Create your views here.
from rest_framework import mixins, generics
from rest_framework.response import Response

from rest_framework.views import APIView

from goods.models import Goods
from goods.serializers import GoodsSerializer


# class GoodsListView(APIView):
#       第一种
#     def get(self, request, format=None):
#         goods = Goods.objects.all()[:10]
#         goods_serializer = GoodsSerializer(goods, many=True)
#         return Response(goods_serializer.data)


# class GoodsListView(mixins.ListModelMixin, generics.GenericAPIView):
#       第二种
#     queryset = Goods.objects.all()[:10]
#     serializer_class = GoodsSerializer
#
#     def get(self, request, *args, **kwargs):
#         return self.list(request, *args, **kwargs)


class GoodsListView(generics.ListAPIView):
    queryset = Goods.objects.all()[:10]
    serializer_class = GoodsSerializer
RUN-2 目标:分页
  1. setting配置.
    教程说仅仅添加'PAGE_SIZE'会无效并不会挂机.
    但是pycharm会提示


    微信截图_20171204233505.png
WARNINGS:
?: (rest_framework.W001) You have specified a default PAGE_SIZE pagination rest_framework setting,without specifying also a DEFAULT_PAGINATION_CLASS.
    HINT: The default for DEFAULT_PAGINATION_CLASS is None. In previous versions this was PageNumberPagination. If you wish to define PAGE_SIZE globally whilst defining pagination_class on a per-view basis you may silence this check.

System check identified 1 issue (0 silenced).

警告:
?:(rest_framework.W001)您已经指定了一个默认的PAGE_SIZE分页rest_framework设置,而没有指定一个DEFAULT_PAGINATION_CLASS。
提示:DEFAULT_PAGINATION_CLASS的默认值是None。 在以前的版本中,这是PageNumberPagination。 如果您希望全局定义PAGE_SIZE,同时在每个视图上定义pagination_class,则可以使此检查无效。

REST_FRAMEWORK = {
    'PAGE_SIZE': 10
}
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 10,

}

  • 成果:


    微信截图_20171204233825.png

RUN-3 定制分页

微信截图_20171204234448.png
  • 不需要设置setting只需更改views
class GoodsPagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = 'page_size'
    page_query_param = "p"
    max_page_size = 100


class GoodsListView(generics.ListAPIView):
    queryset = Goods.objects.all()
    serializer_class = GoodsSerializer
    pagination_class = GoodsPagination
微信截图_20171204235344.png

5-7viewsets和router

目标是引入router
RUN-4
  1. 改写views.py
from django.shortcuts import render

# Create your views here.
from rest_framework import mixins, generics, viewsets
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response

from rest_framework.views import APIView

from goods.models import Goods
from goods.serializers import GoodsSerializer


class GoodsPagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = 'page_size'
    page_query_param = "p"
    max_page_size = 100


# class GoodsListView(APIView):
#       第一种
#     def get(self, request, format=None):
#         goods = Goods.objects.all()[:10]
#         goods_serializer = GoodsSerializer(goods, many=True)
#         return Response(goods_serializer.data)


# class GoodsListView(mixins.ListModelMixin, generics.GenericAPIView):
#       第二种
#     queryset = Goods.objects.all()[:10]
#     serializer_class = GoodsSerializer
#
#     def get(self, request, *args, **kwargs):
#         return self.list(request, *args, **kwargs)


# class GoodsListView(generics.ListAPIView):
#     queryset = Goods.objects.all()
#     serializer_class = GoodsSerializer
#     pagination_class = GoodsPagination


class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    """
    引入router
    商品列表页
    """
    queryset = Goods.objects.all()
    serializer_class = GoodsSerializer
    pagination_class = GoodsPagination
  1. urls
good_list = GoodsListViewSet.as_view(
    {
        'get': 'list',
        
    }
)
             ``````
url(r'goods/$', good_list, name="goods-list"),
            ``````

RUN-5 router改写urls
  1. urls
"""MxShop URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url, include
from django.contrib import admin
from django.db import router
from django.views.static import serve
from rest_framework.documentation import include_docs_urls
from rest_framework.routers import DefaultRouter

import xadmin
from MxShop.settings import MEDIA_ROOT
from goods.views import GoodsListView, GoodsListViewSet

# good_list = GoodsListViewSet.as_view(
#     {
#         'get': 'list',
#
#     }
# )

router = DefaultRouter()

router.register(r'goods', GoodsListViewSet),




urlpatterns = [
    url(r'^xadmin/', xadmin.site.urls),
    url(r'^media/(?P<path>.*)$',serve,{"document_root": MEDIA_ROOT}),

    # url(r'goods/$', good_list, name="goods-list"),
    url(r'^', include(router.urls)),

    url(r'docs/', include_docs_urls(title="慕雪生鲜")),

    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]

5-8

微信截图_20171205084100.png
  1. generic 通用
  2. retrieve 取回
微信截图_20171205090912.png

5-10 过滤

微信截图_20171205091625.png
RUN-6 过滤
  1. 添加APPS到setting
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'DjangoUeditor',
    'users.apps.UsersConfig',
    'goods.apps.GoodsConfig',
    'trade.apps.TradeConfig',
    'user_operation.apps.UserOperationConfig',
    'crispy_forms',
    'django_filters',
    'xadmin',
    'rest_framework',
   

]

  1. views
class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    """
    引入router
    商品列表页
    """
    queryset = Goods.objects.all()
    serializer_class = GoodsSerializer
    pagination_class = GoodsPagination

    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('name', 'shop_price')

成果:


微信截图_20171205092611.png
RUN-7 区段过滤
  1. filters.py
# _*_ coding: utf-8 _*_
import django_filters

from goods.models import Goods

__author__ = 'lv'
__date__ = '2017/12/5 10:17'


class GoodsFilter(django_filters.rest_framework.FilterSet):

    price_min = django_filters.NumberFilter(name='shop_price', lookup_expr='gte')
    price_max = django_filters.NumberFilter(name='shop_price', lookup_expr='lte')

    class Meta:
        model = Goods
        fields = ['price_min', 'price_max']
  1. views
class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    """
    引入router
    商品列表页
    """
    queryset = Goods.objects.all()
    serializer_class = GoodsSerializer
    pagination_class = GoodsPagination

    filter_backends = (DjangoFilterBackend,)
    filter_class = GoodsFilter


成果:


微信截图_20171205102909.png

RUN-8 查询关键词
  1. view
# _*_ coding: utf-8 _*_
import django_filters

from goods.models import Goods

__author__ = 'lv'
__date__ = '2017/12/5 10:17'


class GoodsFilter(django_filters.rest_framework.FilterSet):

    price_min = django_filters.NumberFilter(name='shop_price', lookup_expr='gte')
    price_max = django_filters.NumberFilter(name='shop_price', lookup_expr='lte')
    name = django_filters.CharFilter(name='name', lookup_expr='icontains')

    class Meta:
        model = Goods
        fields = ['price_min', 'price_max', 'name']
微信截图_20171205103749.png
RUN-9 搜索
  • 只更改views很少的代码
from rest_framework import filters

class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    """
    引入router
    商品列表页
    """
    queryset = Goods.objects.all()
    serializer_class = GoodsSerializer
    pagination_class = GoodsPagination

    filter_backends = (DjangoFilterBackend, filters.SearchFilter)
    filter_class = GoodsFilter
    search_fields = ('name', 'goods_brief', 'goods_desc')

成果:


微信截图_20171205104454.png

searche 字段可以匹配正则.

RUN-10 排序
  • views
class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    """
    引入router
    商品列表页
    """
    queryset = Goods.objects.all()
    serializer_class = GoodsSerializer
    pagination_class = GoodsPagination

    filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
    filter_class = GoodsFilter
    search_fields = ('name', 'goods_brief', 'goods_desc')
    ordering_fields = ('sold_num', 'add_time')

成果:

微信截图_20171205110557.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容