【问题标题】:Django get ContentType in a templateDjango 在模板中获取 ContentType
【发布时间】:2012-09-30 03:40:15
【问题描述】:

我有一个页面,其中包含许多具有不同内容类型的对象。我需要有能力评价这些对象。这是它的一个类:

class Score(models.Model):
    user            = models.ForeignKey(User)

    content_type    = models.ForeignKey(ContentType)
    object_id       = models.PositiveIntegerField()
    for_object      = generic.GenericForeignKey('content_type', 'object_id')

    like            = models.BooleanField(default=True)
    created_at      = models.DateTimeField(auto_now_add=True, blank=True, null=True)

    comment         = models.CharField(max_length=255, blank=True, null=True)

    objects = ChainerManager(ScoreQuerySet)

    def __unicode__(self):
        return u'Score for (%s, #%s) from user %s at %s' %\
            (self.content_type, self.object_id, self.user.get_full_name(), self.created_at)

    class Meta:
        unique_together = (('user', 'content_type', 'object_id'),)

我的模板应该是这样的:

...
{% for random_object in random_object_queryset %}
<a href={% url like_object random_object.<content_type> random_object.id %}>{{ random_object.name }}</a>
<a href={% url dislike_object random_object.<content_type> random_object.id %}>{{ random_object.name }}</a>
{% endfor %}
...

我可以制作模板标签来获取它,或者获取一个类名,使用即这个 sn-p:http://djangosnippets.org/snippets/294/ 我可以重写这个片段来获取对象的 content_type_id,但我担心在 DB 中进行大量 CT 查找。

但是有没有一些嵌入式方法可以在模板中获取对象的 CT?

查看代码:

def rate_object(request, classname, object_id, like=True):
    user = request.user
    Klass = ContentType.objects.get(model=classname).model_class()
    obj = get_object_or_404(Klass, user=user, pk=object_id)

    try:
        score = Score.objects.for_object(user, obj)
        score.like = like
        score.save()
    except Score.DoesNotExist:
        score = Score.objects.like(user, obj) if like else Score.objects.dislike(user, obj)

    return HttpResponse(obj)

【问题讨论】:

标签: python django django-templates django-contenttypes


【解决方案1】:

为了建立 @Colleen 的回答,我最终使用了这样的模板过滤器:

from django import template
from django.contrib.contenttypes.models import ContentType

register = template.Library()

@register.filter
def content_type(obj):
    if not obj:
        return False
    return ContentType.objects.get_for_model(obj)

并在这样的模板中使用它:

{% load helpers %}
{% with instance|content_type as ctype %}
    <input type="hidden" name="content_type" value="{{ ctype.pk }}">
{% endwith %}

【讨论】:

  • 进一步讨论和分叉,see this snippet
  • 这个{% with instance|content_type as ctype %} 语法,有文档记录并支持吗? {% with a=b|c %} 也可以吗? {% with a=b|c d=e|f %} 呢?我在文档中找不到。
  • with 是一个内置的模板标签(与上面的自定义过滤器相反),here it is in Django's official docs
  • 我知道。我不知道你是否可以在with 中使用过滤器。显然你已经尝试过了并且它有效,但我想知道它是否被记录和支持的行为。
  • 好点,似乎没有在任何地方明确说明。尽管至少在几个地方暗示了这一点。例如in the introduction to tags/filters 查看关于if 变量能够使用过滤器的部分,或者在dictsort filter examples 中。
【解决方案2】:

我更喜欢使用assignment tags(Django 1.4 中的新功能):

@register.assignment_tag
def content_type(obj):
    if not obj:
        return False
    return ContentType.objects.get_for_model(obj)

并用作

{% content_type object as object_ct %}

【讨论】:

    【解决方案3】:

    我还遇到过需要模板中的内容类型的情况,而我发现获得它的唯一方法是通过自定义模板标签。

    但是,在您的情况下,由于您将 content_type 显式存储为外键,因此我不会担心。在最坏的情况下,当您在视图中获取乐谱对象时,您可以使用prefetch_related()。我不知道 Django 是否足够聪明,如果你要求一个外键就停在现场。id 是唯一的。

    【讨论】:

      猜你喜欢
      • 2014-12-15
      • 1970-01-01
      • 1970-01-01
      • 2011-07-04
      • 2012-01-04
      • 1970-01-01
      • 2013-03-02
      • 2015-02-20
      • 2015-04-21
      相关资源
      最近更新 更多