web项目(美多)后台第四天

美多第四天

分页查询用户

  • 在meiduo_admin 新建文件包utiles—>meiduo_pagination.py
    在用户查询 下 写入分页功能
    • from apps.meiduo_admin.utils.meiduo_pagination import MeiduoPagination
    • pagination_class = MeiduoPagination
  • 1.自定义分页类型,指定页大小、参数名称、最大页大小
  • 2.在视图类中指定分页类型
  • 3.通过阅读源码结论:重写分页类型的方法,自定义响应体
  • meiduo_pagination.py 写入
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response

class MeiduoPagination(PageNumberPagination):
	#后端指定每页显示数量
    page_size = 10
    #  允许从查询参数中接收page_参数,用于制定页大小
    page_size_query_param = 'page_size'
    #如果页的大小参数大于此值,则页大小被设置为此值
    max_page_size = 100

    def get_paginated_response(self, data):
        return Response({
            'lists':data,# 用户数据
            'counts':self.page.paginator.count,# 总数量
            'page':self.page.number,# 当前页数
            'pages':self.page.paginator.num_pages,# 总页数
            'pagesize':self.page.paginator.per_page, # 后端指定的页容量

        })

注意 看一些源码 慢慢理解

创建–增加用户
  • 在序列化器中验证

      - 在serializer->user中添加模型类
    
    • 1 增加password属性

    • 2 指定只读,只写字段

        # 只读字段取 'id'
        read_only_fields = ['id']
        extra_kwargs={
        'password':{
            'write_only':True
        } }
      
    • 3 定义验证方法

        def validate(self,value):
        #前段已经验证过 不用再验证
        	return value
      
    • 4 重写create()方法:用户的密码需要加密保存

        def create(self, validated_data):
        	return User.objects.create_user(**validated_data)
      

规格管理

  • 视图类:Modelviewset
  • 序列化器类:ModelSerializer

创建文件

  • views以及serialazers中创建spec.py

serializer中的spec

from rest_framework import serializers
from apps.goods.models import SPUSpecification
#商品spu规格

class SpecSerlalizer(serializers.ModelSerializer):
    spu = serializers.StringRelatedField(read_only=True)
    spu_id = serializers.IntegerField()
    class Meta:
        model = SPUSpecification
        fields = ['id','name','spu','spu_id']
        read_only_fields = ['id']

views中的spec


from rest_framework.viewsets import ModelViewSet
from apps.goods.models import SPUSpecification
from apps.meiduo_admin.serializers.spec import SpecSerlalizer
from apps.meiduo_admin.utils.meiduo_pagination import MeiduoPagination

class SpecViewSet(ModelViewSet):
    queryset = SPUSpecification.objects.all()
    serializer_class = SpecSerlalizer
    pagination_class = MeiduoPagination

路由规格

router = SimpleRouter()
router.register('goods/specs',spec.SpecViewSet,base_name ='specs')
urlpatterns+=router.urls

在serializers和views中创建spu.py

  • serializers中的spu
from rest_framework import serializers
from apps.goods.models import SPU

class SpuSimpleSeralizer(serializers.ModelSerializer):
    class Meta:
        model = SPU
        fields = ['id','name']
  • views中的spu
from rest_framework.generics import ListAPIView
from apps.meiduo_admin.serializers.spu import SpuSimpleSeralizer
from apps.goods.models import SPU


class SpuSimpleView(ListAPIView):
    queryset = SPU.objects.all()
    serializer_class = SpuSimpleSeralizer

路由规范

    url(r'^goods/simple/$', spu.SpuSimpleView.as_view()),

SKU管理

  • 视图类:ModelViewSet
  • 序列化器类:ModelSerializer
  • SKU的查询,过滤,分页

创建文件

-在serializer创建sku.py

	from rest_framework import serializers
	from apps.goods.models import SKU
	
	
	class SkuSpecRelatedSerializer(serializers.Serializer):
	    spec_id = serializers.IntegerField()
	    option_id = serializers.IntegerField()
	
	
	class SkuSerializer(serializers.ModelSerializer):
	    # 将标准商品以字符串输出
	    spu = serializers.StringRelatedField(read_only=True)
	    # 指定all时,隐藏属性需要明确定义
	    spu_id = serializers.IntegerField()
	    # 指定第三级分类外键输出名称
 	    category = serializers.StringRelatedField(read_only=True)
 	    # 指定隐藏属性
 	    category_id = serializers.IntegerField()
 	    # 规格信息
 	    specs = SkuSpecRelatedSerializer(many=True, read_only=True)
 	
 	    class Meta:
 	        model = SKU
 	        # fields = '__all__'
 	        exclude = ['create_time', 'update_time']
  • 在views中创建sku.py
	from rest_framework.viewsets import ModelViewSet
	from apps.goods.models import SKU
	from apps.meiduo_admin.serializers.sku import SkuSerializer
	from apps.meiduo_admin.utils.meiduo_pagination import MeiduoPagination
	from django.db.models import Q
	
	
	class SkuViewSet(ModelViewSet):
	    # queryset = SKU.objects.all().order_by('-id')
	    def get_queryset(self):
	        queryset = SKU.objects
	        # 接收查询参数中的关键字
	        keyword = self.request.query_params.get('keyword')
	        if keyword:
	            # 构造查询条件
	            # 两个条件为逻辑与关系
	            # queryset = queryset.filter(name__contains=keyword, caption__contains=keyword)
	            # 两个条件为逻辑或关系
	            queryset = queryset.filter(Q(name__contains=keyword) | Q(caption__contains=keyword))
	        # 排序
	        queryset = queryset.order_by('-id')
	        # 查询集
	        return queryset
	
	    serializer_class = SkuSerializer
	    pagination_class = MeiduoPagination
  • 创建视图
router.register('skus',sku.SkuViewSet,base_name='skus')

增加

  • 准备
  • 查询第三级分类
在serializers中创建category.py
	from rest_framework import serializers
	from apps.goods.models import GoodsCategory
	
	
	class Category3Serializer(serializers.Serializer):
	    id = serializers.IntegerField()
	    name = serializers.CharField()
在views中创建category.py
	from rest_framework.generics import ListAPIView
	from apps.goods.models import GoodsCategory
	from apps.meiduo_admin.serializers.category import Category3Serializer
	
	
	class Category3View(ListAPIView):
	    serializer_class = Category3Serializer
	    # 查询第三级分类
	    queryset = GoodsCategory.objects.filter(subs__isnull=True)
创建视图
  # sku-第三级分类
  url('^skus/categories/$', category.Category3View.as_view()),

根据spu_id查询规格及选项

在serializers中创建spec.py
class OptionRelatedSerializer(serializers.Serializer):
 	    id = serializers.IntegerField()
 	    value = serializers.CharField()
 	
 	
 	class SpecBySpuSerializer(serializers.Serializer):
 	    # 根据标准商品编号,查询规格及选项
 	    id = serializers.IntegerField()
 	    name = serializers.CharField()
 	    spu = serializers.StringRelatedField(read_only=True)
 	    spu_id = serializers.IntegerField()
 	    # 规格与选项为1对多关系,在选项中定义了规格外键,通过参数related_name指定options
 	    options = OptionRelatedSerializer(many=True, read_only=True)
在views中创建spec.py
class SpecBySpuView(ListAPIView):
 	    # def get(self,request,*args,**kwargs):
 	    # 根据标准商品编号查询规格及选项
 	    serializer_class = SpecBySpuSerializer
 	
 	    # 需要从路径中提取参数,拼接查询条件
 	    def get_queryset(self):
 	        # 视图对象的属性kwargs表示从路径中提取的关键字参数
 	        return SPUSpecification.objects.filter(spu_id=self.kwargs.get('spu_id'))
创建视图
    # 根据spu查询spec的路由goods/1/specs/
 	url('^goods/(?P<spu_id>\d+)/specs/$', spec.SpecBySpuView.as_view()),

结果:

  • 在sku表中添加数据
  • 在sku规格表中添加数据
  • 生成静态文件
  • 实现:重写序列化器的create()方法
  • 注意:将模板引擎改为jinja2
  • 注意:修改模板文件,将图片输出进行判断
在serializers的sku中添加
    # 创建sku时,需要接收规格数据,删除read_only=True参数
	    specs = SkuSpecRelatedSerializer(many=True)
		class Meta:
		    	model = SKU
       			exclude = ['create_time', 'update_time']	
    	def create(self, validated_data):
	        # SKU对应的表中没有属性specs,所以需要从字典中删除
	        specs = validated_data.pop('specs')
	
	        with transaction.atomic():  # 禁止自动提交
	            sid = transaction.savepoint()  # 开启事务
	            try:
	                # 创建sku对象
	                instance = SKU.objects.create(**validated_data)
	                # 遍历,创建sku规格对象
	                for item in specs:
	                    spec_id = item.get('spec_id')  # 规格编号
	                    option_id = item.get('option_id')  # 选项编号
	                    SKUSpecification.objects.create(sku_id=instance.id, spec_id=spec_id, option_id=option_id)
	            except:
	                transaction.savepoint_rollback(sid)  # 回滚事务
	                raise serializers.ValidationError('数据保存失败')
	            else:
	                transaction.savepoint_commit(sid)  # 提交事务
	
	                # 为sku生成静态文件
	                task_generate.delay(instance.id)
	
	                return instance
在celery_tasks的detail创建tasks.py
	from celery_tasks.main import app
 	import os
 	# 千万注意 --项目的包 在 最下面
 	from apps.goods import models
 	from apps.contents.utils import get_categories
 	from apps.goods.utils import get_breadcrumb
 	from django.template import loader
 	from django.conf import settings
 	from apps.goods.models import SKU
 	
 	
 	def generate_static_sku_detail_html(sku):
 	    # 1.detai_data
 	    # 查询商品频道分类
 	    categories = get_categories()
 	    # 查询面包屑导航
 	    breadcrumb = get_breadcrumb(sku.category)
 	
 	    # 构建当前商品的规格键
 	    sku_specs = sku.specs.order_by('spec_id')
 	    sku_key = []
 	    for spec in sku_specs:
 	        sku_key.append(spec.option.id)
 	    # 获取当前商品的所有SKU
 	    skus = sku.spu.sku_set.all()
 	    # 构建不同规格参数(选项)的sku字典
 	    spec_sku_map = {}
 	    for s in skus:
 	        # 获取sku的规格参数
 	        s_specs = s.specs.order_by('spec_id')
 	        # 用于形成规格参数-sku字典的键
 	        key = []
 	        for spec in s_specs:
 	            key.append(spec.option.id)
 	        # 向规格参数-sku字典添加记录
 	        spec_sku_map[tuple(key)] = s.id
 	    # 获取当前商品的规格信息
 	    goods_specs = sku.spu.specs.order_by('id')
 	    # 若当前sku的规格信息不完整,则不再继续
 	    if len(sku_key) < len(goods_specs):
 	        return
 	    for index, spec in enumerate(goods_specs):
 	        # 复制当前sku的规格键
 	        key = sku_key[:]
 	        # 该规格的选项
 	        spec_options = spec.options.all()
 	        for option in spec_options:
 	            # 在规格参数sku字典中查找符合当前规格的sku
 	            key[index] = option.id
 	            option.sku_id = spec_sku_map.get(tuple(key))
 	        spec.spec_options = spec_options
 	
 	    # 渲染页面
 	    context = {
 	        'categories': categories,
 	        'breadcrumb': breadcrumb,
 	        'sku': sku,
 	        'specs': goods_specs,
 	    }
 	
 	    # 2.detail_template_file
 	    template_file = loader.get_template('detail.html')
 	
 	    # 3.render
 	    html_text = template_file.render(context)
 	
 	    # 4.写入本地
 	    file_path = os.path.join(settings.STATICFILES_DIRS[0], 'detail/{}.html'.format(sku.id))
 	    with open(file_path, 'w') as f:
 	        f.write(html_text)
 	
 	
 	@app.task(bind=True, name="task_generate", retry_backoff=10)
 	def task_generate(self, sku_id):
 	    try:
 	        sku = SKU.objects.get(pk=sku_id)
 	        generate_static_sku_detail_html(sku)
 	    except Exception as e:
 	        raise self.retry(exc=e, max_retries=3)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值