Ivan Semochkin
Ivan Semochkin

Reputation: 8897

Save related models in one query

Hi I have two related models, I need to save it depends on json data from Angular.
Here is models:

Class Company(models.Model):
    name = models.CharField(
        max_length=255, )

class ContactPerson(models.Model):
    company = models.ForeignKey(
        Company,
        related_name='contact_persons', )
    name = models.CharField(
        max_length=255, )

Here is part of view:

class CompanyCreate(JsonView):
    #JsonView write by me, contains some methods
    def post(self, *args, **kwargs):
        data = json.loads(self.request.body)
        company = CompanyForm(data=data['company'])
        contacts = ContactForm(data=data['contacts'])
    if company.is_valid():
            company.save()
            if contacts.is_valid():
                contacts.save(commit=False)
                contacts.company = company
                contacts.save()
    return HttpResponse()

Company is saving, but I cant valid contacts form, because I cant get company.id from first form.

Upvotes: 1

Views: 2002

Answers (1)

Shang Wang
Shang Wang

Reputation: 25539

I don't think you could save them at once because:

  1. They are instances that has foreign key relationships, so one wouldn't exist before the other.

  2. They are 3 different model instances so it doesn't make sense to combine them in one form.

If you just want to save the ones that are valid and reject the ones that are invalid, what you currently do is enough with one change, capturing the return value of save() function:

class CompanyCreate(JsonView):
    #JsonView write by me, contains some methods

    def post(self, *args, **kwargs):
        data = json.loads(self.request.body)
        company_form = CompanyForm(data=data['company'])
        contacts_form = ContactForm(data=data['contacts'])
    if company_form.is_valid():
            company = company_form.save()
            if contacts.is_valid():
                contacts = contacts_form.save(commit=False)
                contacts.company = company
                contacts.save()
    return HttpResponse()

If you want "all or none" logic, meaning you either save everything if everything is valid, otherwise don't save anything, you should exclude the foreign key on each ModelForm, so that when you valid the forms, they ignore the validation of existence of ForeignKey but not all other fields. See if that makes sense.

Upvotes: 2

Related Questions