2010-09-20 48 views
5

Soy un novato en django, por lo que la pregunta puede ser tonta, pero por favor siéntanse libres de enseñarme el camino correcto si lo saben. Traté de buscar en Google el problema, pero todavía estoy perdido. Aquí está mi problema:Dos llaves foráneas y un valor en la plantilla django

tengo una clase en mi modelo que tiene dos claves externas:

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 

A mi me da una lista parcial de los objetos X y una lista parcial de los objetos Y de este modo:

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

En mi plantilla que me gustaría ser capaz de mostrar una tabla de este modo:

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

¿Cómo hago esto correctamente en django?

Muchas gracias,

Respuesta

0

Debe mantener la lógica en su punto de vista. ¿Por qué no filtras la z_list allí?

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

Puedo filtrar la lista en la vista, sin embargo, todavía no me ayuda a mostrarla correctamente (es decir, necesito asignar (x, y) el par de claves al valor z [x, y] en la plantilla para mostrar en una celda de tabla adecuada). ¿Me estoy perdiendo de algo? – mfynf

1

Como @DZPM suggested, usted debe pensar en mantener la lógica en la vista. [tímido] Una vez inventé mi propia estructura de datos "Table" para hacer algo muy similar. La tabla tenía filas correspondientes a X, columnas correspondientes a Y y celdas correspondientes a Z[X, Y]. Luego escribí los filtros get_row y get_cell para hacer el truco en la plantilla. [/ avergonzado]

Dicho esto, lo que desea puede lograrse utilizando un par de filtros personalizados. Esta solución es bastante detallada.

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

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

Puede utilizar estos filtros en la plantilla como se muestra a continuación:

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

¡Bingo! Muchas gracias, ese era el eslabón perdido (filtros personalizados). – mfynf

0

Otro enfoque sería la creación de un generador en su punto de vista y, a continuación, enviarlo a su contexto de la plantilla:

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

A continuación, la plantilla podría tener este aspecto:

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

Combiné los conceptos de filtro personalizado y funciones como objetos de primera clase que hacen un filtro de plantilla en un funtor (función-objeto).

Esto es lo que terminé haciendo:

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) 

En plantilla:

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

Gracias a todos por su ayuda!

Cuestiones relacionadas