Лучшие практики создания нескольких связанных объектов в Django

Я работаю с моделью домена Party из книги "Ресурс моделей данных". Для примера ниже приведена упрощенная версия моделей.

Когда, например, организация является клиентом. Я бы создал комбинацию моделей (Party, Organization, Role(type=customer), Customer).

Это относительно простая задача. однако куда обычно направлена эта логика.

1- Простая функция from module import create_organization_customer.

  • This method is relatively popular for advocates of the service pattern. Though it doesn't feel Django like.

2- Inside a Form ModelForm.save() or Form.create().

  • I like this but then adding rest_framework. would have me copy the logic to the Serializer.create(). etc..

3- Inside a Manager Customer.objects.create() or customer.objects.create_customer().

  • This one is clean and feels more like how Django do things. though, I'm not sure how to feel about it when it spans beyond the Queryset boundaries.

4- Переопределите сохранение на модели Customer.save().

  • I think this is a popular solution. though I'm not sure its the cleanest.
class Party(models.Model):
    party_id = models.CharField(max_length=100, unique=True)

class Person(models.Model):
    party = models.OnetoOneField(Party, related_name="person", primary_key=True, on_delete=models.CASCADE)
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)


class Organization(models.Model):
    party = models.OnetoOneField(Party, related_name="organization", primary_key=True, on_delete=models.CASCADE)
    legal_name = models.CharField(max_length=255)


class Role(models.Model):

    class TypeChoices(models.TextChoices):
        CUSTOMER = 'customer', 'Customer'
        VENDOR = 'vendor', 'Vendor'
        PARTNER = 'partner', 'Partner'
    
    type = models.CharField(max_length=100, choices=TypeChocies.choices)
    party = models.ForeignKey(Party, related_name="roles", primary_key=True, on_delete=models.CASCADE)
    

class Customer(models.Model):
    role = models.OnetoOneField(Role, related_name="customer", primary_key=True,  on_delete=models.CASCADE)
    party = models.OneToOneField(Party, related_name="customer", on_delete=models.CASCADE)
    credit_limit = models.DecimalField(max_digits=12, decimal_places=2)


class Vendor(models.Model):
    role = models.OnetoOneField(Role, related_name="vendor", primary_key=True, on_delete=models.CASCADE)
    party = models.OneToOneField(Party, related_name="vendor", on_delete=models.CASCADE)
    account_number = models.CharField(max_length=70)


class Partner(models.Model):
    role = models.OnetoOneField(Role, related_name="partner", primary_key=True, on_delete=models.CASCADE)
    party = models.OneToOneField(Party, related_name="partner", on_delete=models.CASCADE)
    license_number = models.CharField(max_length=50)
Вернуться на верх