Два внешних ключа и значение в шаблоне django - PullRequest
5 голосов
/ 20 сентября 2010

Я новичок в Джанго, поэтому вопрос может быть глупым, но, пожалуйста, не стесняйтесь учить меня правильному пути, если вы это знаете. Я попытался погуглить вопрос, но я все еще в растерянности. Вот моя проблема:

В моей модели есть класс с двумя внешними ключами:

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

На мой взгляд, я получаю частичный список объектов X и частичный список объектов Y, например:

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

В моем шаблоне я хотел бы иметь возможность отображать таблицу следующим образом:

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

Как мне сделать это правильно в Django?

Большое спасибо,

Ответы [ 4 ]

1 голос
/ 20 сентября 2010

Как @DZPM предложил , вам следует подумать о том, чтобы сохранить логику в своем представлении. [овцы] Однажды я изобрел свою собственную структуру данных «Таблица», чтобы сделать что-то очень похожее. В таблице были строки, соответствующие X, столбцы, соответствующие Y, и ячейки, соответствующие Z[X, Y]. Затем я написал фильтры get_row и get_cell, чтобы добиться цели в шаблоне. [/ Робкий]

Тем не менее, то, что вы хотите, может быть достигнуто с помощью пары пользовательских фильтров. Это решение довольно многословно.

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

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

Вы можете использовать эти фильтры в шаблоне, как показано ниже:

{% if z|x_is:x and z|y_is:y %}
    {{ z }}
{% else %}
    N/A
{% endif %}
0 голосов
/ 22 сентября 2010

Я объединил понятия пользовательского фильтра и функций как объекты первого класса, превратив шаблонный фильтр в функтор (функция-объект).

Вот что я в итоге сделал:

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)

В шаблоне:

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

Спасибо всем за помощь!

0 голосов
/ 20 сентября 2010

Другой подход - создать генератор в вашем представлении и затем отправить его в контекст вашего шаблона:

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

Тогда ваш шаблон может выглядеть так:

{% 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 голосов
/ 20 сентября 2010

Вы должны держать логику в своем поле зрения. Почему бы вам не отфильтровать там z_list?

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