如何在模板中提取与用户关联的属性?

时间:2012-09-25 22:42:42

标签: django templates view model

我正在尝试将与用户相关联的图像正确显示。我需要帮助确定模板中应包含的内容。具体来说,我认为模板“{{review.user__image}}中的代码不正确。根据特定评论和编写该评论的用户,如何提取与用户关联的图像?

views.py

def view_reviews(request, product_name):
    product = get_object_or_404(Productbackup, url_friendly=product_name)
    product_id = product.id
    reviews = Reviewbackup.objects.filter(product_id=product_id).order_by("-created_on")
    return render_to_response('reserve/templates/view_reviews.html', {'reviews':reviews},
        context_instance=RequestContext(request))

models.py

class Reviewbackup(models.Model):
    review = models.CharField('Review', max_length = 2000)
    user = models.CharField('Username', max_length =  200)
    rating = models.IntegerField(max_length=2, choices=RATING_OPTIONS)
    product = models.ForeignKey(Productbackup)
    def __unicode__(self):
        return self.review

class UserProfile(models.Model):
    user = models.ForeignKey(User, primary_key=True)
    image = models.ImageField(blank=True, null=True, max_length=255, upload_to="images/")

模板

{% for review in reviews %} 
    <br><a href = "/user/{{review.user}}/">{{review.user}}</a><br>
    <img class = "thumbnail" src = "http://test.webfactional.com/static/{{review.user__image}}"><br>
    {{review}}
{% endfor %}

3 个答案:

答案 0 :(得分:1)

对不起,答案很长。根据你的代码来判断,我认为你是Django的新手,所以这个答案希望能够提供信息以及过程回答问题。

用户

在您的评论模型中,user应为ForeignKey而不是CharField。我知道存储用户名似乎更自然,特别是如果您自己查看数据库表,但这种方法容易出错,除非您有充分的理由,这是一件坏事。

想象一下,您的用户名为foousername。然后该用户创建了几个评论。因此,此时您将在user字段为foousername的位置进行一些评论。现在,如果用户想要将他/她的用户名更改为someotherfoousername,为了不中断评论与用户之间的链接,您必须更改user字段以查看用户的所有评论创建使用新用户名。这是一个额外的步骤,您可能会忘记这样做,因此它容易出错。使用ForeignKey可以立即解决此问题。即使用户更改了他/她的用户名,用户的主要ID也不会改变,因此如果评论链接到主键(这是外键),则不必更新评论。如此少的工作,更可靠的方法。

这样做(下面将解释related_name):

user = models.ForeignKey(User, related_name='reviews')

related_name

当您使用related_name时,Django会让您的生活更轻松。

考虑你的观点。首先,您查询产品。然后,一旦你得到它,你拿它的id,然后你构建一个查询,它将返回该产品的所有评论。使用Django,您可以使用更少的代码完成所有这些。

product = get_object_or_404(Productbackup, url_friendly=product_name)
reviews = product.reviewbackup_set.all()

但由于整个_set业务,这有点令人困惑。这是related name的用武之地。如果您按如下方式定义product字段:

product = models.ForeignKey(Productbackup, related_name='reviews')

然后你可以用更易读的方式做同样的事情(Python应该是可读的......):

reviews = product.reviews.all()

用户个人资料

外键允许实现一对多关系。因此,对于产品和评论来说,它非常有意义。一个产品可以有很多评论。但通常不是用户配置文件的情况。通常,用户只有一个用户配置文件。因此,在您的用户个人资料中,您不应该向用户ForeignKey,而应该使用OneToOneField,如下所示:

user = models.OneToOneField(User, primary_key=True, related_name='profile')

这使您可以轻松访问用户的个人资料:

user_profile = User.objects.get(...).profile

用户图像

对于每次审核,现在根据我的第一个解释,用户为ForeignKey,您可以非常轻松地访问用户的图片:

review = Reviewbackup.objects.all()[0]
user_image = review.user.profile.image   # <- see, very easy

图片网址

每当您在Django中使用FileField时,它会将文件上传到您的媒体文件夹下的upload_to位置 - 在项目设置中MEDIA_ROOT中定义的文件夹。因此,在您的情况下,Django会将图像存储在媒体文件夹中的images文件夹中。此外,如果您配置MEDIA_URL,则允许访问文件的URL,如:

user_profile.image.url

硬编码网址

在模板中包含直接网址是一个非常糟糕的主意。这是url模式名称的用途。因此,我们的想法是为url模式分配一个名称,以便稍后通过引用名称获取url。这使得代码更易于维护。例如,以下是用户的url模式:

url(r'^user/(?P<username>\w+)/$', 'user_view', name='user_view')

这允许您在模板中使用它:

{% load url from future %}
link: <a href="{% url 'user_view' username=user.username %}">{{ user.username }}</a>

将所有内容放在一起

# views.py
def view_reviews(request, product_name):
    product = get_object_or_404(Productbackup, url_friendly=product_name)
    reviews = product.reviews.all().order_by("-created_on")
    return render_to_response('reserve/templates/view_reviews.html',
                              {'reviews':reviews},
                              context_instance=RequestContext(request))

# models.py
class Reviewbackup(models.Model):
    review = models.CharField('Review', max_length = 2000)
    user = models.ForeignKey(User, related_name='reviews')
    rating = models.IntegerField(max_length=2, choices=RATING_OPTIONS)
    product = models.ForeignKey(Productbackup, related_name='reviews')
    def __unicode__(self):
        return self.review

class UserProfile(models.Model):
    user = models.OneToOneField(User, primary_key=True, related_name='profile')
    image = models.ImageField(blank=True, null=True, max_length=255, upload_to="images/")

{# template #}
{% load url from future %}
{% for review in reviews %} 
    <br><a href="{% url user_view username=review.user.username %}">
        {{ review.user.username }}</a><br>
    <img class="thumbnail" src="{{ review.user.profile.image.url }}"><br>
    {{ review.review }}
{% endfor %}

答案 1 :(得分:0)

您似乎不知道如何获取用户个人资料。以下是有关如何定义UserProfile以便它可以工作的一些信息:

https://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users

简而言之,您将UserProfile.user设为OneToOneField,然后您就可以使用user.get_profile()了。否则,您可以保留模型定义,并使用UserProfile.objects.get(user=user)user.userprofile_set.all()[0](eww)之类的内容。

拥有UserProfile对象后,@ Ignacio非常正确。图像就在那里。我怀疑{{ review.user.userprofile.image }}的问题在于,由于用户是ForeignKey而不是OneToOneField,因此用户会使用userprofile_set属性。

答案 2 :(得分:-1)

image不在User上,而在UserProfile上。

{{ review.user.userprofile.image }}