django rest framework 学习笔记-实战商城3

01用户模块模型定义_哔哩哔哩_bilibili 本博客借鉴至大佬的视频学习笔记

用户模块及商品数据表结构设计

from ckeditor.fields import RichTextField  # pip install django-ckeditor
from django.db import models

# Create your models here.
# from wx.richtext import RichTextField

from common.db import BaseModel


class GoodsGroup(BaseModel):
    """商品分类"""
    name = models.CharField(verbose_name="分类名称", help_text="分类名称", max_length=15,blank=True,null=True)
    image = models.CharField(verbose_name="图片链接", help_text="图片链接", max_length=200, blank=True, null=True)
    status = models.BooleanField(verbose_name="是否启用", help_text="是否启用", default=False,blank=True,null=True)

    class Meta:
        db_table = 'goods_group'
        verbose_name = "商品分类表"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name


class Goods(BaseModel):
    """商品"""
    group = models.ForeignKey('GoodsGroup', verbose_name="分类", help_text="分类", max_length=15, on_delete=models.CASCADE)
    image = models.CharField(verbose_name="图片链接", help_text="图片链接", max_length=200, blank=True, null=True)
    title = models.CharField(verbose_name="标题", help_text="标题", max_length=20, blank=True,null=True)
    desc = models.CharField(verbose_name="商品描述", help_text="商品描述", max_length=200, blank=True,null=True)
    price = models.DecimalField(verbose_name="商品价格", help_text="商品价格", max_digits=10, decimal_places=2, blank=True,null=True)
    cover = models.ImageField(verbose_name="封面图链接", help_text="封面图链接", max_length=200, blank=True,null=True)
    stock = models.IntegerField(verbose_name="库存", help_text="库存", blank=True, null=True, default=1)
    sales = models.IntegerField(verbose_name="销量", help_text="销量", blank=True, null=True, default=0)
    is_on = models.BooleanField(verbose_name="是否上架", help_text="是否上架", blank=True, null=True, default=False)
    recommend = models.BooleanField(verbose_name="是否推荐", help_text="是否推荐", blank=True, null=True, default=False)

    class Meta:
        db_table = 'goods'
        verbose_name = '商品表'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.title


class Detail(BaseModel):
    """商品详情"""
    goods = models.OneToOneField('Goods', verbose_name="商品", on_delete=models.CASCADE, max_length=200)
    producer = models.CharField(verbose_name='厂商', help_text='厂商', max_length=200, blank=True,null=True)
    norms = models.CharField(verbose_name='规格', help_text='规格', max_length=200, blank=True,null=True)
    details = RichTextField(verbose_name='商品详情', help_text='商品详情', max_length=200,blank=True,null=True)

    class Meta:
        db_table = 'details'
        verbose_name = '详情'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.goods


class GoodsBanner(BaseModel):
    """商品轮播图"""
    title = models.CharField(verbose_name='轮播图名称', help_text='轮播图名称', max_length=20, blank=True)
    image = models.ImageField(verbose_name='轮播图链接', help_text='轮播图链接', max_length=200, blank=True)
    # url = models.CharField(verbose_name='跳转的地址',help_text='跳转的地址',max_length=200,blank=True)
    status = models.BooleanField(verbose_name='是否启用', help_text='是否启用', default=False,blank=True,null=True)
    seq = models.IntegerField(verbose_name='顺序', help_text='顺序', default=1, blank=True,null=True)

    class Meta:
        db_table = 'banner'
        verbose_name = '首页商品轮播'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.title


class Collect(models.Model):
    """商品收藏"""
    user = models.ForeignKey('users.User', help_text='用户ID', verbose_name='用户ID', on_delete=models.CASCADE,blank=True,null=True)
    goods = models.ForeignKey('goods.Goods', help_text="商品ID", verbose_name="商品ID", on_delete=models.CASCADE,blank=True,null=True)

    class Meta:
        db_table = 'collect'
        verbose_name = "收藏商品"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.goods

Django自带admin配置

from django.contrib import admin
from .models import GoodsGroup,Goods,Detail,GoodsBanner,Collect
# Register your models here.

@admin.register(GoodsGroup)
class GoodsGroupAdmin(admin.ModelAdmin):
    list_display = ['name','status']

@admin.register(Goods)
class GoodsAdmin(admin.ModelAdmin):
    list_display = ['title','group','price','stock','sales','is_on']

@admin.register(Detail)
class DetailGroupAdmin(admin.ModelAdmin):
    list_display = ['goods', 'producer','norms']

@admin.register(GoodsBanner)
class GoodsBannerAdmin(admin.ModelAdmin):
    list_display = ['title', 'status']

@admin.register(Collect)
class CollectAdmin(admin.ModelAdmin):
    list_display = ['user', 'goods']

商品首页接口实现

class IndexView(APIView):
    """首页数据展示"""
    def get(self,request):
        """返回轮播图、商品分类"""
        group = GoodsGroup.objects.filter(status=True)
        groupSer =GoodsGroupSerializer(group,many=True)
        # 轮播图
        banner = GoodsBanner.objects.filter(status=True)
        bannerSer = GoodsBannerSerializer(banner,many=True)
        # 推荐的商品
        goods = Goods.objects.filter(recommend=True)
        goodsSer = GoodsSerializer(goods,many=True)
        # 返回数据
        result = {
            'banner': bannerSer.data,
            'goods':goodsSer.data,
            'group':groupSer.data
        }
        return Response({"message":'ok','data':result},status=status.HTTP_200_OK)

# 商品首页
path('index/', IndexView.as_view()),

商品列表获取和分类排序接口

# view
class GoodsView(ReadOnlyModelViewSet):
    """"商品列表接口"""
    serializer_class = GoodsSerializer
    # 选择上架的商品
    queryset = Goods.objects.filter(is_on=True),
    # 实现商品分类和推荐类过滤
    filterset_fields = ('group','recommend')
    # 通过价格和销量排序
    ordering_fields =('sales','price','create_time')

# url
# 商品列表接口
path('goods/', GoodsView.as_view({"get":'list'})),
# 单个商品获取
path('goods/<int:pk>/', GoodsView.as_view({"get":'retrieve'})),

# setting
# 过滤器信息配置、排序器配置
'DEFAULT_FILTER_BACKENDS':['django_filters.rest_framework.DjangoFilterBackend',
  'rest_framework.filters.OrderingFilter']

# 注册
'django_filters',

商品的收藏与取消收藏接口

# view
class CollectView(mixins.RetrieveModelMixin,
                  mixins.CreateModelMixin
                  ,mixins.ListModelMixin,mixins.DestroyModelMixin,GenericViewSet):
    """
    商品收藏与取消
    create: 收藏
    delete: 取消
    list: 收藏列表
    """
    queryset = Collect.objects.all()
    serializer_class = CollectSerializer
    permission_classes =  [IsAuthenticated,CollectPermissions]
    filterset_fields = ("user",)

    def create(self, request, *args, **kwargs):
        # 获取请求参数
        user = request.user
        params_user_id = request.data.get('user')
        # 检验请求参数中的id是否当前登录的用户ID
        if user.id != params_user_id:
            return Response({'error':'你没有用户权限访问该信息'},status=status.HTTP_400_BAD_REQUEST)
        return super().create(request, *args, **kwargs)

    def list(self, request, *args, **kwargs):
        """商品收藏列表"""
        queryset = self.filter_queryset(self.get_queryset())
        queryset = queryset.filter(user=request.user)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


# perssion
from rest_framework import permissions
class CollectPermissions(permissions.BasePermission):
    """
    Custom permission to only allow owners of an object to edit it.
    """
    def has_object_permission(self, request, view, obj):
        # 判断是否是管理员
        if request.user.is_superuser:
            return True
        # 判断当前的用户对象和登录的用户对象是否是同一个,防止越权
        return obj == request.user

# url
# 收藏商品
path('collect/', CollectView.as_view({"post":'create','get':'list'})),
# 取消收藏
path('collect/del/<int:pk>/', CollectView.as_view({"delete":'destroy'})),

商品购物车的接口实现: 购物车添加数量、修改商品购物车状态、加购商品

# serializer
from rest_framework import serializers
from apps.cart.models import Cart
from apps.goods.serializers import GoodsSerializer

class CartSerializer(serializers.ModelSerializer):
    """用户的模型序列化器-写入"""
    class Meta:
        model = Cart
        fields = '__all__'

class ReadInfoSerializer(serializers.ModelSerializer):
    """用户的模型序列化器-读取"""
    goods =GoodsSerializer()
    class Meta:
        model = Cart
        fields = '__all__'


# view
from rest_framework import status
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet,mixins
from .models import Cart
from .serializers import CartSerializer, ReadInfoSerializer


# Create your views here.

class  CartViecw(GenericViewSet,
                 mixins.CreateModelMixin,
                 mixins.UpdateModelMixin,
                 mixins.DestroyModelMixin,
                 mixins.ListModelMixin):
    queryset = Cart.objects.all()
    serializer_class = CartSerializer

    def get_serializer_class(self):
        # 实现读写操作使用不同的序列化器
        if self.action == 'list':
            return ReadInfoSerializer
        else:
            return self.serializer_class

    def create(self, request, *args, **kwargs):
        user = request.user
        goods  =request.data.get('goods')
        if Cart.objects.filter(user=user,goods=goods):
            # 该商品存在
            cart_goods = Cart.objects.get(user=user,goods=goods)
            cart_goods.number +=1
            cart_goods.save()
            # 商品序列化
            serializer = self.get_serializer(cart_goods)
            return Response(serializer.data,status=status.HTTP_201_CREATED)
        else:
            # 没有该商品则进行添加该商品
            request.data['user'] = user.id
            return super().create(request,*args,**kwargs)

    def list(self, request, *args, **kwargs):
        query =self.get_queryset().filter(user=request.user)
        serializer = self.get_serializer(query, many=True)
        return Response(serializer.data)

    def update_goods_status(self,request, *args, **kwargs):
        obj =self.get_object()
        obj.is_checked = not obj.is_checked
        obj.save()
        return Response({"message":'修改成功'},status=status.HTTP_200_OK)
    def update_goods_number(self,request, *args, **kwargs):
        number = request.data.get('number')
        obj = self.get_object()
        if not isinstance(number,int): return Response({'error':'参数number只可为INT类型'})
        if number > obj.goods.stock:
            return Response({"message": "数量不可超过该商品的库存数量"}, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
        elif number <= 0:
            obj.delete()
            return Response({"message":"修改成功,已删除"},status=status.HTTP_200_OK)
        else:
            obj.number = number
            obj.save()
            return Response({"message": "修改成功"}, status=status.HTTP_200_OK)

# url
from apps.cart.views import CartViecw
urlpatterns = [
    # 商品首页
    path('cart/', CartViecw.as_view({"post":'create','get':'list'})),
    # 修改商品购物车的状态
    path('cart/<int:pk>/checked/', CartViecw.as_view({"put":'update_goods_status'})),
    # 修改商品数量
    path('cart/<int:pk>/number/', CartViecw.as_view({"put": 'update_goods_number'})),

]

以上是django restframework商城的后端实现。

相关推荐
infiniteWei9 分钟前
【Lucene】什么是全文检索?解读结构化数据与非结构化数据
django·全文检索·lucene
怀旧66626 分钟前
spring boot 项目配置https服务
java·spring boot·后端·学习·个人开发·1024程序员节
infiniteWei1 小时前
【Lucene】全文检索 vs 顺序扫描,为何建立索引比逐个文件搜索更高效?
django·全文检索·lucene
infiniteWei1 小时前
【Lucene】原理学习路线
学习·搜索引擎·全文检索·lucene
德育处主任Pro2 小时前
『Django』APIView基于类的用法
后端·python·django
follycat2 小时前
[极客大挑战 2019]PHP 1
开发语言·学习·网络安全·php
weixin_518285053 小时前
深度学习笔记11-神经网络
笔记·深度学习·神经网络
并不会6 小时前
常见 CSS 选择器用法
前端·css·学习·html·前端开发·css选择器
龙鸣丿6 小时前
Linux基础学习笔记
linux·笔记·学习
Nu11PointerException8 小时前
JAVA笔记 | ResponseBodyEmitter等异步流式接口快速学习
笔记·学习