2010-09-20 5 views
5

Je suis un débutant à django, donc la question pourrait être stupide, mais s'il vous plaît n'hésitez pas à m'apprendre la bonne façon si vous le savez. J'ai essayé de googler le problème, mais je suis toujours à perte. Voici mon problème:Deux clés étrangères et une valeur dans le modèle django

J'ai une classe dans mon modèle qui a deux clés étrangères:

class X(models.Model): 
    name = models.CharField(max_length=30) 
    def __unicode__(self): 
     return name 

class Y(models.Model): 
    name = models.CharField(max_length=30) 
    def __unicode__(self): 
     return name 

class Z(models.Model): 
    name = models.CharField(max_length=30) 
    x = models.ForeignKey(X) 
    y = models.ForeignKey(Y) 
    def __unicode__(self): 
     return name 

À mon avis, je reçois une liste partielle des objets X et une liste partielle des objets Y comme ceci:

def MyView(x_pattern, y_pattern): 
    x_list = X.objects.filter(name__contains=x_pattern) 
    y_list = Y.objects.filter(name__contains=y_pattern) 
    z_list = Z.objects.all() 
    return render_to_response({'x_list': x_list, 'y_list': y_list, 'z_list': z_list}) 

Dans mon modèle, je voudrais être en mesure d'afficher une table comme ceci:

<table> 
    <tr> 
    <td>Y</td> 
    {% for x in x_list %} 
    <td>{{ x }}</td> 
    {% endfor %} 
    </tr> 
    {% for y in y_list %} 
    <tr> 
    <td>{{ y }}</td> 
    {% for x in x_list %} 
    <td> 
     <!-- here I need help: 
      I need to display z[x, y] if it exists, or "N/A" otherwise. 
     --> 
    </td> 
    {% endfor %} 
    </tr> 
    {% endfor %} 

Comment est-ce que je fais cela correctement dans django?

Merci beaucoup,

Répondre

0

Vous devriez garder la logique à votre vue. Pourquoi ne pas simplement filtrer la z_list là?

z_list = Z.objects.filter(x__name__contains=x_pattern, y__name__contains=y_pattern) 
+0

Je peux filtrer la liste dans la vue, mais cela ne m'aide toujours pas à l'afficher correctement (ie je dois mapper la paire de clés (x, y) à la valeur z [x, y] du modèle pour afficher dans une cellule de table appropriée). Est-ce que j'ai râté quelque chose? – mfynf

1

Comme @DZPM suggested, vous devriez penser à garder la logique à votre avis. [penaud] Une fois, j'ai inventé ma propre structure de données "Table" pour faire quelque chose de très similaire. La table avait des lignes correspondant à X, des colonnes correspondant à Y et des cellules correspondant à Z[X, Y]. J'ai ensuite écrit get_row et get_cell filtres pour faire l'affaire dans le modèle. [/ sheepish]

Cela dit, ce que vous voulez peut être accompli en utilisant une paire de filtres personnalisés. Cette solution est plutôt verbeuse.

@register.filter 
def x_is(value, x): 
    return value.x == x 

@register.filter 
def y_is(value, y): 
    return value.y == y 

Vous pouvez utiliser ces filtres dans le modèle comme indiqué ci-dessous:

{% if z|x_is:x and z|y_is:y %} 
    {{ z }} 
{% else %} 
    N/A 
{% endif %} 
+0

Bingo! Merci beaucoup - c'était le lien manquant (filtres personnalisés). – mfynf

0

Une autre approche serait de créer un générateur dans votre vue, puis l'envoyer à votre contexte de modèle:

# nested inside your view function 
def x_and_z_list(y): 
    for x in x_list: 
     z_obj = x.z_set.filter(y=y) 
     z_name = z_obj or 'N/A' 
     yield {'x': x, 'z': z_name} 
return render_to_response('mytemplate', {'list_generator': x_and_z_list} 

Ensuite, votre modèle pourrait ressembler à ceci:

{% for y in y_list %} 
    <tr> 
     <td>{{ y }}</td> 
     {% for pair in list_generator.y %} {# pair is the dict you yielded before #} 
      <td>{{ pair.x.name }}: {{ pair.z }}</td> 
     {% endfor %} 
    </tr> 
{% endfor %} 
0

J'ai combiné les concepts de filtre personnalisé et de fonctions en tant qu'objets de première classe faisant un filtre de modèle dans un foncteur (fonction-objet).

Voici ce que je fini par faire:

def z_filter(x, y): 
    z_list = list(Z.objects.filter(x, y)) 
    return z_list.pop().name or 'N/A' 
register.filter(z_filter) 

dans le modèle:

{% load z_filter %} 
<table> 
<tr> 
    <td>Y</td> 
    {% for x in x_list %} 
    <td>{{ x }}</td> 
    {% endfor %} 
</tr> 
{% for y in y_list %} 
    <tr> 
    <td>{{ y }}</td> 
    {% for x in x_list %} 
    <td>{{ x|z_filter:y }}</td> 
    {% endfor %} 
    </tr> 
{% endfor %} 
</table> 

Merci à tous pour votre aide!

Questions connexes