Como posso usar formulários Django / modelos para representar escolhas entre campos?

votos
4

Como posso usar escolhas boolean em um campo de modelo para ativar / desativar outros campos. Se um valor booleano é true / false eu quero isso para ativar / desativar outros campos do modelo. Existe uma maneira de expressar nativamente essas relações usando Django modelos / formas / widgets? Eu continuo escrevendo modelos personalizados para modelar essas relações, mas não consigo descobrir uma boa maneira de representá-los no Django sem um modelo especial.

Por exemplo:

classe PointInTime (models.Model):
    is_absolute_time = models.BooleanField ()
    absolute_time = models.DateTimeField ()
    is_relative_time = models.BooleanField ()
    days_before = models.IntegerField ()

Portanto, se o is_absolute_time é verdade, eu quero a entrada absolute_time ser editável no GUI ea entrada days_before a ser cinza e não-editável. Se o sinalizador 'is_relative_time' é verdade, eu quero a entrada absolute_time a ser acinzentado, eo valor days_before ser editável. Então is_absolute_time e is_relative_time seria botões de rádio no mesmo grupo na GUI e seus dois campos correspondentes só seria editável quando o botão de opção é selecionado. Isso é fácil de fazer em um modelo personalizado, mas há uma maneira de usar um modelo / form no Django para mostrar nativamente essa relação?

Publicado 03/02/2009 em 16:31
fonte usuário
Em outras línguas...                            


2 respostas

votos
6

Seria útil para esclarecer o que entende por "mostrar nativamente essa relação", e pensar claramente sobre separação de interesses.

Se tudo que você quer é "cinza out" ou desativar um determinado campo com base no valor de outro campo, isto é puramente uma questão de apresentação / UI, por isso, o modelo (e / ou Javascript) é o local apropriado para lidar com isso.

Se você deseja validar que os dados apresentados é internamente consistente (ie absolute_time é preenchido se is_absolute_time é True, etc), isso é uma questão form-validação. O lugar para que a lógica é no método clean () de sua forma ou objeto ModelForm.

Se você quiser garantir que nenhum modelo PointInTime pode ser salvo no banco de dados sem ser internamente consistente, que é uma preocupação de camada de dados. O lugar para isso está em um método save () em seu modelo de objeto personalizado (Django 1.2 irá incluir um mais extenso sistema de validação do modelo ).

Todas essas opções envolvem escrever código imperativo para fazer o que você precisa com essas áreas específicas. Pode ser que você está procurando uma forma de representar a situação declarativa em seu modelo para que o código em todos os três casos acima pode ser escrita genericamente em vez de especificamente. Não há built-in Django maneira de fazer isso, mas você certamente poderia fazer algo como:

class PointInTime(models.Model):
    field_dependencies = {'is_absolute_time': 'absolute_time',
                          'is_relative_time': 'days_before'}
    ... fields here ...

Em seguida, o seu modelo de salvar código () (ou código de seu Formulário clean (), ou o seu modelo), poderia usar este dicionário para determinar quais campos devem ser ativado / desativado, dependendo do valor que outro. Esta generalização é não vale a pena o esforço, porém, a menos que você antecipar a necessidade de fazer a mesma coisa em um número de diferentes modelos.

Por último, algumas alternativas de design de esquema que você pode querer considerar para obter a sua camada de dados melhor normalizada:

  • Se existem apenas dois estados válidos (absoluta e relativa), usar um único campo boolean em vez de dois. Então você evitar possíveis inconsistências (o que significa que ambos os booleans são Falso? Ou verdadeiro?)

  • Ou simplificar ainda mais, eliminando os booleanos inteiramente e apenas utilizando valores nulos de um ou do outro dos absolute_time / days_before.

  • Se pode haver mais de dois estados válidos, use um único IntegerField ou CharField com escolhas em vez de usar dois campos booleanos. Mesma razão que acima, mas pode acomodar mais de duas opções.

  • Desde a RelativeTime e um AbsoluteTime não parecem partilhar quaisquer campos de dados uns com os outros, considere dividi-los para fora em modelos separados inteiramente. Se você tiver outros modelos que precisam de um ForeignKey para um ou outro, você poderia modelar que com herança (ambos RelativeTime e AbsoluteTime herdar de PointInTime, outros modelos têm ForeignKeys para PointInTime).

Respondeu 03/02/2009 em 19:29
fonte usuário

votos
1

Eu não sou inteiramente certo o que você está fazendo com esses objetos, mas o que o usuário escolhe, você está apontando para um único momento no tempo. "5 dias atrás" é "Quinta-feira" e vice-versa.

Assim a menos que as datas rolar com o site (por exemplo, o registro com "5 dias atrás" vai ainda significam quinta-feira, amanhã, etc), certamente este é apenas um problema de interface? Se for esse o caso, eu ia ficar com um único valor para a data do seu modelo e deixe o formulário e vista fazer todo o trabalho.

Isso resolve o lado de administração gerado automaticamente das coisas como você vai ter um campo para enfrentar, mas não vai nativamente dar-lhe a escolha entre os dois, a menos que você escreve o seu próprio widget forma e substituir a classe ModelAdmin para o seu modelo.

Se este não é o caso, por favor, ignore esta resposta.

Respondeu 03/02/2009 em 17:29
fonte usuário

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