I am setting up a blog website and when I add blog posts, the oldest is on the top of the list. How do I reverse this so that the newest posts are on top of the page?
This is my pages/models.py I don't know if ordered_posts = Post.objects.order_by('created_date') is in the right place. I'm not sure where to put it. Any help would be appreciated. Thanks!
class Post(models.Model):
title = models.CharField(max_length=50)
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(auto_now_add=True blank=True, null=True)
author = models.ForeignKey(
'auth.User',
on_delete=models.CASCADE,
)
body = models.TextField()
ordered_posts = Post.objects.order_by('-created_date')
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
You can define ordering in your class Meta.
This is a tuple or list of strings and/or query expressions. Each string is a field name with an optional “-” prefix, which indicates descending order. Fields without a leading “-” will be ordered ascending.
class Post(models.Model):
title = models.CharField(max_length=50)
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(auto_now_add=True blank=True, null=True)
author = models.ForeignKey(
'auth.User',
on_delete=models.CASCADE,
)
body = models.TextField()
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
class Meta:
ordering = ['created_date']
See docs
Related
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...
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
I am creating a rest API for my Django blog project and I have models Post and PostLike models as you below:
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
text = models.TextField()
approved = models.BooleanField(default=False)
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField( default=timezone.now, blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.text[0:100]
class PostLike(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
post = models.ForeignKey(Post, default=None, on_delete=models.CASCADE)
created_date = models.DateTimeField(default=timezone.now)
And I have a Post serialiser like
class PostSerializers(ModelSerializer):
likes_count = serializers.IntegerField(read_only=True)
class Meta:
model= Post
fields = ['id','text','author', 'approved','created_date', 'likes_count' ]
I wish the likes_count to be count for the PostLike objects with the post of the queried post. What is the right way to implement it?
The SerializerMethodField allows you to return a value based on the return value of a class method.
EDIT:
Note that the method accepts the object as a parameter. Therefore to achieve what you want, you can return:
def like_count(self, obj):
return obj.postlike_set.count()
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.
Quick question - I'm not sure what would be the correct way to handle this. Essentially I wish to define a custom tag which handles some logic then returns all posts of model Post which has the is_featured field set to True. I have tried a number of avenues to get this working, but none have worked. My last coherant "guess" was the following:
templatetags/blog_tags.py:
#register.inclusion_tag('blog/post/featured_posts.html')
def show_featured_posts(count=4):
"""Return 4 of the most recent posts (of model: 'Post') that has the variable is_featured set to True."""
if Post.is_featured:
featured_posts = Post.published.order_by('-publish')[:count]
return { 'featured_posts': featured_posts}
models.py (useful bits):
class PublishedManager(models.Manager):
def get_queryset(self):
return super(PublishedManager, self).get_queryset().filter(status='published')
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
POST_TYPES = (
('news', 'News'),
('feature', 'Feature'),
('review', 'Review'),
)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique_for_date='publish')
author = models.ForeignKey(UserProfile, related_name='blog_posts')
body = models.TextField()
lead_in = models.CharField(max_length=500, default='')
#These next items shall contain our development information for game reviews - this is much like the lead_in:
platform = models.CharField(max_length=1000, default='')
publisher = models.CharField(max_length=1000, default='')
developer = models.CharField(max_length=1000, default='')
release = models.DateTimeField(default=timezone.now)
is_featured = models.BooleanField(default=False)
#Out blog layout dictates each featurette has up to three scrolling images associated to it:
image_scroll_1 = models.ImageField(storage=site_media_upload_location, null=True, blank=True)
image_scroll_2 = models.ImageField(storage=site_media_upload_location, null=True, blank=True)
image_scroll_3 = models.ImageField(storage=site_media_upload_location, null=True, blank=True)
type = models.CharField(max_length=10,choices=POST_TYPES,default='review')
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10,choices=STATUS_CHOICES,default='draft')
rating = models.PositiveSmallIntegerField(default=10)
wrap_header = models.CharField(max_length=250, default='')
wrap_up = models.TextField(default='')
disclaimer = models.TextField(default='')
objects = models.Manager()
published = PublishedManager()
tags = TaggableManager()
class Meta:
ordering = ('-publish',)
def __str__(self):
"""Return the state title of the post"""
return self.title
def get_absolute_url(self):
"""Get absolute_url path specific to this post."""
return reverse('blog:post_detail', args = [self.publish.year, self.publish.strftime('%m'), self.publish.strftime('%d'), self.slug])
def get_image(self):
"""Get upload_to path specific to this photo."""
return self.image.url
That is everything I think I need to include - I have the featured_posts.html template all ready to go so I don't think the issue lies with that. It's purely in the blog_tags.py file.
replace the following code in blog_tags.py
if Post.is_featured:
featured_posts = Post.published.order_by('-publish')[:count]
to
featured_posts = Post.published.filter(is_featured=True).order_by('-publish')[:count]