Serializer for Recursive Comment in Django - python

models.py
class Comments(models.Model):
content = models.CharField(max_length=500)
sub_comment_id = models.ForeignKey('self', related_name='sub_comments', null=True, blank=True,
on_delete=models.CASCADE)
author_id = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='user_comments', on_delete=models.CASCADE)
article_id = models.ForeignKey(Article, related_name='article_comments', on_delete=models.CASCADE)
like = models.IntegerField(default=0)
dislike = models.IntegerField(default=0)
is_sub = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = models.Manager()
def __str__(self):
return self.content
what can i do for showing all recursive comments in Comment Serializer?
i use django rest framework-recursive but does not work

I have never try something like this, but i don't see why it wouldn't work
CommentSerializer(serializers.Serializer):
content = serializers.CharField()
...
sub_comments = serializers.SerializerMethodField()
def get_sub_comments(self, comment):
return self.__class__(comment.sub_comments.all(), many=True).data

Related

Subquery in Django ORM

I have following models. My goal is to extract 2 recent Comments per Post. Is that possible?
class Post(models.Model):
author = models.ForeignKey(Author, related_name="posts", on_delete=models.CASCADE)
title = models.CharField(max_length=256)
text = models.TextField(blank=True, default="")
created_at = models.DateTimeField(default=datetime.now, blank=True)
#property
def comments_number(self):
return self.comments.count()
def __str__(self, *args, **kwargs):
return f"{self.title}"
class Comment(models.Model):
post = models.ForeignKey(Post, related_name="comments", on_delete=models.CASCADE)
author = models.ForeignKey(Author, related_name="comment", on_delete=models.CASCADE)
text = models.TextField()
created_at = models.DateTimeField(default=datetime.now, blank=True)
The closest try I've got is this one:
newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')
recent_comments = Post.objects.annotate(newest_comments=Subquery(newest.values('text')[:2]))
And than when I call recent_comments.values_list() I can see the newest one comment per Post obj (only one) but this is not what I want exactly. I have spend a lot of time on it guys and have no clue...

Field 'id' expected a number but got '' in django

blog_id is not get. help me to solve this ---
models.py
class Blog(models.Model):
title = models.CharField(max_length=500)
body = models.TextField()
last_updated_on = models.DateTimeField(auto_now=True)
created_on = models.DateTimeField(auto_now_add=True)
author_instance = models.ForeignKey(AuthorInstance, on_delete=models.PROTECT)
status_draft = models.BooleanField(default=False, blank=True, null=True)
status_publish = models.BooleanField(default=False, blank=True, null=True)
likes = models.ManyToManyField(UserInstance, related_name='like', default=None, blank=True)
like_count = models.BigIntegerField(default='0')
def total_likes(self):
return self.likes.count()
views.py
def like_post(request):
post = get_object_or_404(Blog, id=request.POST.get('blog_id'))
how to solve????
views should be like
def like_post(request,id):
post = get_object_or_404(Blog, id=request.POST.get('blog_id'))

For blog post i used tags by many_to_many filed. Now i try to use Django_Taggit for tag field, but i face some error while migrate

Old MODELS.py
when use tags by many_to_many fields
class Tag(models.Model):
tag_name = models.CharField(max_length=64, unique=True)
tag_slug = models.SlugField(max_length=64, unique=True)
created_on = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
def __str__(self):
return self.tag_name
def get_absolute_url(self):
return reverse("news:tag-detail", kwargs={"slug": str(self.tag_slug)})
class News(models.Model):
title = models.CharField(max_length=192, unique=True)
slug = models.SlugField(max_length=192, unique=True)
cover_photo = models.ImageField(upload_to='news', blank=True, null=True)
summary = models.CharField(max_length=280)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='post_author')
updated_on = models.DateTimeField(auto_now=True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=1)
# tags = models.ManyToManyField(Tag, blank=True, related_name='post_tag')
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("news:post", kwargs={"slug": str(self.slug)})
current models.py
After install Django_Taggit
i remove tags model and rewrite tags line
class News(models.Model):
title = models.CharField(max_length=192, unique=True)
slug = models.SlugField(max_length=192, unique=True)
cover_photo = models.ImageField(upload_to='news', blank=True, null=True)
summary = models.CharField(max_length=280)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='post_author')
updated_on = models.DateTimeField(auto_now=True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=1)
tags = TaggableManager()
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("news:post", kwargs={"slug": str(self.slug)})
Also i remove tags from view.py and urls path and update html
but when i try to 'python manage.py migrate' i face this error
ValueError: Cannot alter field news.News.tags into news.News.tags - they are not compatible types (you cannot alter to or from M2M fields, or add or remove through
= on M2M fields)
First remove the tags field and (makemigrations->migrate), then as you don't have tags as a field anymore add the new taggit field and again (makemigrations->migrate).
If you want to save the current tags, I can think of couple of options.
Create new field for example tags_taggit, and then run a script to translate the current tags into the new tags_taggit field. Then proceed with the steps I told you first
Create fixtures, then run a script to iterate over the fixtures and save the tags into the new field.

Django: How to check object category when using Model Inheritance?

Here is my models.py the idea of app is to have different objects (restaurants, services, etc) with different features (you can check each Model). But when I want to get all objecs Object.objects.all() I don't know which is the category for each of them.
models.py:
from django.db import models
from users.models import ProfileUser
from django.utils import timezone
# Create your models here.
class City(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return f"{self.name}"
class Object(models.Model):
author = models.ForeignKey(ProfileUser, on_delete=models.CASCADE)
title = models.CharField(max_length=300)
city = models.ForeignKey(City, on_delete=models.CASCADE)
address = models.CharField(max_length=300)
phone = models.CharField(max_length=20, default='')
email = models.CharField(max_length=100, default='')
site = models.CharField(max_length=100, default='')
facebook = models.CharField(max_length=100, default='')
instagram = models.CharField(max_length=100, default='')
content = models.TextField()
rating = models.IntegerField(default=10)
created_date = models.DateTimeField(default=timezone.now)
approved_object = models.BooleanField(default=False)
admin_seen = models.BooleanField(default=False)
def __str__(self):
return f"{self.title}"
class Restaurant(Object):
seats = models.IntegerField()
bulgarian_kitchen = models.BooleanField(default=False)
italian_kitchen = models.BooleanField(default=False)
french_kitchen = models.BooleanField(default=False)
is_garden = models.BooleanField(default=False)
is_playground = models.BooleanField(default=False)
class SportFitness(Object):
is_fitness_trainer = models.BooleanField(default=False)
class CarService(Object):
is_parts_clients = models.BooleanField(default=False)
class BeautySalon(Object):
is_hair_salon = models.BooleanField(default=False)
is_laser_epilation = models.BooleanField(default=False)
class FastFood(Object):
is_pizza = models.BooleanField(default=False)
is_duner = models.BooleanField(default=False)
is_seats = models.BooleanField(default=False)
class CarWash(Object):
is_external_cleaning = models.BooleanField(default=False)
is_internal_cleaning = models.BooleanField(default=False)
is_engine_cleaning = models.BooleanField(default=False)
class Fun(Object):
is_working_weekend = models.BooleanField(default=False)
is_kids_suitable = models.BooleanField(default=False)
class Other(Object):
is_working_weekend = models.BooleanField(default=False)
class Comment(models.Model):
object = models.ForeignKey(Object, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(ProfileUser, on_delete=models.CASCADE)
content = models.TextField()
rating = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return f"{self.content}"
You can not get the categories using the Object model.
Object class is created for a particular purpose:
it eliminates the need to declare certain characteristics of a class
Here you can use select_related or prefect_related to get the desired output.
OR
To fulfill your requirements you can use django-polymorphic for more detail you can refer the documentation.
This is how I did it:
Based on #wfehr commend and #Lokesh Pathak answer I implemented django-polymorphic, also added two additional rows(columns) to each model (only for Restaurants for now), so when foreach over all object I can print exact name of category, additional fields are
category_en_name = models.CharField(max_length=100, default='restaurants')
category_bg_name = models.CharField(max_length=100, default='Ресторант')
full models.py:
from django.db import models
from users.models import ProfileUser
from django.utils import timezone
from polymorphic.models import PolymorphicModel
# Create your models here.
class City(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return f"{self.name}"
class Object(PolymorphicModel):
author = models.ForeignKey(ProfileUser, on_delete=models.CASCADE)
title = models.CharField(max_length=300)
city = models.ForeignKey(City, on_delete=models.CASCADE)
address = models.CharField(max_length=300)
phone = models.CharField(max_length=20, default='')
email = models.CharField(max_length=100, default='')
site = models.CharField(max_length=100, default='')
facebook = models.CharField(max_length=100, default='')
instagram = models.CharField(max_length=100, default='')
content = models.TextField()
rating = models.IntegerField(default=10)
created_date = models.DateTimeField(default=timezone.now)
approved_object = models.BooleanField(default=False)
admin_seen = models.BooleanField(default=False)
def __str__(self):
return f"{self.title}"
class Restaurant(Object):
seats = models.IntegerField()
bulgarian_kitchen = models.BooleanField(default=False)
italian_kitchen = models.BooleanField(default=False)
french_kitchen = models.BooleanField(default=False)
category_en_name = models.CharField(max_length=100, default='restaurants')
category_bg_name = models.CharField(max_length=100, default='Ресторант')
is_garden = models.BooleanField(default=False)
is_playground = models.BooleanField(default=False)
class SportFitness(Object):
is_fitness_trainer = models.BooleanField(default=False)
So I can take only Restaurants in views.py:
objects = Object.objects.instance_of(Restaurant)
And in template, I can show category name of each restaurant:
{% for object in objects %}
{{ object.category_bg_name }}
{% endfor %}

How to do subcomments

from django.db import models
class Post(models.Model):
post_title = models.CharField(max_length=120, default=None)
post_text = models.TextField()
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.post_title
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
sub_comment = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True)
author = models.CharField(max_length=50)
comment_text = models.CharField(max_length=250)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.author
Hello, i've got a question. How to preform displaying comment as a thread if i have models like this?
A comment can have multiple subcomments, so this model won't work. Replace sub_comment with parent = models.ForeignKey(..., related_name='subcomments'). Then you will be able to say comment.subcomments which will give you a related object manager, so comment.subcomments.all() will be a query of all subcomments that you can iterate over.

Categories