2011-10-12 6 views
1

Quelle est la meilleure approche dans une situation suivante?Modèles génériques ou modèles dans les modèles - Django

Disons que nous avons quelques modèles, par ex. Article, Photo, BlogEntry et ainsi de suite. Chaque modèle peut être affiché sur la page comme un pouce ou un soi-disant widget.

Exemple:

  • attribut thumbview d'un modèle contient le pouce de l'élément avec le titre dans le bloc html
  • normalview - contient plus le pouce, le titre et la description dans un bloc
  • bigview - pouce, titre, description et dites ... nombre de commentaires ajoutés

Tous ces éléments devraient être polymorphes dans un modèle e pour que je puisse faire quelque chose comme itérer ma liste d'éléments abstraits (différents types) et simplement:

{{ item.thumbview }} 

ou

{{ item.bigview }} 

pour afficher chaque pouce de l'élément.

Il peut être réalisé paresseux-évalué dans un modèle mais je ne me sens pas hardcode'ing html dans un modèle est la bonne manière.

Comment puis-je modéliser un tel comportement? Quel est le meilleur moyen?

J'apprécierais toute suggestion. Merci.

Répondre

1

Vous pouvez utiliser une balise de modèle personnalisé et une méthode standard dans un modèle pour donner un contexte au widget dans le cas où vous ne pouvez pas obtenir des propriétés dans un modèle:

myapp/models.py:

class Photo(models.Model): 
    ... 
    def widget_context(self, context): # receives the context of the template. 
     user = context['request'].user # context should be RequestContext to contain request object (or you may use thread locals). 
     return {'tags': self.tag_set.filter(...), 'can_edit': self.owner == user or user.is_admin} 
fichier

tags template, widgets_app/templatetags/objwidgets.py:

@register.simple_tag(takes_context=True) 
def object_widget(context, obj, size='small'): 
    context_func = getattr(obj, 'widget_context') # try getting the context method 
    extra_context = context_func(context) if context_func else {} 
    extra_context['obj'] = obj 

    long_tuple = (obj._meta.app_label, 'widgets', obj.__class__.__name__, size) 
    return render_to_string([ # multiple templates to have both generic and specific templates 
     '%s/%s/%s.%s.html' % long_tuple, # the most specific (photos/widgets/photo.small.html) 
     '%s/widget.%s.%s.html' % (obj._meta.app_label, obj.__class__.__name__, size), 
     '%s/widget.%s.html' % (obj._meta.app_label, size), # myapp/widget.small.html 
     'widget.%s.html' % size, 
    ], 
    extra_context 
    context) 
utilisation

:

{% load objwidgets %} 
{% object_widget photo1 'large' %} 
{% object_widget photo2 %} 

faire un modèle pour le widget objet, myapp/widgets/photo.small.html:

<b>{{ obj.name }}</b> 
<img src="{{ obj.thumbnail.url }}"/> 
{% if can_edit %}<a href="{{ obj.get_edit_url }}">edit</a>{% endif %} 
{% for t in tags %} 
    <a href="{{ tag.get_absolute_url }}">{{ tag.text }}</a> 
{% endif %} 
+0

explication Grand. Merci beaucoup! – laszchamachla

+0

De rien! –

+0

_Après quelques jours de codage_ - cette approche est tout simplement géniale! Il encourage le DRY de manière optimale, rend le développement plus rapide et plus propre. Le meilleur conseil Django sur SO pour moi jamais :) – laszchamachla

0

Vous ne devriez pas générer de code HTML du tout dans votre modèle. Vous pouvez écrire some custom template tags pour réaliser ce dont vous avez besoin. Si vous utilisez la version django dev, vous pouvez créer une balise d'inclusion avec un argument qui pourrait renvoyer un morceau de html en fonction du type de modèle de l'entrée.