Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django get ContentType in a template

I have a page with a lot of objects with different content types. I need to have an ability to rate this objects. Here is a class for it:

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

And my template should look like:

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

I can make template tag to get it, or get a classname, using i.e. this snippet: http://djangosnippets.org/snippets/294/ I can rewrite this snuppet to get the content_type_id for object, but i'm afraid a little about big amount of CT lookups in DB.

But is there some embedded method to get object's CT in a template?

The view code:

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)
like image 523
night-crawler Avatar asked Oct 09 '12 18:10

night-crawler


People also ask

How do I get content type in Django?

Installing the contenttypes framework The contenttypes framework is included in the default INSTALLED_APPS list created by django-admin startproject , but if you've removed it or if you manually set up your INSTALLED_APPS list, you can enable it by adding 'django. contrib. contenttypes' to your INSTALLED_APPS setting.

What does {% %} mean in Django?

{% %} and {{ }} are part of Django templating language. They are used to pass the variables from views to template. {% %} is basically used when you have an expression and are called tags while {{ }} is used to simply access the variable.

How do I get templates in Django?

To configure the Django template system, go to the settings.py file and update the DIRS to the path of the templates folder. Generally, the templates folder is created and kept in the sample directory where manage.py lives. This templates folder contains all the templates you will create in different Django Apps.

What is load in Django template?

The django. template. loader module defines two functions to load templates. This function loads the template with the given name and returns a Template object.


2 Answers

To build on @Colleen 's answer, I ended up using a template filter like so:

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)

And used it in a template like so:

{% load helpers %}
{% with instance|content_type as ctype %}
    <input type="hidden" name="content_type" value="{{ ctype.pk }}">
{% endwith %}
like image 156
tutuDajuju Avatar answered Oct 05 '22 08:10

tutuDajuju


I prefer doing this with assignment tags (new in Django 1.4):

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

and used as

{% content_type object as object_ct %}
like image 31
susundberg Avatar answered Oct 05 '22 07:10

susundberg