上传的图片资源目录配置:
settings.py:
MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
urls.py:
# media上传的图片
urlpatterns = [
re_path(r'^media/(?P<path>.*)$', serve, {"document_root": MEDIA_ROOT})
]
导入商品种类数据
db_tools/import_category_data.py: 编写脚本导入数据
from db_tools.data.category_data import row_data:db_tools/data/category_data.py 下row_data为数组
__author__ = "westbrook-ding"
__date__ = "2018/10/26 0026 18:53"
# 单独使用django的model
import os
import sys
# os.path.realpath(__file__):获取当前脚本文件的绝对路径
# os.path.dirname(path):文件所在的目录
pwd = os.path.dirname(os.path.realpath(__file__))
# 添加模块搜索目录 djangoShop
sys.path.append(pwd+"../")
# 设置django配置目录 默认会在djangoShop下找
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoShop.settings')
import django
django.setup()
# 引入商品种类class
from goods.models import GoodsCategory
# 引入商品种类数组
from db_tools.data.category_data import row_data
# 保存数据到数据库中
for lev1_cat in row_data:
lev1_instance = GoodsCategory()
lev1_instance.code = lev1_cat['code']
lev1_instance.name = lev1_cat['name']
lev1_instance.category_type = 1
lev1_instance.save()
for lev2_cat in lev1_cat["sub_categorys"]:
lev2_instance = GoodsCategory()
lev2_instance.code = lev2_cat['code']
lev2_instance.name = lev2_cat['name']
lev2_instance.category_type = 2
lev2_instance.parent_category = lev1_instance
lev2_instance.save()
for lev3_cat in lev2_cat["sub_categorys"]:
lev3_instance = GoodsCategory()
lev3_instance.code = lev3_cat['code']
lev3_instance.name = lev3_cat['name']
lev3_instance.category_type = 3
lev3_instance.parent_category = lev2_instance
lev3_instance.save()
导入商品数据
db_tools/import_good_data.py: 编写脚本导入数据
from db_tools.data.product_data import row_data:db_tools/data/product_data.py 下row_data为数组
__author__ = "westbrook-ding"
__date__ = "2018/10/26 0026 18:53"
# 单独使用django的model
import os
import sys
# os.path.realpath(__file__):获取当前脚本文件的绝对路径
# os.path.dirname(path):文件所在的目录
pwd = os.path.dirname(os.path.realpath(__file__))
# 添加模块搜索目录 djangoShop
sys.path.append(pwd+"../")
# 设置django配置目录 默认会在djangoShop下找
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoShop.settings')
import django
django.setup()
# 引入商品class
from goods.models import Goods, GoodsCategory, GoodsImage
# 引入商品数据数组
from db_tools.data.product_data import row_data
# 保存商品数据
for good_cat in row_data:
good = Goods()
good.name = good_cat["name"]
good.goods_brief = good_cat["desc"] if good_cat["desc"] is not None else ""
good.goods_desc = good_cat["goods_desc"] if good_cat["goods_desc"] is not None else ""
good.market_price = float(int(good_cat["market_price"].replace("¥", '').replace("元", "")))
good.shop_price = float(int(good_cat["sale_price"].replace("¥", '').replace("元", "")))
good.goods_front_image = good_cat["images"][0]
category_name = good_cat["categorys"][-1]
category = GoodsCategory.objects.filter(name=category_name)
if category is not None:
good.category = category[0]
good.save()
# 商品轮播图
for good_image in good_cat["images"]:
good_image_instance = GoodsImage()
good_image_instance.goods = good
good_image_instance.image = good_image
good_image_instance.save()
restful api介绍
djangorestframework(drf)框架
1.通过django的view实现商品列表页
goods/views_base.py:
__author__ = "westbrook-ding"
__date__ = "2018/10/27 0027 13:51"
from django.views.generic import View
from goods.models import Goods
class GoodslistView(View):
def get(self, request):
"""
通过django的view实现商品列表页
"""
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
# dumps是将dict转化成str格式,loads是将str转化成dict格式。
return HttpResponse(json.dumps(json_list), content_type="application/json")
urls.py:
from django.urls import path, include, re_path
from goods.views_base import GoodslistView
urlpatterns = [
# 商品列表
path('goods/', GoodslistView.as_view(), name="goods_list")
]
以上代码可进一步优化如下:
model_to_dict() model转化成字典
from django.forms.models import model_to_dict
for good in goods:
# model_to_dict() model转化成字典
json_dict = model_to_dict(good)
json_list.append(json_dict)
model_to_dict() 有些字段无法转换采用model序列化
from django.core import serializers
# django models序列化
json_list = serializers.serialize("json", goods)
import json
# dumps是将dict转化成str格式,loads是将str转化成dict格式。
json_list = json.loads(json_list)
from django.http import HttpResponse, JsonResponse
# return HttpResponse(json.dumps(json_list), content_type="application/json")
return JsonResponse(json_list, safe=False)
使用djangorestframework:
1.安装drf框架
pip install djangrestframework
pip install markdown Markdown对可浏览API的支持。
pip install django-filter 过滤支持。
pip install django-crispy-forms 改进的HTML显示以进行过滤。
pip install coreapi 模式生成支持。
pip install django-guardian 对象级权限支持。
2.添加'rest_framework'
到您的INSTALLED_APPS
设置
3.如果您打算使用可浏览的API,您可能还需要添加REST框架的登录和注销视图。将以下内容添加到根urls.py
文件中
re_path(r'^api-auth/', include('rest_framework.urls'))
4.配置自动生成api文档
urls.py:
# 引入drf自动生成文档的方法
from rest_framework.documentation import include_docs_urls
urlpatterns = [
path('doc/', include_docs_urls(title="生鲜电商api文档"))
]
5.drf用apiview来实现商品列表:
a. goods应用下 serializers.py:
# 引入 rest_framework的serializers 序列化
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()
b. goods应用下 views.py:
# 引入自定义的序列化方法
from .serializers import GoodsSerializer
# APIView继承的是django的View
from rest_framework.views import APIView
from rest_framework.response import Response
from goods.models import Goods
# Create your views here.
class GoodslistView(APIView):
"""
商品列表
"""
def get(self, requset, format=None):
goods = Goods.objects.all()[:10]
# many = True 序列化成数组对象
goods_json = GoodsSerializer(goods, many=True)
return Response(goods_json.data)
c. urls.py:
from django.urls import path, include, re_path
from goods.views import GoodslistView
# 引入drf自动生成文档的方法
from rest_framework.documentation import include_docs_urls
urlpatterns = [
# 商品列表
path('goods/', GoodslistView.as_view(), name="goods_list"),
path('doc/', include_docs_urls(title="生鲜api文档")),
re_path(r'^api-auth/', include('rest_framework.urls'))
]
通过 http://127.0.0.1:8000/goods 访问goods api 得到如下数据: drf 的序列化帮我们图片目录添加的/media 前缀(django没有做这一步)
6.drf的modelserializer实现商品列表功能:
goods下serializers.py:
# 引入 rest_framework的serializers 序列化
from rest_framework import serializers
from goods.models import Goods, GoodsCategory
# ModelSerializer
class GoodsCategorySerializer(serializers.ModelSerializer):
class Meta:
model = GoodsCategory
# __all__ 序列化所有字段
fields = "__all__"
class GoodsSerializer(serializers.ModelSerializer):
# 将外键的id也序列化出来 覆盖category字段
category = GoodsCategorySerializer()
class Meta:
model = Goods
# __all__ 序列化所有字段 ["name","click_num"]:筛选字段 外键会默认序列成id
fields = "__all__"
views.py、urls.py写法同5.drf用apiview来实现商品列表
7.GenericView方式实现商品列表页和分页
goods应用下的views.py:
# 引入自定义的序列化方法
from .serializers import GoodsSerializer
# 引入drf的generics和PageNumberPagination
from rest_framework import generics
from rest_framework.pagination import PageNumberPagination
from goods.models import Goods
# 自定义商品列表分页
class GoodsPagination(PageNumberPagination):
page_size = 10 # 每页10条
page_size_query_param = 'page_size'
page_query_param = 'p' # 指定页码参数为p 默认为page
max_page_size = 100
# 查看源码 generics.ListAPIView 继承了 mixins.ListModelMixin,和GenericAPIView,而GenericAPIView继承了views.APIView
class GoodslistView(generics.ListAPIView):
"""
商品列表页
"""
queryset = Goods.objects.all() # 查询商品列表
serializer_class = GoodsSerializer # 序列化的类
pagination_class = GoodsPagination # 配置分页
goods下serializers.py和 urls.py写法同 6.drf的modelserializer实现商品列表功能:
8.viewsets和router实现商品列表页
goods下的views.py:
# 引入自定义的序列化方法
from .serializers import GoodsSerializer
# 引入drf mixins、viewsets 、PageNumberPagination
from rest_framework.pagination import PageNumberPagination
from rest_framework import mixins
from rest_framework import viewsets
from goods.models import Goods
# 自定义商品列表分页
class GoodsPagination(PageNumberPagination):
page_size = 10 # 每页10条
page_size_query_param = 'page_size'
page_query_param = 'p' # 指定页码参数为p 默认为page
max_page_size = 100
# viewsets.GenericViewSet 继承了ViewSetMixin, generics.GenericAPIView
# ViewSetMixin 重写了as_view方法 使其可以使用router
class GoodslistViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
"""
商品列表页
"""
queryset = Goods.objects.all() # 查询商品列表页
serializer_class = GoodsSerializer # 序列化类
pagination_class = GoodsPagination # 配置分页
urls.py:
from django.urls import path, include, re_path
# 引入drf自动生成文档的方法
from rest_framework.documentation import include_docs_urls
# 引入drf路由
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
from goods.views import GoodslistViewSet
# 商品列表router
router.register(r'goods', GoodslistViewSet)
urlpatterns = [
# router
path('', include(router.urls)),
path('doc/', include_docs_urls(title="生鲜api文档")),
re_path(r'^api-auth/', include('rest_framework.urls'))
]
goods下的serializers.py同7.GenericView方式实现商品列表页和分页
9.drf的ApiView、GenericView、ViewSet和router分析
GenericViewSet(ViewSet) -drf 可使用router、动态序列化、minxin
GennericApiView -drf 可使用mixin 分页等
ApiView -drf
View -django
minxin
CreateModelMixin
ListModelMixin
UpdateModelMixin
RetrieveModelMixin
DestoryModelMixin
10. drf的过滤(django_filter)
goods下的filter.py:
__author__ = "westbrook-ding"
import django_filters
from .models import Goods
# 自定义商品过滤器
class GoodsFilter(django_filters.rest_framework.FilterSet):
"""
商品本店价格区间
"""
# gte:>= lte:<=
price__min = django_filters.NumberFilter(field_name='shop_price', lookup_expr='gte')
price__max = django_filters.NumberFilter(field_name='shop_price', lookup_expr='lte')
# 模糊查询 contains i:忽略大小写 不加lookup_expr="icontains" 表示全部匹配
name = django_filters.CharFilter(field_name='name', lookup_expr="icontains")
class Meta:
model = Goods
fields = ['price__min', 'price__max', 'name']
goods下的views.py:
from django_filters.rest_framework import DjangoFilterBackend
from goods.filter import GoodsFilter
class GoodslistViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
"""
商品列表页
"""
queryset = Goods.objects.all()
serializer_class = GoodsSerializer # 序列化类
pagination_class = GoodsPagination # 配置分页
# 过滤
filter_backends = (DjangoFilterBackend,)
# filter_fields = ('name', 'shop_price') # 必需全部匹配
filter_class = GoodsFilter
11.drf的搜索和排序
SearchFilter搜索 OrderingFilter排序
goods下的views.py:
# 引入drf filters
from rest_framework import filters
from goods.models import Goods
class GoodslistViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
"""
商品列表页
"""
queryset = Goods.objects.all()
serializer_class = GoodsSerializer # 序列化类
pagination_class = GoodsPagination # 配置分页
# 搜索: filters.SearchFilter和search_field
# 排序: filters.OrderingFilter 和ordering_fields
filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
# 搜索
# search_fields 满足元组中所选字段的任意条件均会被筛选出来
# '^'开始 - 搜索。
# '='完全匹配。
# '@'全文搜索。(目前只支持Django的MySQL后端。)
# '$'正则表达式搜索。
search_fields = ('^name', 'goods_brief', 'goods_desc')
# 按字段排序
ordering_fields = ('sold_num', 'add_time')
12.商品分类数据接口(列表和详情)
goods下serializers.py:(多级分类序列化)
# 引入 rest_framework的serializers 序列化
from rest_framework import serializers
from goods.models import GoodsCategory
# ModelSerializer
# 三级大类序列化
class GoodsCategorySerializer3(serializers.ModelSerializer):
class Meta:
model = GoodsCategory
# __all__ 序列化所有字段
fields = "__all__"
# 二级大类序列化
class GoodsCategorySerializer2(serializers.ModelSerializer):
# many = True: 子类有多个
sub_cat = GoodsCategorySerializer3(many=True)
class Meta:
model = GoodsCategory
# __all__ 序列化所有字段
fields = "__all__"
# 一级商品大类序列化
class GoodsCategorySerializer(serializers.ModelSerializer):
# many = True: 子类有多个 通过models.py 中class GoodsCategory 字段属性 related_name="sub_cat" 关联起来
sub_cat = GoodsCategorySerializer2(many=True)
class Meta:
model = GoodsCategory
# __all__ 序列化所有字段
fields = "__all__"
goods下views.py: (mixins.ListModelMixin:列表,mixins.RetrieveModelMixin:单个商品分类详情,通过id查询)
from rest_framework import mixins
from rest_framework import viewsets
from goods.models import GoodsCategory
# 引入自定义的序列化方法
from .serializers import GoodsCategorySerializer
class CategoryListViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
"""
商品分类列表 、单个分类详情(mixins.RetrieveModelMixin:请求示例id=1:
http://127.0.0.1:8000/category/1/)
"""
# 获取一级大类
queryset = GoodsCategory.objects.filter(category_type=1)
serializer_class = GoodsCategorySerializer
urls.py:
# 商品分类列表router
router.register(r'category', CategoryListViewSet)
13.django解决跨域问题: django-cors-headers
a.安装 pip install django-cors-headers
b. settings.py 配置如下
INSTALLED_APPS = (
...
'corsheaders',
...
)
# 置于 django.middleware.csrf.CsrfViewMiddleware 之前
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
]
CORS_ORIGIN_ALLOW_ALL = True
c . 重新运行项目