通过 Django ModelForm 中的外键字段验证多个相关对象
Validate multiple related objects through foreign key field in Django ModelForm
在下面代码所示的示例中,是否可以使用 LocalizacaoForm
自动验证和创建 Endereco
和 Coordenada
的实例?
我之所以要这样做是为了尽可能多地使用通用视图,并且它们不能很好地(至少不是开箱即用的)使用多个 ModelForm每次观看。
在应用程序中,我想呈现一个 LocalizacaoForm
并显示来自 Endereco
和 Coordenada
的字段。到目前为止我所做的似乎并没有解决它,因为 self.fields.update(fields_for_model(Coordenada))
只创建输入字段,而不是 Coordenada
的实际实例。因此,我得到对象 coordenada.
的 django NOT NULL constraint failed id
有没有办法做我想做的事,或者我应该坚持单独渲染每个表单?
#models.py
class Coordenada(models.Model):
latitude = models.FloatField()
longitude = models.FloatField()
altitude = models.FloatField()
erro_horizontal = models.FloatField()
class Endereco(models.Model):
cep = models.IntegerField()
uf = models.CharField(max_length=2)
localidade = models.CharField(max_length=50) # nome da cidade
# other fields...
class Localizacao(models.Model):
endereco = models.OneToOneField(Endereco)
coordenada_geografica = models.ForeignKey('Coordenada')
#forms.py
class LocalizacaoForm(forms.ModelForm):
def __init__(self, instance=None, *args, **kwargs):
super(LocalizacaoForm, self).__init__(instance=instance, *args, **kwargs)
# Retrieve the fields from Endereco and Coordenada model and update the fields with it
self.fields.update(fields_for_model(Endereco))
self.fields.update(fields_for_model(Coordenada))
class Meta:
model = Localizacao
exclude = ('endereco', 'coordenada_geografica')
#views.py
class LocalizacaoCreateView(generic.CreateView):
model = Localizacao
form_class = LocalizacaoForm
template_name = 'localizacao_create_form.html'
您可以在 LocalizacaoForm
的 save()
方法中创建 Coordenada
和 Endereco
的实例,如下所示:
class LocalizacaoForm(forms.ModelForm):
# The rest of the form ...
# ...
def save(self, commit=False):
localizacao = super(LocalizacaoForm, self).save(commit=False)
# create an instance of Coordenada
coordenada = Coordenada.objects.create(
latitude=self.cleaned_data['latitude'],
longitude=self.cleaned_data['longitude'],
altitude=self.cleaned_data['altitude'],
erro_horizontal=self.cleaned_data['erro_horizontal']
)
# create an instance of Endereco
endereco = Endereco.objects.create(
cep=self.cleaned_data['cep'],
uf=self.cleaned_data['uf'],
localidade=self.cleaned_data['localidade'],
)
# add those instances to localizacao
localizacao.coordenada_geografica = coordenada
localizacao.endereco = endereco
if commit:
localizacao.save()
return localizacao
在下面代码所示的示例中,是否可以使用 LocalizacaoForm
自动验证和创建 Endereco
和 Coordenada
的实例?
我之所以要这样做是为了尽可能多地使用通用视图,并且它们不能很好地(至少不是开箱即用的)使用多个 ModelForm每次观看。
在应用程序中,我想呈现一个 LocalizacaoForm
并显示来自 Endereco
和 Coordenada
的字段。到目前为止我所做的似乎并没有解决它,因为 self.fields.update(fields_for_model(Coordenada))
只创建输入字段,而不是 Coordenada
的实际实例。因此,我得到对象 coordenada.
django NOT NULL constraint failed id
有没有办法做我想做的事,或者我应该坚持单独渲染每个表单?
#models.py
class Coordenada(models.Model):
latitude = models.FloatField()
longitude = models.FloatField()
altitude = models.FloatField()
erro_horizontal = models.FloatField()
class Endereco(models.Model):
cep = models.IntegerField()
uf = models.CharField(max_length=2)
localidade = models.CharField(max_length=50) # nome da cidade
# other fields...
class Localizacao(models.Model):
endereco = models.OneToOneField(Endereco)
coordenada_geografica = models.ForeignKey('Coordenada')
#forms.py
class LocalizacaoForm(forms.ModelForm):
def __init__(self, instance=None, *args, **kwargs):
super(LocalizacaoForm, self).__init__(instance=instance, *args, **kwargs)
# Retrieve the fields from Endereco and Coordenada model and update the fields with it
self.fields.update(fields_for_model(Endereco))
self.fields.update(fields_for_model(Coordenada))
class Meta:
model = Localizacao
exclude = ('endereco', 'coordenada_geografica')
#views.py
class LocalizacaoCreateView(generic.CreateView):
model = Localizacao
form_class = LocalizacaoForm
template_name = 'localizacao_create_form.html'
您可以在 LocalizacaoForm
的 save()
方法中创建 Coordenada
和 Endereco
的实例,如下所示:
class LocalizacaoForm(forms.ModelForm):
# The rest of the form ...
# ...
def save(self, commit=False):
localizacao = super(LocalizacaoForm, self).save(commit=False)
# create an instance of Coordenada
coordenada = Coordenada.objects.create(
latitude=self.cleaned_data['latitude'],
longitude=self.cleaned_data['longitude'],
altitude=self.cleaned_data['altitude'],
erro_horizontal=self.cleaned_data['erro_horizontal']
)
# create an instance of Endereco
endereco = Endereco.objects.create(
cep=self.cleaned_data['cep'],
uf=self.cleaned_data['uf'],
localidade=self.cleaned_data['localidade'],
)
# add those instances to localizacao
localizacao.coordenada_geografica = coordenada
localizacao.endereco = endereco
if commit:
localizacao.save()
return localizacao