Reputation: 288
In my application I have some products, and a logged in user should be able to mark these products as favorites.
I modeled them as a many to many relationship in my models.py
, like this:
class Product(models.Model):
product_name = models.CharField(max_length=200)
# ...
def __unicode__(self):
return self.product_name
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
favorites = models.ManyToManyField(Product)
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.get_or_create(user=instance)
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
What I'd like to achieve now is that on a product detail view the user can see if the product is already a favorite of his, and should be able to check a box to make it his favorite.
On the model level this is a many to many relationship, but on the view it is more of a boolean relationship (favorite yes/no for current user).
I already managed to have the favorite status displayed in the detail view, with a SerializerMethodField
class ProductSerializer(serializers.ModelSerializer):
# ...
favorite = serializers.SerializerMethodField()
def get_favorite(self, obj):
try:
self.context['request'].user.profile.favorites.get(pk=obj.pk)
return True
except Product.DoesNotExist:
return False
What I am struggling with currently is adding a favorite to the current user's list of favorites with this setup, as this SerializerMethodField
is read-only and, because of that, doesn't appear in the validated_data in the update()
method.
Does anyone have a solution for this or a similar problem?
Upvotes: 2
Views: 935
Reputation: 7923
You can create custom field.
class FavoriteField(serializers.BooleanField):
def get_attribute(self, instance):
return self.context['request'].user.profile.favorites.filter(pk=instance.pk).exists()
class ProductSerializer(serializers.ModelSerializer):
favorite = FavoriteField()
def update(self, instance, validated_data):
instance = super().update(instance, validated_data)
is_favourite = validated_data.get('favorite') # can be None
if is_favourite is True:
self.context['request'].user.profile.favorites.add(instance)
elif is_favourite is False:
self.context['request'].user.profile.favorites.remove(instance)
return instance
Upvotes: 1