Foreword
When adding a product earlier, the product code can only be added once and can be verified with a unique field using the UniqueValidator. If a user collects a product, one user can collect multiple products, and one product can also be collected by multiple people.
However, the same person can only collect the same product once, so you can use UniqueTogetherValidator to jointly uniquely verify
Collection product
Add products and collect products models.py model design
from django.db import models from django.contrib.auth.models import User # Create your models here. # Author-Shanghai Youyou QQ communication group: 717225969 # blog address https://www.cnblogs.com/yoyoketang/ class Goods(models.Model): """Product List""" goods_name = models.CharField(max_length=30, default="", verbose_name="product name") goods_code = models.CharField(max_length=30, unique=True, verbose_name="Product code") merchant_id = models.CharField(max_length=30, default="", blank=True, null=True, verbose_name="merchant ID") merchant_name = models.CharField(max_length=30, default="", blank=True, null=True, verbose_name="merchant name") # goods_price = models.FloatField(blank=True, null=True, # default=0, # verbose_name="Product price") goods_price = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, default=0, verbose_name="product price") goods_stock = models.IntegerField(blank=True, null=True, default=0, verbose_name="item inventory") goods_groupid = models.IntegerField(blank=True, null=True, default=0, verbose_name="Product group") goods_status = models.IntegerField(choices=( (0, 'Removed'), (1, 'For Sale') ), default=1, verbose_name="0 off the shelves 1 on sale") price = models.FloatField(blank=True, null=True, default=0, verbose_name="cost price") create_time = models.DateTimeField(auto_now_add=True, verbose_name="Add Time") update_time = models.DateTimeField(auto_now=True, verbose_name="Modification time") class Meta: verbose_name_plural = 'commodity' verbose_name = "Product information" def __str__(self): return self.goods_code class UserCollect(models.Model): """User Favorites""" user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="userid") goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name="goods", help_text="goods id") status = models.CharField(choices=( (0, 'Cancel favorite'), (1, 'Collected') ), default=1, verbose_name="0 Uncollect 1 Collect") create_time = models.DateTimeField(auto_now_add=True, verbose_name="Add Time") update_time = models.DateTimeField(auto_now=True, verbose_name="Modification time") class Meta: verbose_name = 'User Collection' verbose_name_plural = verbose_name # Unique combination, a product can only be collected once unique_together = ("user", "goods") def __str__(self): return self.user.username
Serialized Collection Product
During serialization, the user field is a hidden field and does not need to be passed by the user. As long as the user is logged in, he can obtain the currently logged in account through request.user.
status has 2 statuses, which do not need to be passed in by the user. Set read_only=True
validators.UniqueTogetherValidator jointly verifies the uniqueness of ‘user’, ‘goods’ fields
This validator can be used unique_together to impose constraints on model instances. It has two required parameters and an optional messages parameter:
- queryset required – This is the queryset against which uniqueness should be enforced.
- fields Required – A list or tuple of field names that should form a unique set. These must exist as fields in the serializer class.
- message – The error message that should be used when validation fails.
from .models import Goods, UserCollect from rest_framework import validators # Author-Shanghai Youyou QQ communication group: 717225969 # blog address https://www.cnblogs.com/yoyoketang/ class UserCollectSerializer(serializers.ModelSerializer): # Get the currently logged in user user = serializers.HiddenField( default=serializers.CurrentUserDefault() ) status = serializers.ChoiceField(choices=( (0, 'Cancel favorite'), (1, 'Collected') ), read_only=True) def to_representation(self, instance): """return of to_representation custom serialized data""" data = super().to_representation(instance) data.update(status=instance.get_status_display()) return data class Meta: # validate achieves unique union, a product can only be collected once validators = [ validators.UniqueTogetherValidator( queryset=UserCollect.objects.all(), fields=('user', 'goods'), #The message information can be customized message="Collected" ) ] model = UserCollect # You need to return the product ID when collecting, because you must know the product ID when canceling collection. fields = '__all__' # Return all fields
Add views to favorites and queries
# Author-Shanghai Youyou QQ communication group: 717225969 # blog address https://www.cnblogs.com/yoyoketang/ class UserCollectAPIView(APIView): """my collection""" def get(self, request, *args, **kwargs): """Check my collection""" collect = UserCollect.objects.all().filter(status=1, user=request.user) # Query your own collection serializer = UserCollectSerializer(instance=collect, many=True, context={"request": request}) return Response({ "code": 0, "msg": "success!", "data": serializer.data }) def post(self, request, *args, **kwargs): """Add to Favorites""" verify_data = UserCollectSerializer(data=request.data, context={"request": request}) if verify_data.is_valid(): save = verify_data.save() return Response({ "code": 0, "msg": "success!", "data": UserCollectSerializer(instance=save, context={"request": request}).data }) else: return Response({ "code": 10086, "msg": "Illegal parameter", "data": verify_data.errors })
Test my collection function
When collecting products, just pass the product ID
If it has been collected, it will prompt that it has been collected
When querying, each user only queries his own data with status 1