スライダーコンポーネントのAPI実装
最初に、PyCharmの開発環境をローカルに設定し、Vueの設定もローカルホストに変更します。
- goods/serializer.py
class BannerSerializer(serializers.ModelSerializer):
class Meta:
model = Banner
fields = '__all__'
- goods/views.py
class BannerViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
queryset = Banner.objects.all().order_by('index')
serializer_class = BannerSerializer
- urls.py
router.register(r'banners', BannerViewSet, basename='banners')
管理画面からスライダーバナー画像を追加します。
新商品フィルタリング機能の実装
商品モデルにはis_newというフィールドがあります。
is_new = models.BooleanField('新商品かどうか', default=False)
この機能を実装するには、GoodsFilterクラスにこのフィールドを追加するだけです。
class Meta:
model = Goods
fields = ['pricemin', 'pricemax', 'is_hot', 'is_new']
管理画面でいくつかの商品に対してis_newをTrueに設定します。
ホーム画面のカテゴリ表示機能
トップカテゴリには以下のような情報を含めます:
- ブランドロゴ(複数)
- サブカテゴリ
- 広告商品
- 全商品一覧
- goods/serializers.py
class BrandSerializer(serializers.ModelSerializer):
class Meta:
model = GoodsCategoryBrand
fields = '__all__'
class IndexCategorySerializer(serializers.ModelSerializer):
brands = BrandSerializer(many=True)
goods = serializers.SerializerMethodField()
sub_cat = CategorySerializer2(many=True)
ad_goods = serializers.SerializerMethodField()
def get_ad_goods(self, obj):
try:
ad_good = IndexAd.objects.get(category_id=obj.id).goods
return GoodsSerializer(ad_good, context={'request': self.context['request']}).data
except IndexAd.DoesNotExist:
return {}
def get_goods(self, obj):
goods = Goods.objects.filter(
Q(category_id=obj.id) |
Q(category__parent_category_id=obj.id) |
Q(category__parent_category__parent_category_id=obj.id)
)
return GoodsSerializer(goods, many=True, context={'request': self.context['request']}).data
class Meta:
model = GoodsCategory
fields = '__all__'
- goods/views.py
class IndexCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
queryset = GoodsCategory.objects.filter(is_tab=True, name__in=['食品', '飲料'])
serializer_class = IndexCategorySerializer
- urls.py
router.register(r'indexgoods', IndexCategoryViewSet, basename='indexgoods')
商品のクリック数とお気に入り数の管理
- クリック数の更新
class GoodsListViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
queryset = Goods.objects.all().order_by('id')
serializer_class = GoodsSerializer
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
instance.click_num += 1
instance.save()
return Response(self.get_serializer(instance).data)
- お気に入り数の更新(シグナルによる実装)
# signals.py
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from user_operation.models import UserFav
@receiver(post_save, sender=UserFav)
def update_fav_count_on_save(sender, instance, created, **kwargs):
if created:
instance.goods.fav_num += 1
instance.goods.save()
@receiver(post_delete, sender=UserFav)
def update_fav_count_on_delete(sender, instance, **kwargs):
instance.goods.fav_num -= 1
instance.goods.save()
# apps.py
class UserOperationConfig(AppConfig):
name = 'user_operation'
def ready(self):
import user_operation.signals
在庫と販売数の更新処理
- 在庫数の更新
class ShoppingCartViewSet(viewsets.ModelViewSet):
def perform_create(self, serializer):
cart = serializer.save()
cart.goods.goods_num -= cart.nums
cart.goods.save()
def perform_destroy(self, instance):
goods = instance.goods
goods.goods_num += instance.nums
goods.save()
instance.delete()
def perform_update(self, serializer):
before = ShoppingCart.objects.get(id=serializer.instance.id)
goods = before.goods
delta = serializer.validated_data['nums'] - before.nums
goods.goods_num -= delta
goods.save()
serializer.save()
- 販売数の更新(支払い完了時)
for order_good in order_goods:
goods = order_good.goods
goods.sold_num += order_good.goods_num
goods.save()
DRFでのキャッシュ設定
キャッシュを導入することで、データ取得の高速化を実現します。
- インストール
pip install drf-extensions
- goods/views.py
from rest_framework_extensions.cache.mixins import CacheResponseMixin
class GoodsListViewSet(CacheResponseMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
...
- settings.py
REST_FRAMEWORK_EXTENSIONS = {
'DEFAULT_CACHE_RESPONSE_TIMEOUT': 5
}
Redisを用いたキャッシュ構成
- インストール
pip install django-redis
- settings.py
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
}
}
}
APIアクセスレート制限
- settings.py
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
),
'DEFAULT_THROTTLE_RATES': {
'anon': '3/minute',
'user': '5/minute'
}
}
- goods/views.py
from rest_framework.throttling import UserRateThrottle, AnonRateThrottle
class GoodsListViewSet(CacheResponseMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
throttle_classes = (UserRateThrottle, AnonRateThrottle)