mdcg
mdcg

Reputation: 65

Multiple models validation in the same View - Django 1.11

I'm looking for a strategy to validate the uniqueness of the keys of four models that have relationships with each other before finally being able to save them in the database.

In other words, I would like to check the uniqueness of the keys so that there is no inconsistency in the database when using the Model.save() method, and only use it when all the unique keys are really unique.

Following the view below as an example, the fields cnpj, address, and number respectively in LegalPerson, Email and Phone, must be unique.

class StoreRegistrationView(View):
    '''
    Classe responsavel pelo cadastro de lojas
    '''
    def post(self, request):

        if request.method == 'POST':
            #import pdb; pdb.set_trace()
            form = StoreForm(request.POST)

            if form.is_valid():

                lp = LegalPerson(
                    cnpj = form.cleaned_data['cnpj'],
                    corporate_name = form.cleaned_data['corporate_name'],
                    fantasy_name = form.cleaned_data['fantasy_name'],
                    state_inscription = form.cleaned_data['state_inscription'],
                    municipal_inscription = form.cleaned_data['municipal_inscription'],
                    )

                lp.save()

                address = Address(
                    street = form.cleaned_data['street'],
                    neighborhood = form.cleaned_data['neighborhood'],
                    number = form.cleaned_data['number'],
                    complement = form.cleaned_data['complement'],
                    city = form.cleaned_data['city'],
                    estate = form.cleaned_data['estate'],
                    country = 'Brasil',
                    cep = form.cleaned_data['cep'],
                    latitude = form.cleaned_data['latitude'],
                    longitude = form.cleaned_data['longitude'],
                    person = lp,
                    )

                address.save()

                email = Email(
                    address = form.cleaned_data['email'],
                    person=lp,
                    )

                email.save()

                phone = Phone(
                    number=form.cleaned_data['phone_number'],
                    person=lp,
                    )

                phone.save()

                # Mensagem de sucesso que será disponibilizada para o usuário
                messages.success(request, 'Cadastro de loja efetuado com sucesso.')

                return redirect('importar-produtos')

        messages.warning(request, 'Erro durante o cadastro.')
        context = {
            'store_form': StoreForm(),
                }

        return render(request, 'n3oadmin/store-registration.html', context)

I've been researching, and found that models in django have some validating methods like Model.full_clean(), Model.clean(), and Model.validate_unique().

Upvotes: 0

Views: 805

Answers (2)

Alasdair
Alasdair

Reputation: 308949

Instead of using a regular form, you should create multiple model forms.

class LegalPersonForm(forms.ModelForm):
    class Meta:
        model = LegalPerson
        fields = [...]

class = AddressForm(forms.ModelForm):
    class Meta:
        model = LegalPerson
        exclude = ['person']

Then, use your model forms in your view and template. The model forms will take care of validating unique constraints.

if request.method == 'POST':
    address_form = AddressForm(request.POST)
    legal_person_form = LegalPersonForm(request.POST)

    if address_form.is_valid() and legal_person_form.is_valid():
        person = legal_person_form.save()
        address = address_form.save(commit=False)
        address.person = person
        address.save()

        ...

        return redirect('importar-produtos')
else:
    address_form = AddressForm()
    legal_person_form = LegalPersonForm()

context = {
    'address_form': address_form,
    'legal_person_form': legal_person_form,
}
return render(request, 'n3oadmin/store-registration.html', context)

Note you can exclude foreign key fields in the model form. Then, in the view, you can save with commit=False, set the foreign key, then save the instance.

Note also that we have only instantiated blank forms AddressForm() and LegalPersonForm in the else block (for GET requests). This means that if the form is valid, you get to see the form errors in the template instead of a blank form.

Upvotes: 3

Sayok88
Sayok88

Reputation: 2108

You can refer to this here to set a unique field.

https://docs.djangoproject.com/en/1.11/ref/models/fields/#unique

Upvotes: 0

Related Questions