2009-11-22 5 views
0

Surmontez cette partie d'un modèle Django. regs est une liste d'objets Reg. Reg.editable est un BooleanField. Je souhaite afficher un bouton radio par élément dans la liste. Si r.editable est False, le bouton radio doit être désactivée:Problème avec la logique dans le modèle Django

{% for r in regs %} 
<input type="radio" value="{{ forloop.counter }}" 
{% if forloop.first %}checked="checked"{% endif %} 
{% if not r.editable %}disabled="disabled"{% endif %}/> 
{% endfor %} 

Comme vous pouvez le voir, je suis en utilisant forloop.first pour vérifier le premier bouton radio, mais cela a un problème! Qu'en est-il si le premier élément a éditable == Faux? Le premier bouton radio sera désactivé et chéqué. Si un utilisateur envoie "le formulaire", je recevrai une valeur non attendue.

Suis-je clair avec le problème ici? Comment puis-je réécrire ce modèle pour rendre tel que coché le bouton radio FIRST ENABLED?

Merci

+0

BTW, je n'utilise pas le trou Django, juste le moteur de modèle, donc je ne peux pas déplacer cette logique à la vue :) –

Répondre

1

La réelle réponse à cette question est la suivante:

Une telle logique n'a pas sa place dans le modèle. Vous pouvez prétraiter le contexte avant de le transmettre au modèle, ce qui élimine le besoin de le faire en utilisant la logique du moteur de gabarit (intentionnellement) paralysée. À mon avis, ce que vous faites est faux. Je veux dire, django a parfaitement les formes api, pourquoi rendre les entrées directement alors? Certains pourraient argumenter que les formes de Django sont inflexibles, mais pour ce besoin spécifique, cela sera sans doute suffisant.

Et de réitérer - ce genre de logique n'appartient pas à la couche de présentation. Alors ne le mettez pas là, ça vous mordra. En fait, c'était déjà fait.

1

Juste régler votreif s

{% for r in regs %} 
    {% if forloop.first %} 
     <input type="radio" value="{{ forloop.counter }}" checked="checked"/> 
    {% else %} 
     {% if not r.editable %} 
      <input type="radio" value="{{ forloop.counter }}" disabled="disabled"/> 
     {% endif %} 
    {% endif %} 
{% endfor %} 

PS: Votre question n'a pas expliqué clairement ce que vous vouliez. J'ai fait quelques hypothèse raisonnable hypothèse. Mettez à jour la question si ce que vous voulez est quelque chose d'autre.

+0

Cela résout le problème de la première radio n'étant pas (vérifié et désactivé), mais Et si la première radio devait être désactivée et non cochée? –

2

Le langage de modèle de Djangos ne vous donne pas beaucoup de logique dans le modèle (j'ai entendu des choses positives sur Jinja2 si vous voulez changer ça). Il y a aussi la balise "Smart" {% if %} qui ajoute plus de fonctionnalités et qui est d'ailleurs proposée pour être incluse dans Django 1.2. En ce qui concerne la résolution de ce problème, je déplacerais probablement la logique vers la vue. (Attention: ne pas le temps de tester cet extrait de code, mais il devrait donner l'idée générale)

def my_view(request, *args, **kwargs): 

    # QuerySet is fetched however it's done... 
    regs = Regs.objects.all() 

    # Wrap regs in display information  
    checked = False 
    radio_buttons = [] 

    for r in regs: 
     if r.editable: 
      if not checked: 
       radio_buttons.append({ 'checked':True, 'enabled':True, 'object':r }) 
       # Set to true once 
       checked = True 
      else: 
       radio_buttons.append({ 'checked':False, 'enabled':True, 'object':r }) 
     else: 
      radio_buttons.append({ 'checked':False, 'enabled':False, 'object':r })   

    # Then pass in radio_buttons for the value of regs down here 
    render_to_whatever(..., { 'regs':radio_buttons }) 

Dans ce cas, nous avons Enveloppez la QuerySet qui donnera notre modèle un peu plus de détails sur le rendu . Le modèle devient "stupide" maintenant.

{% for r in regs %} 
    <input type="radio" value="{{ forloop.counter }}" 
    {% if r.checked %}checked="checked"{% endif %} 
    {% if not r.enabled %}disabled="disabled"{% endif %}/> 
    {% comment %} To access the original object use: {{ r.object }} {% endcomment %} 
{% endfor %} 
0

Similaire à T.La réponse de Pierre de faire cette logique dans la vue, vous pouvez simplement ajouter une nouvelle variable de modèle qui indique la première radio vérifié:

def my_view(request, *args, **kwargs): 
    regs = Regs.objects.all() 
    checked_index = None 
    for i, reg in enumerate(regs): 
    if reg.enabled: 
     checked_index = i 
     break 
    # pass checked_index into the template... 

Modèle:

{% for r in regs %} 
    {% ifequal forloop.counter0 checked_index %} 
    <input type="radio" value="{{ forloop.counter }}" checked="checked"/> 
    {% else %} 
    <input type="radio" value="{{ forloop.counter }}" {% if not r.editable %}disabled="disabled"{% endif %}/> 
    {% endif %} 
{% endfor %} 
0

similaires à becomingGuru mais résoudre vos problèmes:

{% for r in regs %} 
    {% if not r.editable %} 
     <input type="radio" value="{{ forloop.counter }}" disabled="disabled"/>  
    {% else %} 
     {% if forloop.first %} 
      <input type="radio" value="{{ forloop.counter }}" checked="checked"/> 
     {% endif %} 
    {% endif %} 
{% endfor %} 

Il vérifie d'abord si r est modifiable, puis vérifie s'il s'agit du premier. Cordialement.

Questions connexes