1

In the example shown by the code below, is it possible to automatically validate and create instances of Endereco and Coordenada using LocalizacaoForm?

The reason why I want to do this is so that I can use Generic Views as much as possible, and they don't work well (at least not out-of-the-box) with more than one ModelForm per view.

In the application, I want to render a LocalizacaoForm and show the fields from Endereco and Coordenada as well. What I am doing in so far doesn't seem to solve it, because self.fields.update(fields_for_model(Coordenada)) only creates the input fields, not an actual instance of Coordenada. Therefore I get a django NOT NULL constraint failed id for the object coordenada.

Is there a way to do what I want or should I just stick with rendering each form separately?

#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'

1 Answer 1

2

You can create instances of Coordenada and Endereco in the save() method of LocalizacaoForm, like this:

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
Sign up to request clarification or add additional context in comments.

1 Comment

Works like a charm and looks much cleaner than if I had created the each form separately. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.