Here I have two models called PostComment and AnswerComment separately to handle comments in my web application. Now I need to have voting option for both Post and Answer comments. Therefore I though using Django GenericRelations here would be a good idea to continue. I have implemented all the parts and I can't use Django Rest Framework to post data with Django HyperlinkedRelatedField. I'm using rest-framework-generic-relations (link) app as DRF documentation has recommended it. It gives me following error when I try to post data.
Followings are my implementations,
Post and Answer Models,
class PostComment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
comment = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class AnswerComment(models.Model):
answer = models.ForeignKey(Answer, on_delete=models.CASCADE)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
comment = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Comment Model,
class VoteType(models.TextChoices):
EMPTY = 'EMPTY'
LIKE = 'LIKE'
DISLIKE = 'DISLIKE'
class CommentVote(models.Model):
voteType = models.CharField(max_length=10, choices=VoteType.choices, default=VoteType.EMPTY)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now=True)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
voted_object = GenericForeignKey('content_type', 'object_id')
Serializer for vote (as implemented in the documentation),
class CommentVoteSerializer(serializers.ModelSerializer):
voted_object = GenericRelatedField({
AnswerComment: serializers.HyperlinkedRelatedField(
queryset=AnswerComment.objects.all(),
view_name='answercomment-detail'
),
PostComment: serializers.HyperlinkedRelatedField(
queryset=PostComment.objects.all(),
view_name='postcomment-detail'
),
})
class Meta:
model = CommentVote
fields = ['voted_object', 'voteType', 'owner']
View for vote,
class CommentVoteViewSet(viewsets.ModelViewSet):
queryset = CommentVote.objects.all()
serializer_class = CommentVoteSerializer
Urls for vote,
router.register(r'comment_vote', CommentVoteViewSet, basename='comment_vote_api')
Any help would be great. Thank you!
Related
models
class CreatorRawArtwork(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=500)
descripton = models.TextField()
editions = models.IntegerField(null=True, blank=True)
price = models.CharField(max_length=500)
created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)
medias = models.FileField(null=True, blank=True, upload_to="raw-medias")
user = models.ForeignKey(to=Login, on_delete=models.CASCADE, related_name="creatorrawartwork", null=True, blank=True
)
collection = models.ForeignKey(
to=DesignerCollection, on_delete=models.CASCADE, related_name="creatorrawartwork", null=True, blank=True)
categories = models.ManyToManyField(DesignerCategories, related_name='creatorrawartwork')
def __str__(self):
return self.title
serializer
class CreatorRawArtworkSerializer(serializers.ModelSerializer):
categories = serializers.PrimaryKeyRelatedField(queryset=DesignerCategories.objects.all(), many=True)
class Meta:
model = CreatorRawArtwork
fields = "__all__"
depth=1
views
class CreatorRawArtworkView(viewsets.ModelViewSet):
queryset = CreatorRawArtwork.objects.all()
serializer_class = CreatorRawArtworkSerializer
Here i am trying to create manytomany fields using drf serialier it is showing some error
plese check the screenshot for parameter and responses
What can be the issue please take a look
class CreatorRawArtworkSerializer(serializers.ModelSerializer):
collection = DesignerCollectionSerializer(read_only=True) #assuming you have already defined serializer for *DesignerCollectionSerializer*
categories = DesignerCategoriesSerializer(many=True)
class Meta:
model = CreatorRawArtwork
fields = "__all__"
depth=1
I tested with your code and your code is working fine
just make sure your request data is json
I have 3 fields in my model. below is the code.
Model.py
class Settings(models.Model):
typeOptions = (
('txt', 'text'),
('img', 'image'),
('json', 'json'),
)
title = models.CharField(max_length=80)
type = models.CharField(max_length=5, choices=typeOptions, default='txt')
value = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey(User, null=True, editable=False, on_delete=models.SET_NULL, related_name='%(class)s_created')
updated_by = models.ForeignKey(User, null=True, editable=False, on_delete=models.SET_NULL, related_name='%(class)s_updated')
class Meta:
verbose_name_plural = 'Settings'
verbose_name = 'Setting'
def __str__(self):
return self.title
as you see I've 3 types for my type field i can save text and json directly in my database as my value is a text filed but i want a custom file handler so i can see if type of the post is image than i need to upload the file and save path to database.
I'll be using it just for API so i'm not practically concerned about Django admin. I hope someone will be able to help me.
I need to work this Django Rest framework so when i send a post request it manage the data.
I am deciding on how to track if a user has seen a post in the timeline or not.
There is Post and Comment model like this.
class Comment(models.Model):
author = models.ForeignKey('UserProfile')
title = models.CharField(max_length=255)
text = models.TextField(null=True, blank=True)
date_created = models.DateTimeField()
post = models.ForeignKey('Post', related_name='comments')
class Post(ContentTypeModel):
title = models.CharField(max_length=255)
group = models.ForeignKey('UserGroup', null=True)
date_updated = models.DateTimeField()
Suggestions about best practices on how to track if post has been seen by particular member of a user group will be nice.
I managed to do as was suggested, i.e. adding m2m relation to track who viewed the post:
class Post(models.Model):
...
date_updated = models.DateTimeField()
viewers = models.ManyToManyField('UserProfile', through='PostViewer')
class PostViewer(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
viewer = models.ForeignKey('UserProfile', on_delete=models.CASCADE, related_name='posts_seen')
last_seen = models.DateTimeField(null=True, blank=True, help_text='Is set when user sees the post in details')
class Meta:
unique_together = ('post', 'viewer')
This way i can compare post.date_updated to viewer.last_seen and get desired filtering on who have seen the update/create of Post.
I have a reviewing system for Subjects. User can review a subject, and users can like that review.
class UserReview(models.Model):
subject = models.ForeignKey(Subject, blank=True, null=True)
user = models.ForeignKey(User)
review = models.TextField(null=True, blank=True)
likes = GenericRelation('Like')
class Like(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
class Meta:
unique_together = (('content_type', 'object_id', 'user'),)
How do I check if a user (eg UserA) exist in the likes of a user review? For now I am doing this way:
if user_review_obj.likes.filter(user=UserA).count() > 0:
// exist...
But I am hoping there is another better way.
You can use exists, however the correct usage is
if user_review_obj.likes.filter(user=UserA).exists():
# . . .
I am making a comments section on my webpage and want users to be able to upvote or downvote a comment.
My models are as such:
class Comment(models.Model):
owner = models.ForeignKey(User)
body = models.TextField(null=True, blank=True, max_length=500)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Vote(models.Model):
comment = models.ForeignKey(Comment)
upvote = models.SmallIntegerField(null=True, blank=True, default=0)
downvote = models.SmallIntegerField(null=True, blank=True, default=0)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
When a user posts a comment, I want it to also create a Vote model that is linked to that comment.
I am new to django and programming but from my understanding, I need to create a save hook or something similar?
You can override the save() method of Comment model, ie:
class Comment(models.Model):
...
def save(self, **kwargs):
super(Comment, self).save(**kwargs)
vote = Vote(comment=self)
vote.save()
I suggest you to read the documentation for a better insight.
Consider this code:
class ModelA(models.Model):
name = models.CharField(max_length=30)
#classmethod
def get_new(cls):
return cls.objects.create().id
class ModelB(models.Model):
thing = models.OneToOneField(ModelA, primary_key=True, default=ModelA.get_new)
num_widgets = IntegerField(default=0)
Of course you can use lambda as well, as long as you return integer id of related object. I don't recommend overwritting save method.