Home > Mobile >  How can you assign multiple string values to an attribute in Django models
How can you assign multiple string values to an attribute in Django models

Time:02-23

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)

As you can see here, I have a locations field which. This field is to store at most 5 locations the business is located in. How can I best achieve this?

I have read about using a Many2Many field but this would not be desirable as the locations would have to be first created in the Admin and then added to the business.

CodePudding user response:

I don't see why the locations would have to be added in the Admin panel first. ManyToManyField is indeed the way to go.

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)

Then you can add locations to the Customer in your view:

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)

Check out the docs for more information.

CodePudding user response:

Ifyou don't want ManyToManyField you could impose a bit of syntax on what is a valid Location, and store the locations in a single CharField with some separator character. You would use validators to make sure that things stay sane. If you are using PostgreSQL as your DB, you could make the locations into a JSONField or an ArrayField, but if you can't do that it's not too hard to use a plain 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'
    )

Use the Python string .split and .join methods to convert from a single location string and a list of up to 5 location values. Remember to validate location values in forms

valid = ( len( location) <= Customer.MAX_LOCATION_LENGTH and 
    Customer.LOCATIONS_SEPARATOR not in location )

ManyToMany will pay dividends should you ever wish to start associating other data with location values. Therefore, personally, I would not recommend the above in any common circumstance.

  • Related