商品列表頁、詳情頁功能實現


打造生鮮超市(一):項目介紹,環境搭建
打造生鮮超市(二):model設計
打造生鮮超市(三):xadmin后台管理

打造生鮮超市(四):商品列表頁
打造生鮮超市(五):商品類別數據顯示

一、商品列表頁

1、 goods/serializers.py 序列化

from rest_framework import serializers
from goods.models import GoodsCategory

class CategorySerializer3(serializers.ModelSerializer):
    '''三級分類'''
    class Meta:
        model = GoodsCategory
        fields = "__all__"

class CategorySerializer2(serializers.ModelSerializer):
    '''二級分類'''
    sub_cat = CategorySerializer3(many=True)
    class Meta:
        model = GoodsCategory
        fields = "__all__"
#
class CategorySerializer(serializers.ModelSerializer):
    '''一級分類'''
    sub_cat = CategorySerializer2(many=True)
    class Meta:
        model = GoodsCategory
        fields = "__all__"
class GoodsSerializer(serializers.ModelSerializer): category = CategorySerializer() #覆蓋默認的category序列化字段 images = GoodsImageSerializer(many=True) # images名稱是GoodsImage中goods = models.ForeignKey(Goods, verbose_name="商品", related_name="images") # related_name="images" 中的images class Meta: model = Goods fields = "__all__" # 取所有字段

2、goods/filter

django_filters

# 官方文檔:https://django-filter.readthedocs.io/en/stable/guide/rest_framework.html#quickstart

import django_filters
from django.db.models import Q
from .models import Goods

class GoodsFilter(django_filters.rest_framework.FilterSet):
    """
    商品的過濾類
    """
    # 自從 django-filter2.0之后 將Filter的name字段 更名為 field_name(本項目用的django-filter2.3)
    pricemin = django_filters.NumberFilter(field_name='shop_price', help_text="最低價格",lookup_expr='gte')
    pricemax = django_filters.NumberFilter(field_name='shop_price', lookup_expr='lte')
    top_category = django_filters.NumberFilter(method='top_category_filter')

    #
    def top_category_filter(self, queryset, name, value):
        return queryset.filter(Q(category_id=value)|Q(category__parent_category_id=value)|Q(category__parent_category__parent_category_id=value))


    #
    class Meta:
        model = Goods
        fields = ['pricemin', 'pricemax', 'is_hot', 'is_new']

3、goods/views.py

from .serializers import GoodsSerializer, CategorySerializer, HotWordsSerializer, BannerSerializer
from rest_framework import mixins
from rest_framework import filters
from rest_framework.pagination import PageNumberPagination
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import viewsets

# .models:加 . 的好處表示從當前的goods目錄下找models,加速查找且不容易找失敗
from .models import Goods, GoodsCategory
from .filters import GoodsFilter

# 自定義分頁
class GoodsPagination(PageNumberPagination):
    page_size = 12                        # 每一頁顯示多少條數據
    page_query_param = "page"             # url中指定顯示哪一頁的數據    ?page=2
    page_size_query_param = 'page_size'   # 臨時控制每頁顯示幾條數據     ?page=2&page_size=2
    max_page_size = 100                   # 每頁最多顯示多少條數據,針對上面的size

class GoodsListViewSet(mixins.ListModelMixin,mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    """
    商品列表頁, 分頁, 搜索, 過濾, 排序
    """
    queryset = Goods.objects.all()#
    serializer_class = GoodsSerializer#

    pagination_class = GoodsPagination#
    # authentication_classes = (TokenAuthentication, )  # 商品列表頁是公開的,不需要授權認證
    filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)#
    filter_class = GoodsFilter#
    search_fields = ('name', 'goods_brief', 'goods_desc')#
    ordering_fields = ('sold_num', 'shop_price')#
#
class CategoryViewset(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    """
    list:
        商品分類列表數據
    retrieve:
        獲取商品分類詳情
    """
    queryset = GoodsCategory.objects.filter(category_type=1) # 獲取第一類數據
    serializer_class = CategorySerializer

4、urls.py

# 配置Category的url
router.register(r'categorys', CategoryViewSet, base_name="categorys")

二、drf跨域問題

后端服務器解決跨域問題的方法

1、安裝模塊django-cors-headers

pip install django-cors-headers

2、 添加到INSTALL_APPS中

INSTALLED_APPS = (
    ...
    'coreschema',
 ... )

3、添加中間件

必須在CsrfViewMiddleware之前。我們直接放在第一個位置就好了 

4、settings中相關設置

CORS_ORIGIN_ALLOW_ALL = True

三、商品詳情頁

打造生鮮超市(七):商品詳情頁功能

相關blog

相似問題

 

1、商品輪播圖goods/serializers.py 

from rest_framework import serializers
from goods.models import Goods,  GoodsImage

# 商品詳情頁輪播圖
class GoodsImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsImage
        fields = ("image", )

class GoodsSerializer(serializers.ModelSerializer):
    category = CategorySerializer()  #覆蓋默認的category序列化字段
    images = GoodsImageSerializer(many=True)
    # images名稱是GoodsImage中goods = models.ForeignKey(Goods, verbose_name="商品", related_name="images")
    #  related_name="images" 中的images
    class Meta:
        model = Goods
        fields = "__all__"  # 取所有字段

2、熱銷商品

只需要在過濾器中增加“is_hot”就可以了
goods/filters.py里的GoodsFilter添加“is_hot”

    class Meta:
        model = Goods
        fields = ['pricemin', 'pricemax','is_hot']

3、用戶收藏

CurrentUserDefault

UniqueTogetherValidator

Custom permissions:Examples

Attributes:lookup_field

HiddenField:
HiddenField的值不依靠輸入,而需要設置默認的值,不需要用戶自己post數據過來,也不會顯式返回給用戶,最常用的就是user!!
我們在收藏某件商品的時候,后台要獲取到當前的用戶;相當於前台只需要傳遞過來一個商品的ID即可;
那么在后台我根據當前的登入用戶和當前的商品ID即可判斷用戶是否收藏過該商品;這就是一個聯合唯一主鍵的判斷;這同樣需要使用HiddenField。

 (1)序列化

user_operation/serializers.py

from rest_framework import serializers
from user_operation.models import UserFav
from rest_framework.validators import UniqueTogetherValidator

class UserFavSerializer(serializers.ModelSerializer):
    #獲取當前登錄的用戶
    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )
    class Meta:
        #validate實現唯一聯合,一個商品只能收藏一次
        validators = [
            UniqueTogetherValidator(
                queryset=UserFav.objects.all(),
                fields=('user', 'goods'),
                #message的信息可以自定義
                message="已經收藏"
            )
        ]
        model = UserFav
        #收藏的時候需要返回商品的id,因為取消收藏的時候必須知道商品的id是多少
        fields = ("user", "goods",'id')

(2)user_operation/views.py 

from rest_framework import viewsets
from rest_framework import mixins
from rest_framework.permissions import IsAuthenticated
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.authentication import SessionAuthentication

from .models import UserFav, UserLeavingMessage, UserAddress
from utils.permissions import IsOwnerOrReadOnly
from .serializers import UserFavSerializer, UserFavDetailSerializer, AddressSerializer, LeavingMessageSerializer


class UserFavViewset(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin,
                     mixins.DestroyModelMixin, viewsets.GenericViewSet):
    """
    list:
        獲取用戶收藏列表
    retrieve:
        判斷某個商品是否已經收藏
    create:
        收藏商品
  destory:
     取消收藏
""" # queryset = UserFav.objects.all() # 不能獲取所有人的UserFav serializer_class = UserFavSerializer # IsAuthenticated:用戶必須登錄,IsOwnerOrReadOnly:必須是當前的用戶在操作 permission_classes = (IsAuthenticated, IsOwnerOrReadOnly) # auth使用來做用戶認證的 authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication) # 搜索的字段 lookup_field = "goods_id" # 獲取當前用戶的 UserFav def get_queryset(self): return UserFav.objects.filter(user=self.request.user) 

(3)配置url

# 配置用戶收藏的url
router.register(r'userfavs', UserFavViewset, base_name="userfavs")

 

打賞

免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2022 CODEPRJ.COM