0

My problem is that I need to know if a user has rated a certain model instance, BlogSite. On the page, there are multiple BlogSite instances, which have a 5-star rating system. When the current user has rated a certain instance, it should be set to read-only.

I'm running into a roadblock because if I use a model function, I need to pass 2 variables - current_user and BlogSite. I haven't been able to find how to access request.user in models.py and it's looking like I shouldn't be doing that?

The other path I went down was to create a custom filter - but I found out that I can only pass in one parameter. I would rather not do this method because I feel it would be better to keep the logic in views.py

Does anyone have ideas of how I can solve this problem?

#models.py
class BlogSite(models.Model):
    #fields

#get the average rating for a blogsite
def rating_avg(self):
    rating_dict = BlogSiteReview.objects.filter(blog_site=self).aggregate(Avg('review_rating'))
    rating_avg = rating_dict.get('review_rating__avg')
    if rating_avg:
        return rating_avg
    else:
        #no ratings
        return 0

def rated(self, current_user):
    #If there is a row for the blogsitereview with this blogsite for the logged in user, return True, else False
    #can I access the current user? This does not work, seems like I can't get request here.
    current_user = request.user
    review = BlogSiteReview.objects.filter(blog_site=self, user=current_user)

    if review:
        return True
    else:
        return False

class BlogSiteReview(models.Model):
    blog_site = models.ForeignKey(BlogSite)
    user = models.ForeignKey(User)
    #other fields

Here is the relevant part of the view:

#views.py
def search(request, type, regionValue):
    #....
    #ideally, the solution would be to have a field or function in the BlogSite model
    blog_sites = BlogSite.objects.filter(country=region.id, active=True)
    #....

In the template I would have an if statement to add a class if rated returns True

<tr>
    <td><a href="http://{{ blogsite.url }}" id="{{ blogsite.id }}">{{ blogsite.site_name }}</a></td>
    <td><div id="rating{{ blogsite.id }}" class="rating {% if blogsite.user_rated %}jDisabled{% endif %}" data-average="{{ blogsite.rating_avg }}" data-id="{{ blogsite.id }}"></div></td>
    <td>{{ blogsite.create_date }}</td>
</tr>

I'm looking for 2 things here - does using a model method to get if a user has rated seem like the correct approach? The problem I have with this so far is that I can't find how to access the current user to use in models.py. Another idea I thought of is to pass in the request.current_user from the view somehow, but the user is not associated with BlogSite, so I can't filter on that.

4

2 回答 2

0

我最终采取了一种稍微不同的方法,这是我在试图入睡时想到的,但我无法摆脱 Django :) 在视图中,我创建了一个特定用户留下评论的 blog_sites 列表

#views.py
rated = BlogSiteReview.objects.filter(user=request.user).values_list('blog_site', flat=True)
return render(request, page, {..., 'blogsites':blog_sites, 'rated':rated})

如果 blog_site FK id 在 blog_sites for 循环中,我在模板中添加了一个类:

#template
{% for blogsite in blogsites %}
<tr>
  <td><a href="http://{{ blogsite.url }}" id="{{ blogsite.id }}">{{ blogsite.site_name }}</a></td>
  <td><div id="rating{{ blogsite.id }}" class="rating {% if blogsite.id in rated %}jDisabled{% endif %}" data-average="{{ blogsite.rating_avg }}" data-id="{{ blogsite.id }}"></div></td>
  <td>{{ blogsite.create_date }}</td>
  <td>{{ rated }}</td>
</tr>
{% empty %}
  <p>There are no registered blogsites for this country.</p>
{% endfor %}

我现在终于可以睡觉了!

于 2013-10-29T06:02:52.397 回答
0

您可以blog_site.rated(request.user)通过模板参数传递结果。如果您为模板提供多个 BlogSite 实例(blog_sites在您的视图示例中)并在模板中迭代它们,您可以将实例和rated结果分组到视图中的元组或字典中,如下所示:

({"site": block_site, "rated": block_site.rated(request.user)} for block_site in block_sites)

result.site并在模板中分别使用和访问这些result.rated,假设这result是模板中的迭代变量(因为您命名为 view search)(替换blogsite模板片段)。

因此,我个人会保留rated您发布的方法和current_user参数。

编辑:这是一个混合了您的代码(问题和答案)和我的建议的示例:

#views.py
def search(request, type, regionValue):
    #....
    blog_sites = BlogSite.objects.filter(country=region.id, active=True)
    search_results = ({"site": block_site, "rated": block_site.rated(request.user)} for block_site in block_sites)
    return render(request, page, {..., 'search_results': search_results})

在模板中:

{% for result in search_results %}
  {% with blogsite=result.site rated=result.rated %}
    <tr>
      <td><a href="http://{{ blogsite.url }}" id="{{ blogsite.id }}">{{ result.site.site_name }}</a></td>
      <td><div id="rating{{ blogsite.id }}" class="rating {% if rated %}jDisabled{% endif %}" data-average="{{ blogsite.rating_avg }}" data-id="{{ blogsite.id }}"></div></td>
      <td>{{ blogsite.create_date }}</td>
      <td>{{ rated }}</td>
    </tr>
  {% endwith %}
{% empty %}
  <p>There are no registered blogsites for this country.</p>
{% endfor %}
于 2013-10-27T18:23:24.343 回答