Criando formulários a partir de models¶
ModelForm¶
Se você está construindo uma aplicação baseada em banco de dados, existe uma
grande chance de que seus formulários corresponderão com os seus modelos
Django. Por exemplo, você tem um modelo BlogComment, e quer criar um
formulário que possibilite que as pessoas enviem comentários. Neste caso, seria
redundante definir os tipos de campo no seu formulário, porque isso já foi
feito no seu modelo.
Por este motivo, o Django disponibiliza uma classe de ajuda que possibilita
a criação de uma classe Form a partir de um modelo Django.
Por exemplo:
>>> from django.forms import ModelForm
# Cria a classe de formulário
>>> class ArticleForm(ModelForm):
... class Meta:
... model = Article
# Criando um formulário para adicionar um artigo.
>>> form = ArticleForm()
# Criando um formulário para atualizar dados de um artigo.
>>> article = Article.objects.get(pk=1)
>>> form = ArticleForm(instance=article)
Tipos de campos¶
A classe Form gerada terá um campo de formulário para cada campo de modelo.
Cada campo de modelo tem um campo de formulário correspondente padrão. Por
exemplo, um CharField num modelo é representado como um CharField num
formulário. Um ManyToManyField no modelo é representado como um
MultipleChoiceField. Segue uma lista completa de conversões:
| Campo de modelo | Campo de formulário |
|---|---|
AutoField |
Não é representado no formulário |
BooleanField |
BooleanField |
CharField |
CharField com max_length igual ao
valor de max_length do campo do modelo |
CommaSeparatedIntegerField |
CharField |
DateField |
DateField |
DateTimeField |
DateTimeField |
DecimalField |
DecimalField |
EmailField |
EmailField |
FileField |
FileField |
FilePathField |
CharField |
FloatField |
FloatField |
ForeignKey |
ModelChoiceField (veja abaixo) |
ImageField |
ImageField |
IntegerField |
IntegerField |
IPAddressField |
IPAddressField |
ManyToManyField |
ModelMultipleChoiceField (veja
abaixo) |
NullBooleanField |
CharField |
PhoneNumberField |
USPhoneNumberField
(de django.contrib.localflavor.us) |
PositiveIntegerField |
IntegerField |
PositiveSmallIntegerField |
IntegerField |
SlugField |
CharField |
SmallIntegerField |
IntegerField |
TextField |
CharField com
widget=forms.Textarea |
TimeField |
TimeField |
URLField |
URLField com verify_exists igual
ao valor de verify_exists do campo
do modelo |
XMLField |
CharField com widget=Textarea |
FloatField juntamente com os campos de fomulário
e de modelo DecimalField são novos no Django 1.0.Como esperado, os campos de modelo do tipo ForeignKey e ManyToManyField
são casos especiais:
ForeignKeyé representado pordjango.forms.ModelChoiceField, que é umChoiceFieldem quechoicesé umQuerySetdo modelo.ManyToManyFieldé representado pordjango.forms.ModelMultipleChoiceField, que é umMultipleChoiceFieldem quechoicesé umQuerySetdo modelo.
Além disso, cada campo de formulário gerado tem os valores de atributos definidos como asseguir:
- Se um campo de modelo tem
blank=True, então o valor derequiredseráFalseno campo de formulário. Caso contrário,required=True. - O atributo
labeldo campo de formulário será igual aoverbose_namedo campo de modelo, com o primeiro caractere em maiúsculo. - O
help_textdo campo de formulário é igual aohelp_textdo campo de modelo. - Se o campo de modelo tem o atributo
choicesdefinido, então owidgetdo campo de formulário será oSelect, com a lista de opções vindas do atributochoicesdo campo de modelo. As opções normalmente incluirão o valor em branco, que é selecionado por padrão. Se o campo é requerido, isso força o usuário a fazer uma escolha. O valor em branco não será incluído se o campo de modelo tem atributoblank=Falsee um valor dedefaultexplícito (em vez disso o valor dedefaultserá selecionado inicialmente).
Finalmente, note que você pode redefinir o campo de formulário utilizado por um determinado modelo. Veja Redefinindo os tipos de campo padrão abaixo.
Um exemplo completo¶
Considere este conjunto de modelos:
from django.db import models
from django.forms import ModelForm
TITLE_CHOICES = (
('MR', 'Mr.'),
('MRS', 'Mrs.'),
('MS', 'Ms.'),
)
class Author(models.Model):
name = models.CharField(max_length=100)
title = models.CharField(max_length=3, choices=TITLE_CHOICES)
birth_date = models.DateField(blank=True, null=True)
def __unicode__(self):
return self.name
class Book(models.Model):
name = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
class AuthorForm(ModelForm):
class Meta:
model = Author
class BookForm(ModelForm):
class Meta:
model = Book
Com estes modelos, as subclasses de ModelForm acima seriam equivalentes
a isto (a única diferença sendo o método save(), que discutiremos daqui
a pouco.):
class AuthorForm(forms.Form):
name = forms.CharField(max_length=100)
title = forms.CharField(max_length=3,
widget=forms.Select(choices=TITLE_CHOICES))
birth_date = forms.DateField(required=False)
class BookForm(forms.Form):
name = forms.CharField(max_length=100)
authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
O método save()¶
Todo formulário produzido por ModelForm tem também um método
save(). Este método cria e grava um objeto no banco de dados a partir
dos dados atrelados ao formulário. Uma subclasse de ModelForm pode
aceitar uma instância de modelo existente como uma argumento nomeado
instance; se este argumento é fornecido, o save() irá atualizar
a instância. Se não é fornecido, o save() criará uma nova instância do
modelo especificado:
# Cria uma instância de formulário com dados do POST.
>>> f = ArticleForm(request.POST)
# Grava um novo objeto Article com os dados do formulário.
>>> new_article = f.save()
# Cria um formulário para editar um Article existente.
>>> a = Article.objects.get(pk=1)
>>> f = ArticleForm(instance=a)
>>> f.save()
# Cria um formulário para editar um Article existente, mas
# usa os dados do POST para popular o formulário.
>>> a = Article.objects.get(pk=1)
>>> f = ArticleForm(request.POST, instance=a)
>>> f.save()
Note que save() irá levantar uma exceção ValueError se os dados no
formulário não validarem – ou seja if form.errors.
Este método save() aceita um argumento nomeado opcional commit, que
aceita ou True ou False. Se você chamar save() com
commit=False, então ele devolverá um objeto que ainda não foi gravado no
banco de dados. Neste caso, é sua responsabilidade chamar save() na
instância de modelo. Isso é útil se você quer fazer algum custom processamento customizado
no objeto antes de gravá-lo, ou se você quer usar um umas das
opções de gravação de modelo especializadas. commit é True
por padrão.
Um efeito colateral no uso de commit=False é notado quando o seu modelo
tem um relacionamento de muitos para muitos com outro modelo. Se seu modelo tem
um relacionamento de muitos para muitos e você especifica commit=False
quando vai gravar um formulário, o Django não pode gravar od dados para o
relacionamento de muitos para muitos imediatamente. Isso se deve ao fato de
não ser possível gravar os dados de muitos para muitos para uma instância que
ainda não existe no banco de dados.
Para contornar este problema, cada vez que você grava um formulário usando
commit=False, o Django adiciona um método save_m2m() para a sua
subclasse de ModelForm. Depois de de gravar manualmente a instância
produzida pelo formulário, você pode chamar save_m2m() para gravar
os dados de muitos para muitos do formulário. Por exemplo:
# Cria uma instância de formulário com os dados de POST.
>>> f = AuthorForm(request.POST)
# Cria, mas não grava a nova instância de Author.
>>> new_author = f.save(commit=False)
# Modifica o Author de alguma maneira.
>>> new_author.some_field = 'some_value'
# Grava a nova instância.
>>> new_author.save()
# Agora, grava od dados de muitos para muitos para o formulário.
>>> f.save_m2m()
Só é necessário chamar o save_m2m() se você usar save(commit=False).
Quando você simplesmente usa o save() num formulário, todos os dados –
incluindo os dados de muitos para muitos – são gravados sem a necessidade de
chamadas a nenhum método adicional.
Por exemplo:
# Cria uma instância de formulário com os dados de POST.
>>> a = Author()
>>> f = AuthorForm(request.POST, instance=a)
# Cria e grava a nova instância de Author. Não há necessidade de fazer
# nada mais.
>>> new_author = f.save()
A não ser pelos métodos save() e save_m2m(), um ModelForm
funciona exatamente igual a qualquer outro formulário de forms.
Por exemplo, o método is_valid()` é utilizado para validar os dados, o método
is_multipart() para determinar se um formulário requer upload de arquivo
multipart (e se request.FILES deve ser passado ao formulário), etc. Veja
Vinculando arquivos enviados a um formulário para mais informação.
Usando somente alguns campos no formulário¶
Em alguns casos, você não quer que todos os campos do modelo apareçam no
formulário gerado. Existem três maneiras de dizer ao ModelForm para usar
somente alguns campos do modelo:
- Coloque
editable=Falseno campo do modelo. Como resultado, qualquer formulário criado viaModelFormnão incluirá este campo. - Use o atributo
fieldsda classe internaMetadoModelForm. Esse atributo, se especificado, deve ser uma lista de nomes de campos a serem incluídos no formulário. - Use o atributo
excludeda classe internaMetadoModelForm. Esse atributo, se especificado, deve ser uma lista de nomes de campos a serem excluídos do formulário.
Por exemplo, se você quer que um formulário para o modelo Author
(definido acima) tenha somente os campos name e title,
você especificaria fields ou exclude assim:
class PartialAuthorForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'title')
class PartialAuthorForm(ModelForm):
class Meta:
model = Author
exclude = ('birth_date',)
Já que o modelo Author tem somente três campos, ‘name’, ‘title’, e ‘birth_date’, os formulários acima conterão exatamente os mesmos campos.
Note
Se você especifica fields ou exclude na criação de um formulário
com ModelForm, então na chamada do método save(), não serão
atribuídos valores aos campos que não constam do formulário resultante.
O Django impedirá qualquer tentativa de gravar um modelo incompleto,
então se o modelo não permite que os campos faltantes sejam vazios, e não
existe um valor padrão definido para eles, qualquer tentativa de chamar
save() num ModelForm com campos faltantes não funcionará.
Para evitar esse erro, você deve instanciar seu modelo com valores iniciais
para os campos vazios, porém obrigatórios:
author = Author(title='Mr')
form = PartialAuthorForm(request.POST, instance=author)
form.save()
Alternatively, you can use save(commit=False) and manually set
any extra required fields:
form = PartialAuthorForm(request.POST)
author = form.save(commit=False)
author.title = 'Mr'
author.save()
Veja a seção sobre gravação de formulários para mais detalhes no
uso de save(commit=False).
Redefinindo os tipos de campo padrão¶
Os tipos de campos padrão, como descritos na tabela Tipos de campos acima,
são padrões sensatos. Se você tem um DateField no seu modelo, existem
grandes chances dq que você queira que ele seja representado como um
DateField no seu formulário. Mas o ModelForm te dá a flexibilidade
de mudar o campo de formulário para um determinado campo de modelo. Isso é
feito de maneira declarativa especificando os campos como faria num Form
normal. Campos declarados redefinirão os campós padrões gerados pelo uso
do atributo model.
Por exemplo, se você quiser usar MyDateFormField para o campo
pub_date, faça o seguinte:
>>> class ArticleForm(ModelForm):
... pub_date = MyDateFormField()
...
... class Meta:
... model = Article
Se quiser redefiner um widget padrão de um campo, então especifique o parâmetro widget quando declarar o campo de formulário:
>>> class ArticleForm(ModelForm):
... pub_date = DateField(widget=MyDateWidget())
...
... class Meta:
... model = Article
Sobrescrevendo o método clean()¶
Você pode sobrescrever o método clean() em um formulário de modelo para fornecer informações
adicionais como uma validação, da mesma forma que faria num formulário normal.
In this regard, model forms have two specific characteristics when compared to forms:
Por padrão o método clean() valida a unicidade dos campos que são
marcados como unique, unique_together ou unique_for_date|month|year no
modelo. Portanto, se você gostaria de sobrescrever o método clean() e
manter a validação padrão, você deve chamar o método da clean() da classe pai.
Also, a model form instance bound to a model object will contain a
self.instance attribute that gives model form methods access to that
specific model instance.
Herança de formulário¶
Como nos formulários básicos, você pode extender e reutilizar ModelForms
através da herança. Isso é útil se você precisa declarar campos ou métodos
adicionais em uma classe pai para uso em alguns formulários derivados de
modelos. Por exemplo, usando a classe ArticleForm anterior:
>>> class EnhancedArticleForm(ArticleForm):
... def clean_pub_date(self):
... ...
Isso cria um formulário que se comporta da mesma maneira que ArticleForm,
exceto por alguma validação e limpeza de dados adicional para o campo
pub_date.
Você pode criar uma subclasse da classe interna Meta da classe pai se você
quer mudar as listas Meta.fields ou Meta.excludes:
>>> class RestrictedArticleForm(EnhancedArticleForm):
... class Meta(ArticleForm.Meta):
... exclude = ['body']
Isso adiciona o método de EnhancedArticleForm e modifica o
ArticleForm.Meta original para remover um campo.
Entretanto, existem algumas coisas a serem notadas.
- As regras normais de resolução de nomes Python se aplicam. Se você tem
múltiplas classes base que declaram uma classe interna
Meta, somente a primeira será utilizada. Isso significa oMetado filho, se existir, caso contrário oMetado primeiro pai, etc. - Pela mesma razão, uma subclasse não pode herdar de
ModelFormeFormsimultaneamente.
É bem provável que estas notas não te afetarão, a não ser que esteja tentando fazer algo complexo utilizando subclasses.
Model Formsets¶
Como nos formsets comuns, o Django fornece um par de
classes avançadas de formset que tornam facil trabalhar com modelos do Django. Vamos
reutilizar o modelo Author do exemplo acima:
>>> from django.forms.models import modelformset_factory
>>> AuthorFormSet = modelformset_factory(Author)
Isso criará um formset que é capaz de funcionar com os dados associados ao
modelo Author que funciona exatamente igual a um formset comum:
>>> formset = AuthorFormSet()
>>> print formset
<input type="hidden" name="form-TOTAL_FORMS" value="1" id="id_form-TOTAL_FORMS" /><input type="hidden" name="form-INITIAL_FORMS" value="0" id="id_form-INITIAL_FORMS" />
<tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" maxlength="100" /></td></tr>
<tr><th><label for="id_form-0-title">Title:</label></th><td><select name="form-0-title" id="id_form-0-title">
<option value="" selected="selected">---------</option>
<option value="MR">Mr.</option>
<option value="MRS">Mrs.</option>
<option value="MS">Ms.</option>
</select></td></tr>
<tr><th><label for="id_form-0-birth_date">Birth date:</label></th><td><input type="text" name="form-0-birth_date" id="id_form-0-birth_date" /><input type="hidden" name="form-0-id" id="id_form-0-id" /></td></tr>
Note
Uma coisa para se notar é que modelformset_factory usa
formset_factory para gerar formsets. Isto significa que um formeset de
model é somente uma extensão de um formset básico que sabe como interagir
com um model em particular.
Mudando o queryset¶
Por padrão quando você cria um formset de um modelo o formset irá usar um
queryset que inclui todos os objetos no modelo (ex: Author.objects.all()).
Você pode sobrescrever esse comportamento usando o argumento queryset:
>>> formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O'))
Alternativamente, você pode criar uma subclasse que defina o self.queryset no
__init__:
from django.forms.models import BaseModelFormSet
class BaseAuthorFormSet(BaseModelFormSet):
def __init__(self, *args, **kwargs):
self.queryset = Author.objects.filter(name__startswith='O')
super(BaseAuthorFormSet, self).__init__(*args, **kwargs)
Então, passe sua classe BaseAuthorFormSet para a função factory:
>>> AuthorFormSet = modelformset_factory(Author, formset=BaseAuthorFormSet)
Controlando quais campos são usados com fields e exclude¶
Por padrão um model formset usará todos os campos do model, que não estão
marcados com editable=False, Entretanto, isto pode ser sobrescrito no nível
do formset:
>>> AuthorFormSet = modelformset_factory(Author, fields=('name', 'title'))
Usando fields você irá restringir o formset para usar somente os campos
fornecidos. Alternativamente, você pode ter uma abordagem de “out-put”,
especificando quais campos serão excluídos:
>>> AuthorFormSet = modelformset_factory(Author, exclude=('birth_date',))
Usando exclude você irá evistar que dados campos sejam usados em um formset.
Gravando objetos num formset¶
Como num ModelForm você pode gravar os dados no objeto do modelo. Isso é
feito com o método save() do formset:
# Cria uma instância de formset com os dados do POST.
>>> formset = AuthorFormSet(request.POST)
# Supondo que tudo está válido, grave os dados
>>> instances = formset.save()
O método save() devolverá as instâncias que foram gravadas no banco de
dados. Se uma instância não mudar seus nos dados atrelados ela não será gravada
no banco e não será encontrada no valor de retorn (instances no exemplo acima).
Pass commit=False to return the unsaved model instances:
# não grava no banco de dados
>>> instances = formset.save(commit=False)
>>> for instance in instances:
... # faz alguma coisa com a instância
... instance.save()
Isso dá a habilidade de anexar dados às instâncias antes de gravá-las no banco
de dados. Se seu formset contém um ManyToManyField você precisará também
chamar formset.save_m2m() para assegurar que os relacionamentos de muitos
para muitos serão gravados apropriadamente.
Limitando o número de objetos editáveis¶
Como em formsets comuns você pode usar um parâmetro max_num no
modelformset_factory para limitar o número de formulários mostrados.
Com formsets de modelo, isso limitará apropriadamente a query para selecionar
somente o máximo de objetos necessários:
>>> Author.objects.order_by('name')
[<Author: Charles Baudelaire>, <Author: Paul Verlaine>, <Author: Walt Whitman>]
>>> AuthorFormSet = modelformset_factory(Author, max_num=2, extra=1)
>>> formset = AuthorFormSet(queryset=Author.objects.order_by('name'))
>>> formset.initial
[{'id': 1, 'name': u'Charles Baudelaire'}, {'id': 3, 'name': u'Paul Verlaine'}]
Se o valor de max_num é maior que o número de objetos retornados,
formulários em branco extra serão adicionados ao formset, tão logo o total
de formulários não exceda max_num:
>>> AuthorFormSet = modelformset_factory(Author, max_num=4, extra=2)
>>> formset = AuthorFormSet(queryset=Author.objects.order_by('name'))
>>> for form in formset.forms:
... print form.as_table()
<tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" value="Charles Baudelaire" maxlength="100" /><input type="hidden" name="form-0-id" value="1" id="id_form-0-id" /></td></tr>
<tr><th><label for="id_form-1-name">Name:</label></th><td><input id="id_form-1-name" type="text" name="form-1-name" value="Paul Verlaine" maxlength="100" /><input type="hidden" name="form-1-id" value="3" id="id_form-1-id" /></td></tr>
<tr><th><label for="id_form-2-name">Name:</label></th><td><input id="id_form-2-name" type="text" name="form-2-name" value="Walt Whitman" maxlength="100" /><input type="hidden" name="form-2-id" value="2" id="id_form-2-id" /></td></tr>
<tr><th><label for="id_form-3-name">Name:</label></th><td><input id="id_form-3-name" type="text" name="form-3-name" maxlength="100" /><input type="hidden" name="form-3-id" id="id_form-3-id" /></td></tr>
Usando um model formset em uma visão¶
Models formsets são muito similares a formsets. Digamos que queiramos apresentar um
formset para editar instâncias do modelo Author:
def manage_authors(request):
AuthorFormSet = modelformset_factory(Author)
if request.method == 'POST':
formset = AuthorFormSet(request.POST, request.FILES)
if formset.is_valid():
formset.save()
# Faça algo.
else:
formset = AuthorFormSet()
return render_to_response("manage_authors.html", {
"formset": formset,
})
Como você pode ver a lógica da visão de um formset de modelo não é drasticamente diferente
de como usar um formset “normal”. A única diferença é que nos chamamos
formset.save() para salvar os dados no banco de dados. (Isto foi descrito acima em
Gravando objetos num formset.)
Sobrescrevendo o clean() sobre um model_formset¶
Assim como com ModelForms, por padrão o método clean() de um
model_formset irá validar se nenhum dos ítens do formset viola as restrições
de unicidade do seu model (qualquer uma unique, unique_together ou
unique_for_date|month|year). Se você quiser sobrescrever o método
clean() de um model_formset e manter esta validação, você deve chamar
o método clean da classe pai:
class MyModelFormSet(BaseModelFormSet):
def clean(self):
super(MyModelFormSet, self).clean()
# exemplo de validação customizada de forms do formset:
for form in self.forms:
# your custom formset validation
# sua validação personalizada de formset
Usando um queryset customizado¶
Como já foi dito, você pode sobrescrever o queryset padrão usado pelo model formset:
def manage_authors(request):
AuthorFormSet = modelformset_factory(Author)
if request.method == "POST":
formset = AuthorFormSet(request.POST, request.FILES,
queryset=Author.objects.filter(name__startswith='O'))
if formset.is_valid():
formset.save()
# Faça algo.
else:
formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O'))
return render_to_response("manage_authors.html", {
"formset": formset,
})
Note que nós passamos o argumento queryset em ambos os casos POST e
GET neste exemplo.
Usando o formset no template¶
Já três formas de renderizar um formset num template Django.
Primeiro, você pode deixar o formset fazer a maior parte do trabalho:
<form method="POST" action="">
{{ formset }}
</form>
Segundo, você pode manualmente renderizar o formset, mas deixe o form trabalhar por contra própria:
<form method="POST" action="">
{{ formset.management_form }}
{% for form in formset.forms %}
{{ form }}
{% endfor %}
</form>
Quando você renderizar formulários manualmente, certifique-se de renderizar o management_form como mostrado acima. Veja a documentação do management form.
Terceiro, você pode renderizar manualmente cada campo:
<form method="POST" action="">
{{ formset.management_form }}
{% for form in formset.forms %}
{% for field in form %}
{{ field.label_tag }}: {{ field }}
{% endfor %}
{% endfor %}
</form>
Se você optar por usar este terceiro método e você não iterar sobre os campos
com um loop {% for %}, você precisará renderizar a chave primária.
Por exemplo, se você renderizou os campos name e age de um model:
<form method="POST" action="">
{{ formset.management_form }}
{% for form in formset.forms %}
{{ form.id }}
<ul>
<li>{{ form.name }}</li>
<li>{{ form.age }}</li>
</ul>
{% endfor %}
</form>
Observe como é preciso, explicitamente, renderizar {{form.id}}. Isto garante
que o formset do model, no caso do POST, irá funcionar perfeitamente. (Este
exemplo assume uma chave primária chamada id, certifique-se de
renderizá-la.)
Formsets em linha (inline)¶
Formsets em linha é uma pequena camada de abstração sobre os formsets de model. Este simplificam o caso de trabalhar com objetos relacionados através de uma chave estrangeira. Suponhamos que você tenha dois models:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(max_length=100)
Se você quiser criar um formset que permita editar books pertencentes a um author em particular, você pode fazer isto:
>>> from django.forms.models import inlineformset_factory
>>> BookFormSet = inlineformset_factory(Author, Book)
>>> author = Author.objects.get(name=u'Mike Royko')
>>> formset = BookFormSet(instance=author)
Note
inlineformset_factory usa modelformset_factory e marca
can_delete=True.
Mais de uma chave estrangeira para o mesmo model¶
Se o seu model contém mais de uma chave estrangeira para o mesmo model, você
precisará resolver a ambiguidade manualmente utilizando fk_name. Por
exemplo, considere o seguinte model:
class Friendship(models.Model):
from_friend = models.ForeignKey(Friend)
to_friend = models.ForeignKey(Friend)
length_in_months = models.IntegerField()
Para resolver isto, você pode usar fk_name para inlineformset_factory:
>>> FriendshipFormSet = inlineformset_factory(Friend, Friendship, fk_name="from_friend")
Usando um formset em linha em um view¶
Você pode querer prover um view que permite um usuário editar os objetos relacionados de um model. Aqui tem uma maneira de se fazer isso:
def manage_books(request, author_id):
author = Author.objects.get(pk=author_id)
BookInlineFormSet = inlineformset_factory(Author, Book)
if request.method == "POST":
formset = BookInlineFormSet(request.POST, request.FILES, instance=author)
if formset.is_valid():
formset.save()
# Do something.
else:
formset = BookInlineFormSet(instance=author)
return render_to_response("manage_books.html", {
"formset": formset,
})
Observe como passamos instance em ambos os casos POST e GET.