web-dev-qa-db-fra.com

Django - Exemple de balise de modèle personnalisé simple

J'ai tilisateurs, vidéos, sujets, critères et évaluations

  • Un vidéo a un sujet
  • Un sujet ​​a critères
  • Un tilisateur peut créer un vidéo pour un sujet ​​donné
  • Un tilisateur peut noter un vidéo sur chaque critères donné pour le sujet ​​concerné.

Vous pouvez voir mon message d'origine Django - Modèle de notation exemple DetailView Template pour obtenir des détails sur le modèle utilisé

J'ai étendu un modèle DetailView basé sur le modèle video pour mettre la liste des ratings pour le video sélectionné pour une donnée tilisateur comme contexte supplémentaire.

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

Dans le modèle pointé par le DetailView, je voudrais lister les critères des vidéo, et pour chaque critères afficher la valeur de notation actuelle sous la forme tilisateur.

<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 est un plugin jquery que j'utilise pour dessiner de jolis contrôles de notation d'étoiles)

En fait, je reçois mes valeurs de notation ici dans le 2ème for mais je suis sûr qu'il existe une meilleure façon de le faire. En fait, je ne suis toujours pas sûr de mon modèle exactitude.

Enfin, je voudrais remplacer {# The rating value #} par la valeur de notation du taux pour le critique actuel (dans la boucle). Comment puis je faire ça ?

53
Pierre de LESPINAY

Voici ma solution (basée sur un tag personnalisé):

Créez d'abord la structure du fichier. Allez dans le répertoire de l'application où la balise est nécessaire et ajoutez ces fichiers:

templatetags
templatetags/__init__.py
templatetags/video_tags.py

Le fichier templatetags/video_tags.py:

from Django import template

register = template.Library()

@register.simple_tag
def get_rate(crit, rates):
    return rates.get(crit=crit).rate

La partie modèle, avec notre appel de tag:

{% 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>
86
Pierre de LESPINAY

HTML en ligne dans la balise

Si le code HTML est petit, cette méthode est plus pratique que la création d'un fichier séparé.

Cet exemple supprime les liens vers les profils utilisateur. Le fichier templatetags/somemodule.py contient:

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 renvoie déjà une chaîne sûre qui n'est pas échappée XSS. Par exemple. si on avait fait juste:

return '<br>'

il serait échappé. Vous voudrez peut-être aussi jouer avec mark_safe.

Vous pouvez rendre cette balise disponible sur toutes les vues avec:

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

dans settings.py.

Voir également: