2010-09-20 10 views
5

Jestem nowicjuszem w Django, więc pytanie może być głupie, ale proszę, naucz mnie mnie właściwej drogi, jeśli wiesz. Próbowałem googlować, ale wciąż nie mogę. Oto mój problem:Dwa klucze obce i wartość w szablonie django

Mam klasę w moim modelu, który ma dwa klucze obce:

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 

Moim zdaniem uzyskać częściową listę obiektów X i częściową listę obiektów Y w taki sposób:

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}) 

W moim szablonu Chciałbym być w stanie wyświetlić tabelę tak:

<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 %} 

Jak to zrobić poprawnie w django?

Dziękuję bardzo,

Odpowiedz

0

Powinieneś zachować logikę w swoim widoku. Dlaczego po prostu nie filtrować z_list?

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

Mogę filtrować listę w widoku, ale nadal nie pomaga mi jej poprawnie wyświetlać (tj. Muszę odwzorować (x, y) parę kluczy na z [x, y] wartość w szablonie, aby wyświetlić w odpowiedniej komórce tabeli). Czy coś mi umyka? – mfynf

1

Jako @DZPM suggested powinieneś myśleć o zachowaniu logiki w swoim widoku. [nieśmiało] Kiedyś wymyśliłem własną strukturę danych "Tabela", aby zrobić coś bardzo podobnego. Tabela miała rzędy odpowiadające X, kolumny odpowiadające Y i komórkom odpowiadającym Z[X, Y]. Następnie napisałem filtry get_row i get_cell, aby zrobić trik w szablonie. [/ sheepish]

To powiedziawszy, to, czego chcesz, można osiągnąć za pomocą pary niestandardowych filtrów. To rozwiązanie jest dość szczegółowe.

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

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

Można używać tych filtrów w szablonie, jak pokazano poniżej:

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

Bingo! Dziękuję bardzo - to był brakujący link (niestandardowe filtry). – mfynf

0

Innym rozwiązaniem byłoby stworzenie generatora w widoku, a następnie wysłać go do kontekstu szablonu:

# 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} 

Następnie szablon mógłby wyglądać następująco:

{% 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

Połączyłem koncepcje filtra niestandardowego i funkcji jako obiektów pierwszej klasy, tworząc filtr szablonu w funktor (funkcja-obiekt).

Oto co skończyło się robi:

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) 

W szablonie:

{% 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> 

Dzięki wszystkim za pomoc!