django forms - how to update user data from previous comment when user posts a new comment

亡梦爱人 提交于 2019-12-24 18:23:26

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!