问题
I feel like I'm really close, but not quite there yet. Please bear with me as I am very much so in the beginner stages of learning django.
I have a feature where users can comment on each blog post. I want to display the total number of comments each user has next to his name. If that user has left 4 comments on 4 different posts, I want it to show "4 total comments" next to his name on each one of his individual comments throughout my website.
I have made a model method that I put in my view, which automatically updates the total comments for each user. The only problem is that if the user has left two comments, only his latest comment will show "2 total comments". His previous one shows only "1".
My question is, how do I make the previous entry update when the user has left a new comment?
models.py
class Comment(models.Model):
...
post = models.ForeignKey(Post, related_name="comments")
user = models.ForeignKey(User, related_name="usernamee")
email = models.EmailField(null=True, blank=True)
picture = models.TextField(max_length=1000)
...
review_count = models.IntegerField(default=0)
class UserProfile(models.Model):
...
def user_rating_count(self): #This is what adds "1" to the user's total post count
user_ratings =
Comment.objects.all().filter(user_id=self.user.id).count()
user_ratings += 1
return user_ratings
views.py
@login_required
def add_comment(request, slug):
post = get_object_or_404(Post, slug=slug)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.user = request.user
comment.email = request.user.email
comment.picture = request.user.profile.profile_image_url()
comment.review_count = request.user.profile.user_rating_count() #This is where I'd like it to update, but it doesn't seem to work this way
comment.save()
return redirect('blog:post_detail', slug=post.slug)
else:
form = CommentForm()
template = "blog/post/add_comment.html"
context = {
'form': form,
}
return render(request, template, context)
template
{% for comment in post.comments.all %}
<p>{{ comment.user.first_name }} <b>{{ comment.user.last_name }}</b> {{ comment.review_count }}</p>
{% endfor %}
User comments once = FirstName LastName 1. User comments twice, his second comment = FirstName LastName 2, but the first comment remains unchanged.
Any ideas on how to properly do this? Any help is greatly appreciated!
回答1:
First i don't think you need the review_count
to be a Database field. Except you plan to use it to sort (or do something that requires it to be in the Database).
From your question "django forms - how to update user data from previous comment when user posts a new comment" I believe you have an idea on why it's not working.
It's because it's a previous comment and Updating the data of the latest comment won't automatically update the previous comments (It would be disastrous if that happened by default :-) )
Anyway once you remove thereview_count
and make user_rating_count
a property of the UserProfile
model your problem disappears.
class UserProfile(models.Model):
@property
def user_rating_count(self):
"""This is what adds "1" to the user's total post count"""
return self.usernamee.count() # Remember the `related_name` you set earlier?
Then you can use it in your templates like this
{% for comment in post.comments.all %}
<p>{{ comment.user.first_name }} <b>{{ comment.user.last_name }}</b> {{ request.user.profile.user_rating_count }}</p>
{% endfor %}
If you're bothered about the value being recalculated on each page load (You should be). Django provides a nifty decorator to cache the property in memory and reduce the load on your database (When you call the method/access the property repeatedly)
from django.utils.functional import cached_property
class UserProfile(models.Model):
@cached_property
def user_rating_count(self):
"""This is what adds "1" to the user's total post count"""
return self.usernamee.count() # Remember the `related_name` you set earlier?
If it doesn't need to be a Database field, it doesn't need to be. You can easily make it a computed property and Cache it (If you feel it's expensive to recalculate everytime and you don't really care about the "freshness" of the data).
By the way if you needed to update the Old comments (The way you wanted to initially), You would've done a batch update like this
I'm being overly verbose here:
comments = Comment.objects.filter(user_id=self.user.id)
count = comments.count()
comments.update(review_count=count)
That will update all the comments that match the filter params. But like i said i don't think this is the best approach for what you want to do.
Read up
https://docs.djangoproject.com/en/1.11/ref/utils/#django.utils.functional.cached_property
and
https://docs.djangoproject.com/en/1.11/ref/models/querysets/#update
来源:https://stackoverflow.com/questions/46065177/django-forms-how-to-update-user-data-from-previous-comment-when-user-posts-a-n