2012-10-09 28 views
8

Mam stronę z dużą ilością obiektów o różnych typach zawartości. Potrzebuję umiejętności oceniania tych obiektów. Tutaj jest klasą dla niego:Django pobierz ContentType do szablonu

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'),) 

A mój szablon powinien wyglądać następująco:

... 
{% 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 %} 
... 

mogę zrobić szablon, aby go lub dostać classname korzystając czyli tym fragmencie: http://djangosnippets.org/snippets/294/ I mogę przepisać ten snuppet, aby uzyskać content_type_id dla obiektu, ale obawiam się trochę o dużej liczbie wyszukiwań CT w DB.

Ale czy jest jakiś wbudowany sposób na pobranie CT obiektu w szablonie?

Kod widok:

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) 
+0

Czy możesz umieścić swój kod widzenia? –

+1

Dla informacji: Nie powinieneś dodawać tyle spacji po zmiennych. To nie jest PEP8 (http://www.python.org/dev/peps/pep-0008/#whitespace-in-expressions-and-statements) – Thomas

Odpowiedz

10

Aby zbudować na odpowiedź @Colleen „s, skończyło się stosując filtr szablon tak:

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) 

i wykorzystał je w szablonie tak:

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

do dalszej dyskusji i rozwidlania, [zobacz ten fragment] (https: // djangosnippets.org/snippets/3015/) – tutuDajuju

+0

Ta składnia '' {% with instance | content_type as ctype%} '' jest udokumentowana i obsługiwana? Czy '' {% with a = b | c%} '' również działa? A co z '' {% z a = b | c d = e | f%} ''? Nie mogę znaleźć tego w dokumentacji. –

+0

'with' jest wbudowanym tagiem szablonu (w przeciwieństwie do niestandardowego filtra powyżej), [tutaj jest w oficjalnych dokumentach Django] (https://docs.djangoproject.com/en/1.6/ref/templates/builtins/# with) – tutuDajuju

2

miałem też sytuację, w której co potrzebne typ treści w szablonie, a jedynym sposobem znalazłem mogę dostać to przez znacznika niestandardowego szablonu.

W twojej sytuacji, ponieważ przechowujesz content_type jawnie jako klucz obcy, nie martwiłbym się o to. Najgorszy przypadek można użyć prefetch_related() po uzyskaniu obiektów punktów w widoku. Nie wiem, czy Django jest wystarczająco inteligentny, aby zatrzymać się na polu, jeśli zapytasz o foreignkey.id, to jedyna rzecz.

1

Wolę ten sposób z assignment tags (nowość Django 1.4):

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

i stosowane jako

{% content_type object as object_ct %} 
Powiązane problemy