Mesmo que geralmente sejam parte de um View
, os do Django Form
, por padrão, não estão cientes do contexto no qual estão sendo usados. Isso faz todo o sentido, em harmonia com o princípio do acoplamento fraco : a Form
precisa cuidar da validação dos dados, bem como da renderização (via Widget
s) e nada mais.
No entanto, muitas vezes é o caso em que preciso de um ModelForm
para agir de maneira um pouco diferente, quer seja mencionado como parte de um CreateView
ou de um UpdateView
. Vejamos um exemplo rápido – digamos que estamos criando um modelo (digamos, um Appointment
) que tem uma ForeignKey
relação com um User
– e queremos apenas ter usuários ativos mostrados em nosso ModelChoiceField
. Porém, quando você está editando um existente Appointment
que pertence a um usuário inativo , obviamente você precisa ter esse usuário no queryset também, ou o formulário não será validado. O que nós fazemos?
Uma maneira de implementar comportamentos diferentes para formulários é apenas usar formulários diferentes ; ainda outro – para fazer o construtor do formulário aceitar um is_createview
argumento de palavra – chave e adicioná-lo ao dict
que é retornado por um CreateView get_form_kwargs
. Ambas as formas exigem que você escreva mais código do que o necessário, especialmente quando você pode simplesmente fazer:
class AppointmentForm(ModelForm):
def __init__(self, *args, **kwargs):
if self.instance.pk is None: # it's a CreateView
self.fields['user'].queryset = ... # active users
else: # it's an UpdateView:
self.fields['user'].queryset = ... # active users + self.instance.user
instance
é um atributo de classe (muito útil) de ModelForm
s, que contém uma instância de sua classe de modelo (ou seja Appointment
). No contexto de a CreateView
, instance
ainda não é salvo no banco de dados, portanto pk
é None
. Simples assim!