Ввод данных в Django с помощью отношений, какой способ является стандартным или наиболее эффективным?

В случае модели без отношений the, наиболее эффективным способом ввода данных будет использование django.forms.ModelForm. Возьмем следующий пример:

class Customer(models.Model):

    first_name = models.CharField(max_length=120)
    last_name = models.CharField(max_length=120)

    def __str__(self):
        return f"{self.first_name} {self.last_name}"


class CustomerModelForm(forms.ModelForm):

    class Meta:
        fields = ("first_name", "last_name")
        model = Customer


form = CustomerModelForm(data={"first_name": "Jon", "last_name": "Doe"})
if form.is_valid():
    form.save()

Но когда вы добавляете отношения, что является наиболее эффективным или лучшим стандартом. Давайте обновим модель до:

class Customer(models.Model):

    first_name = models.CharField(max_length=120)
    last_name = models.CharField(max_length=120)
    address = models.ForeignKey(
        "Address",
        on_delete=models.PROTECT
    )

    def __str__(self):
        return f"{self.first_name} {self.last_name}"


class Address(models.Model):

    street = models.CharField(max_length=120)
    city = models.CharField(max_length=120)
    state = models.CharField(max_length=2)
    zip_code = models.CharField(max_length=5)

    def __str__(self):
        return f"{self.street}, {self.city}, {self.state}  {self.zip_code}"

Одним из решений может быть следующее:

class CustomerModelForm(forms.ModelForm):

    class Meta:
        fields = ("first_name", "last_name", "address")
        model = Customer


class AddressModelForm(forms.ModelForm):

    class Meta:
        fields = (
            "street",
            "city",
            "state",
            "zip_code"
        )
        model = Address


class Customer(forms.Form):

    first_name = models.CharField(max_length=120)
    last_name = models.CharField(max_length=120)
    street = models.CharField(max_length=120)
    city = models.CharField(max_length=120)
    state = models.CharField(max_length=2)
    zip_code = models.CharField(max_length=5)

    def save(self):
        address_form = AddressModelForm(
            data={
                "street": "123 Sycamore St",
                "city": "Eagles Harbor",
                "state": "AD",
                "zip_code": "12345"
            }
        )
        if address_form.is_valid():
            address = address_form.save()
            customer_form = CustomerModelForm(
                data={"first_name": "Jon", "last_name": "Doe"}
            )
            if customer_form.is_valid():
                return customer_form.save()

Или же вы полностью пропустите модельные формы:

class Customer(forms.Form):

    ...

    def save(self):
        address, c = Address.objects.get_or_create(
            street="123 Sycamore St",
            city="Eagles Harbor",
            state="AD",
            zip_code="12345"
        )

        customer, c = Customer.objects.get_or_create(
            first_name="Jon",
            last_name="Doe",
            address=address,
        )

        return customer

Не уверен, что понимаю вас, но вижу, что вы делаете, я бы сделал это довольно просто:

class Customer(models.Model):
    first_name=..
    ...
    zip_code=..

class CustomerForm(forms.ModelForm):
    class Meta:
        fields = ('__ALL__')
        model = Customer

При использовании ORM помогает представить, что происходит на уровне базы данных. Не совсем понятно, зачем создавать целую новую таблицу только для адресов.

Edit: Вы все еще можете сделать это так, и иметь address = models.ForeignKey(Address) на вашей модели Customer. Я думаю, что вы превращаете довольно простую вещь в нечто более сложное, чем она есть на самом деле. Вы также жестко кодируете значения, в этом нет необходимости.

Вернуться на верх