Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - Simple custom template tag example

I have users, videos, topics, criterias and ratings

  • A video has a topic
  • A topic has criterias
  • A user can create a video for a given topic
  • A user can rate a video on each criterias given for the concerned topic.

You can see my original post Django - Rating Model Example DetailView Template to get details on the model used

I have extended a DetailView template based on the video model to put the list of ratings for the selected video for a given user as extra context.

class VideoFileDetailView(DetailView):   model = VideoFile    def get_context_data(self, **kwargs):     context = super(VideoFileDetailView, self).get_context_data(**kwargs)     context['rates'] = VideoRate.objects.filter(video=self.object, user=self.request.user)     return context 

In the template pointed by the DetailView, I'd like to list the criterias of the video, and for each criteria display the current rating value form the user.

<div id="rating">   <ul> {% for crit in videofile.topic.crits.all %}     <li>   {% for rate in rates %}     {% if rate.crit.id == crit.id %}       {{ rate.rate }}     {% endif %}   {% endfor %}       <div class="rateit"         data-rateit-value="{# The rating value #}"         data-rateit-ispreset="true"         crit-id="{{ crit.id }}"></div>       {{ crit }}     </li> {% endfor %}   </ul> </div> 

(rateit is a jquery plugin that I use to draw pretty stars rating controls)

Actually I get my rating values here within the 2nd for but I'm sure there is a better way to do that. In fact, I'm still not sure about my model correctness.

Finally I'd like to replace {# The rating value #} by the rating value from rate for the current crit (in the loop). How can I do that ?

like image 257
Pierre de LESPINAY Avatar asked Jun 23 '11 08:06

Pierre de LESPINAY


People also ask

What is simple tag Django?

Simple tags This function, which is a method of django. template. Library , takes a function that accepts any number of arguments, wraps it in a render function and the other necessary bits mentioned above and registers it with the template system.

How do I register a filter in Django?

To be a valid tag library, the module must contain a module-level variable named register that is a template. Library instance, in which all the tags and filters are registered. Show activity on this post. from django.


2 Answers

Here is my solution (based on a custom tag):

Firstly create the file structure. Go into the app directory where the tag is needed, and add these files:

templatetags templatetags/__init__.py templatetags/video_tags.py 

The templatetags/video_tags.py file:

from django import template  register = template.Library()  @register.simple_tag def get_rate(crit, rates):     return rates.get(crit=crit).rate 

The template part, with our tag call:

{% load video_tags %}  <div id="rating">   <ul> {% for crit in videofile.topic.crits.all %}     <li>       <div class="rateit"         data-rateit-value="{% get_rate crit rates %}"         data-rateit-ispreset="true"         crit-id="{{ crit.id }}"></div>       {{ crit }}     </li> {% endfor %}   </ul> </div> 
like image 98
Pierre de LESPINAY Avatar answered Sep 28 '22 09:09

Pierre de LESPINAY


Inline HTML in tag

If the HTML is small, this method is more convenient than creating a separate file.

This example factors out links to user profiles. The file templatetags/somemodule.py contains:

from django import template from django.template import Template  register = template.Library()  @register.simple_tag(takes_context=True) def user_link(context):     return Template('<a href="{% url \'user_detail\' ' +             'user.id %}">{{ user.username }}</a>').render(context) 

Template#render already returns a safe string which is not XSS escaped. E.g. if we had done just:

return '<br>' 

it would be escaped. You might also want to play with mark_safe.

You can make that tag available on all views with:

TEMPLATES = [     {         'OPTIONS': {             'builtins': [                 'myprojectname.templatetags.somemodule', 

in settings.py.

See also:

  • https://docs.djangoproject.com/en/1.9/howto/custom-template-tags/
  • Rendering a template variable as HTML