Exibir vários modelos do Django relacionados em um problema de design da tabela

votos
3

Eu estou lutando com o design de um aplicativo Django. Dados os seguintes modelos:

class A(models.Model):
    name = models.CharField(max_length=255)

class B(models.Model):
    name = models.CharField(max_length=255)
    a = models.ForeignKey(A)

class C(models.Model):
    val = models.IntegerField()
    b = models.ForeignKey(B)

Eu gostaria de ter uma visão / modelo que exibe uma tabela HTML que mostra na primeira coluna todos os objetos A, na segunda coluna todos os objetos B (agrupadas por A) que são referenciados para A e na última coluna a soma de todas as Val de de C objectos que são referenciados para cada B. Tudo isto com uma soma para cada um objecto. O exemplo a seguir mostra o que eu estou procurando:

A1.name | B1.name [onde FK a A1] | soma (C.val) [onde FK para B1]
A1.name | B2.name [onde FK a A1] | soma (C.val) [onde FK para B2]
A1.name | total | soma (C.val) [onde FK para Bx (todos B que tem FK para A1]
A2.name | B3.name [onde FK para A2] | soma (C.val) [onde FK para B3]
A2.name | total | soma (C.val) [onde FK para Bx (todos B que tem FK para A2]

Alguém pode me dar um conselho como projetar um problema tão (infelizmente, o meu código, muitas vezes acaba em uma grande bagunça)?

Devo estender as classes de modelo com métodos adequados? Fazer uma consulta personalizada para todo os dados da tabela na vista? Apenas obter todos os objetos por meio de gerentes e fazer a maioria das coisas no modelo?

Obrigado por cada resposta.

Saudações,

Luke.

Publicado 11/02/2009 em 11:13
fonte usuário
Em outras línguas...                            


2 respostas

votos
5

Se você tem esse modelo de data para que você pode buscar tudo bé então agrupá-los por ae calcular o montante total. Código pode ser parecido com este:

Visão:

from django.utils.itercompat import groupby

def view(request):
   bs = B.objects.all().annotate(sum_of_c_val=Sum('c.val'))\
                       .select_related('a')
   b_by_a = [
            {
               'grouper': key,
               'list': list(val),
               'total': sum([b.sum_of_c_val for b in val])
            }
            for key, val in
            groupby(bs, lambda b: b.a)
   ]

   return render_to_response('tmpl.html', {'b_by_a': b_by_a})

E modelo:

{% for b_group in b_by_a %}
  {% for b in b_group.list %}
    <tr>
        <td>`b_group`.`grouper`.`name`</td>
        <td>`b`.`name`</td>
        <td>`b`.`sum_of_c_val`</td>
    </tr>
  {% endfor %}
  <tr>
      <td>`b_group`.`grouper`.`name`</td>
      <td>Total</td>
      <td>`b_group`.`total`</td>
  </tr>
{% endfor %}

EDITAR:

Para compatível com Django 1.0 você tem que substituir annotatechamada com extraselect ou em python cálculo da quantidade.

  1. Com subconsulta:

    bs = B.objects.all().extra(
        select={
          'sum_of_c_val': 'SELECT SUM(app_c.val) FROM app_c WHERE app_c.b_id=app_b.id'
        }).select_related('a')
    #...
    

    Onde app- nome do aplicativo

  2. Este cálculo em python:

     bs = B.objects.all().select_related('a')
     for b in bs:
         b.sum_of_c_val = sum(map(int, b.c.all().values_list("val", flat=True)))
     #...
    

    Mas produz N consultas adicionais (onde N = len(bs))

Respondeu 11/02/2009 em 11:56
fonte usuário

votos
1

Disclaimer: Eu sou um Django iniciante mim, mas se eu entendi seus conceitos básicos bem, então:

Dado que a visão que você quer é - como diz - apenas uma visão dos dados subjacentes, então você deve fazer a triagem e agrupamento no módulo de vista. Eu não acho que você deve mexer com o modelo (que é apenas os dados), nem com o modelo (que é apenas um layout do ponto de vista).

Respondeu 11/02/2009 em 11:37
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more