我在Django安装中创建了一个应用程序"customerbin"。我需要创建/编辑/删除可以有多个地址的客户,其中只有一个地址可以是主要地址。如果一个客户被删除,那么属于该客户的所有地址也需要被删除。如果创建了新客户,我们就无法从其他客户那里挑选地址。
型号.py:
from django.db import models
class Address(models.Model):
street = models.CharField(max_length=100)
number = models.IntegerField(null=True)
postal = models.IntegerField(null=True)
city = models.CharField(max_length=100)
country = models.CharField(max_length=100)
is_primary = models.BooleanField(null=False)
geo_lat = models.DecimalField(max_digits=22, decimal_places=16, blank=True, null=True)
geo_lon = models.DecimalField(max_digits=22, decimal_places=16, blank=True, null=True)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
class Customer(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
vat = models.CharField(max_length=100)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
address = models.ForeignKey(Address, on_delete=models.CASCADE)
admin.py:
from django.contrib import admin
from . import models
# Register your models here.
admin.site.register(models.Customer)
admin.site.register(models.Address)
我如何才能做到:
- 一个地址只链接到一个客户
- 删除客户时删除所有地址
- 只有一个地址是客户的主要地址
您应该有一个从Address
到Customer
的外键,而不是从Customer
到Address
的外键。为了确保用户只存在一个主地址,请使用带有condition
:的UniqueConstraint
[Django-docs]
from django.db.models import Q
class Address(models.Model):
street = models.CharField(max_length=100)
number = models.IntegerField(null=True)
postal = models.IntegerField(null=True)
city = models.CharField(max_length=100)
country = models.CharField(max_length=100)
is_primary = models.BooleanField(null=False)
geo_lat = models.DecimalField(max_digits=22, decimal_places=16, blank=True, null=True)
geo_lon = models.DecimalField(max_digits=22, decimal_places=16, blank=True, null=True)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
# Here ↓
customer = models.ForeignKey("Customer", on_delete=models.CASCADE, related_name="addresses")
def save(self, *args, **kwargs):
if self.is_primary:
self.__class__._default_manager.filter(customer=self.customer, is_primary=True).update(is_primary=False)
super().save(*args, **kwargs)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['customer'],
condition=Q(is_primary=True),
name='unique_primary_per_customer'
)
]
class Customer(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
vat = models.CharField(max_length=100)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
# Remove address from here
这里,如果相关客户被删除,on_delete=models.CASCADE
将导致地址被删除。
首先,您错误地链接了这两个模型。根据上面的代码,当相应的地址被删除时,用户就会被删除,这不是你想要的。所以,这是我的建议。将Address
模型中的外键添加到具有on_delete=models.CASCADE
的Customer
模型中,还将具有默认值的Address
模型中的布尔字段is_primary
添加到False
。在Address
模型的clean
方法中,您可以只处理一个主地址的逻辑,在该方法中,可以检查是否已经有要添加地址的用户的主地址。如果是,则创建一个验证错误。如果没有,请照常进行。如果这个解释还不够,我也可以帮助你编写代码。