Digamos que tenho o seguinte no meu models.py:
Ou seja, existem vários Companies, cada um com um intervalo de Ratese Clients. Cada um Clientdeve ter uma base Rateescolhida de seu pai Company's Rates, não outra Company's Rates.
Ao criar um formulário para adicionar um Client, eu gostaria de remover as Companyopções (como isso já foi selecionado por meio de um botão "Adicionar cliente" na Companypágina) e limitar as Rateopções a isso Companytambém.
Como eu faço isso no Django 1.0?
Meu forms.pyarquivo atual é apenas clichê no momento:
E o views.pytambém é básico:
No Django 0.96, eu pude invadir isso fazendo algo como o seguinte antes de renderizar o modelo:
ForeignKey.limit_choices_toparece promissor, mas não sei como passar the_company.ide não sei se isso funcionará fora da interface do administrador.
Obrigado. (Parece uma solicitação bastante básica, mas se eu deveria redesenhar algo, estou aberto a sugestões.)
Obrigado pela dica para "limit_choices_to". Não resolve a sua pergunta, mas o meu :-) Docs: docs.djangoproject.com/en/dev/ref/models/fields/...
ForeignKey é representado por django.forms.ModelChoiceField, que é um ChoiceField cujas opções são um modelo QuerySet. Veja a referência para ModelChoiceField .
Portanto, forneça um QuerySet ao querysetatributo do campo . Depende de como seu formulário é criado. Se você criar um formulário explícito, terá campos nomeados diretamente.
Isso é feito explicitamente na exibição. Não hackear.
Ok, isso parece promissor. Como faço para acessar o objeto de campo relevante? form.company.QuerySet = Rate.objects.filter (company_id = the_company.id)? ou através de um dicionário?
Ok, obrigado por expandir o exemplo, mas parece que tenho que usar form.fields ["rate"]. Queryset para evitar "'ClientForm' objeto não tem nenhum atributo 'rate'", estou perdendo alguma coisa? (e seu exemplo deve ser form.rate.queryset ser consistente também.)
Não seria melhor definir o conjunto de consultas dos campos, no __init__método do formulário ?
— Lakshman Prasad /
@Lott o último comentário não está correto (ou o meu site não deve estar funcionando :). Você pode preencher os dados de validação usando a chamada super (...) .__ init__ no seu método substituído. Se você estiver fazendo várias dessas alterações no conjunto de consultas, é muito mais elegante empacotá-las, substituindo o método init .
— 7289 Michael
Felicidades @Slott, eu adicionei uma resposta, pois levaria mais de 600 caracteres para explicar. Mesmo que essa pergunta seja antiga, está obtendo uma pontuação alta no Google.
— 227 Michael
Além da resposta de S.Lott e como se tornar o Guru mencionado nos comentários, é possível adicionar os filtros do conjunto de consultas substituindo a ModelForm.__init__função. (Isso pode se aplicar facilmente a formulários regulares), pode ajudar na reutilização e manter a função de visualização organizada.
Isso pode ser útil para reutilizar, digamos, se você possui filtros comuns necessários em muitos modelos (normalmente eu declaro uma classe Form abstrata). Por exemplo
Fora isso, estou apenas reafirmando o material do blog Django, do qual existem muitos bons por aí.
Há um erro de digitação no seu primeiro trecho de código, você está definindo args duas vezes em __init __ () em vez de args e kwargs.
Gosto mais dessa resposta, acho mais fácil encapsular a lógica de inicialização do formulário na classe form, em vez do método view. Felicidades!
Isso é simples e funciona com o Django 1.4:
Você não precisa especificar isso em uma classe de formulário, mas pode fazê-lo diretamente no ModelAdmin, pois o Django já inclui este método interno no ModelAdmin (nos documentos):
Uma maneira ainda mais interessante de fazer isso (por exemplo, na criação de uma interface administrativa de front-end que os usuários possam acessar) é subclassificar o ModelAdmin e alterar os métodos abaixo. O resultado líquido é uma interface do usuário que APENAS mostra o conteúdo relacionado a eles, permitindo que você (um superusuário) veja tudo.
Eu substituí quatro métodos, os dois primeiros tornam impossível para um usuário excluir qualquer coisa e também remove os botões de exclusão do site de administração.
A terceira substituição filtra qualquer consulta que contenha uma referência a (no exemplo 'usuário' ou 'porco-espinho' (apenas como ilustração).
A última substituição filtra qualquer campo de chave estrangeira no modelo para filtrar as opções disponíveis da mesma forma que o conjunto de consultas básico.
Dessa forma, você pode apresentar um site de administração fácil de gerenciar, que permite que os usuários mexam com seus próprios objetos, e você não precisa se lembrar de digitar os filtros ModelAdmin específicos sobre os quais falamos acima.
remova os botões "excluir":
impede permissão de exclusão
filtra objetos que podem ser visualizados no site de administração:
filtra as opções de todos os campos de chave estrangeira no site de administração:
— neil.millikin
E devo acrescentar que isso funciona bem como um formulário personalizado genérico para vários administradores de modelos com campos de referência semelhantes de interesse.
— Nemesisfixx
Esta é a melhor resposta se você estiver usando Django 1.4+
Para fazer isso com uma exibição genérica, como CreateView ...
a parte mais importante disso ...
, leia meu post aqui
Se você não criou o formulário e deseja alterar o conjunto de consultas, pode fazer:
Isso é bastante útil quando você está usando visualizações genéricas!
Então, eu realmente tentei entender isso, mas parece que o Django ainda não torna isso muito simples. Não sou tão burra assim, mas simplesmente não consigo ver nenhuma solução (um tanto) simples.
Acho geralmente muito feio ter que substituir as visualizações de administrador por esse tipo de coisa, e todos os exemplos que eu acho nunca se aplicam totalmente às visualizações de administrador.
Essa é uma circunstância tão comum nos modelos que eu acho que é terrível que não haja uma solução óbvia para isso ...
Isso cria um problema ao configurar o Admin for Company, porque ele possui linhas para Contrato e Local, e as opções m2m do Contrato para Local não são filtradas corretamente de acordo com a Empresa que você está editando no momento.
Em resumo, eu precisaria de alguma opção de administrador para fazer algo assim:
Por fim, eu não me importaria se o processo de filtragem fosse colocado no CompanyAdmin base ou se fosse no ContractInline. (Colocá-lo na linha faz mais sentido, mas dificulta a referência ao contrato base como 'próprio'.)
Existe alguém por aí que sabe de algo tão simples quanto esse atalho tão necessário? Quando eu criei administradores PHP para esse tipo de coisa, isso era considerado funcionalidade básica! Na verdade, era sempre automático e precisava ser desativado se você realmente não o quisesse!
Uma maneira mais pública é chamar get_form nas classes Admin. Também funciona para campos que não são do banco de dados. Por exemplo, aqui eu tenho um campo chamado '_terminal_list' no formulário que pode ser usado em casos especiais para escolher vários itens de terminal de get_list (request) e filtrar com base em request.user: