Skip to content

Commit

Permalink
improvements to like field/likes + some bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
JasonLovesDoggo committed Jan 3, 2024
1 parent b6108d5 commit 871b8a1
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 15 deletions.
21 changes: 13 additions & 8 deletions core/api/serializers/custom/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
from django.utils.encoding import smart_str
from django.conf import settings
from rest_framework import serializers
from rest_framework.fields import Field, MultipleChoiceField

Expand All @@ -26,29 +27,33 @@ def to_representation(self, obj):
}


# todo switch all of these back to ChoiceField. refer to git history for the old code.
class ContentTypeField(serializers.Field):
class ContentTypeField(serializers.ChoiceField):
def __init__(self, **kwargs):
self.slug_field = "model"
choices = ContentType.objects.filter(
app_label="core", model__in=settings.POST_CONTENT_TYPES
).values_list("model", "model")
default_error_messages = {
"does_not_exist": "ContentType with model '{value}' does not exist.",
"invalid": 'Invalid value. Expected string with the model name e.g. "Comment"',
"does_not_exist": "ContentType with model '{value}' does not exist."
}
kwargs["help_text"] = 'The model name e.g. "Comment" or "BlogPost"'
super().__init__(**kwargs)
super().__init__(choices, **kwargs)
self.default_error_messages.update(default_error_messages)

def to_internal_value(self, data):
try:
return ContentType.objects.get(app_label="core", model=str(data).casefold())
return ContentType.objects.get(app_label="core", model=data)
except ObjectDoesNotExist:
self.fail("does_not_exist", value=smart_str(data))
self.fail(
"does_not_exist", slug_name=self.slug_field, value=smart_str(data)
)
except (TypeError, ValueError):
self.fail("invalid")

def to_representation(self, obj):
return obj.model



class SingleUserSerializer(serializers.ModelSerializer):
gravatar_url = serializers.SerializerMethodField(read_only=True)

Expand Down
23 changes: 18 additions & 5 deletions core/api/views/objects/post_interactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,20 @@ def get_last_modified_queryset():

class LikeSerializer(serializers.ModelSerializer):
content_type = ContentTypeField()


def update(self, instance, validated_data):
raise NotImplementedError("You cannot update a like, if you wish to delete. do so.")

def destroy(self, instance: Like, validated_data):
if instance.author != self.context["request"].user:
raise ValidationError("You cannot unlike another user's like.")
instance.delete(force=True)

def create(self, validated_data) -> Like:
obj_name = validated_data["content_type"].name.lower().replace(" ", "")
if (self.context["request"].user != validated_data["author"]) and not self.context["request"].user.is_superuser:
raise ValidationError("You cannot like as another user.")

if obj_name not in settings.POST_CONTENT_TYPES: # is the object type valid?
raise ValidationError(
f"Invalid object type: {obj_name}, valid types are: {settings.POST_CONTENT_TYPES}"
Expand All @@ -191,15 +202,17 @@ def create(self, validated_data) -> Like:
.exists()
): # does the object exist?
raise ValidationError(f"The specified {obj_name} does not exist.")

if Like.objects.filter( # has the user already liked this object?
content_type=validated_data["content_type"],
object_id=validated_data["object_id"],
author=self.context["author"],
author=validated_data['author'], # author is current user?
).exists():
raise ValidationError(f"User has already liked this {obj_name}")
like = Like(**validated_data)
like.save()
return like
else:
like = Like(**validated_data)
like.save()
return like

class Meta:
model = Like
Expand Down
4 changes: 2 additions & 2 deletions core/models/post.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ def delete(self, using=None, keep_parents=False, **kwargs):
Don't actually delete the object, just set the user to None and save it. This way, we can still keep track of the likes, saves and comments.
if force is set to True, then it will actually delete the object (used for when you want to delete a comment or unlike/save something)
"""
if kwargs.get("force", True):
super().delete(using=using, keep_parents=keep_parents)
if kwargs.get("force", False):
return super().delete(using=using, keep_parents=keep_parents)
self.user = None
self.save()

Expand Down

0 comments on commit 871b8a1

Please sign in to comment.