Как присвоить атрибуту несколько строковых значений в моделях Django
class Customer(models.Model):
user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE,
related_name="Customer", limit_choices_to={'is_staff': False})
employee = models.ForeignKey(
Employee, null=True, blank=True, on_delete=models.SET_NULL)
# locations = What should go here?
business_name = models.CharField(max_length=200, null=True, blank=True)
phone_no = models.CharField(max_length=200, null=True, blank=True)
address = models.CharField(max_length=500, null=True, blank=True)
website_url = models.URLField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Как вы можете видеть здесь, у меня есть поле locations. Это поле должно хранить не более 5 мест, в которых расположен бизнес. Как мне лучше всего этого добиться?
Я читал об использовании поля Many2Many, но это нежелательно, поскольку местоположения должны быть сначала созданы в администраторе, а затем добавлены в бизнес.
Я не понимаю, почему местоположения должны быть сначала добавлены в панели администратора. ManyToManyField действительно является подходящим способом.
class Location(models.Model):
location = models.CharField(max_length=200)
class Customer(models.Model):
user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE,
related_name="Customer", limit_choices_to={'is_staff': False})
employee = models.ForeignKey(
Employee, null=True, blank=True, on_delete=models.SET_NULL)
locations = models.ManyToManyField(Location)
business_name = models.CharField(max_length=200, null=True, blank=True)
phone_no = models.CharField(max_length=200, null=True, blank=True)
address = models.CharField(max_length=500, null=True, blank=True)
website_url = models.URLField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Затем вы можете добавить местоположения к клиенту в вашем представлении:
def home(request):
# First create the customer
customer = Customer.objects.create_user(user=request.user)
# Then get the locations
# I'm assuming you'll get this from a form post request
locations = request.POST.getlist('locations')
for location in locations:
Location.objects.create(location=location)
customer.add(location)
Посмотрите docs для получения дополнительной информации.
Если вы не хотите ManyToManyField, вы можете наложить синтаксис на то, что является допустимым местоположением, и хранить местоположения в одном поле CharField с некоторым символом-разделителем. Вы можете использовать validators, чтобы убедиться, что все остается в порядке. Если вы используете PostgreSQL в качестве БД, вы можете сделать местоположение в JSONField или ArrayField, но если вы не можете сделать это, не так уж сложно использовать простое CharField
MAX_LOCATIONS = 5
LOCATIONS_SEPARATOR = '||'
MAX_LOCATION_LENGTH = 200
locations = models.CharField( max_length= MAX_LOCATIONS*(MAX_LOCATION_LENGTH + len(LOCATIONS_SEPARATOR) ),
validators = [LocationsValidator, ],
...
)
...
def LocationsValidator( value):
if len( value.split( LOCATION_SEPARATOR )) > MAX_LOCATIONS
raise ValidationError(
f'Location value represents more than maximum {MAX_LOCATIONS} locations'
)
Используйте методы Python string .split и .join для преобразования из одной строки расположения и списка до 5 значений расположения. Не забывайте проверять значения местоположения в формах
valid = ( len( location) <= Customer.MAX_LOCATION_LENGTH and
Customer.LOCATIONS_SEPARATOR not in location )
ManyToMany принесет дивиденды, если вы когда-нибудь захотите начать связывать другие данные со значениями местоположения. Поэтому лично я бы не рекомендовал использовать вышеописанное в любых обычных обстоятельствах.