I have this customer model where I want to introduce a user field where the user field is
user = models.OneToOneField(User, on_delete=models.CASCADE)
but there are already some objects in this model so if i create this one to one field then it would ask me for a default value for those objects but I cannot pass default values because it'll clash with the logic.
Old model:
class Customer(models.Model):
first_name = models.CharField(max_length=50, default=0)
last_name = models.CharField(max_length=50, default=0)
customer_display_name = models.CharField(max_length=50, default=0)
customer_name = models.CharField(max_length=50, default=0)
customer_phone = models.CharField(max_length=50, default=0)
customer_website = models.CharField(max_length=50, default=0)
customer_email = models.EmailField(max_length=250, default=0, blank=True, null=True)
shipping_address = models.ManyToManyField(CustomerShippingAddress)
billing_address = models.ManyToManyField(CustomerBillingAddress)
active = models.BooleanField(default=True)
remarks = models.CharField(max_length=500, default=0, blank=True, null=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
New model:
class Customer(models.Model):
first_name = models.CharField(max_length=50, default=0)
last_name = models.CharField(max_length=50, default=0)
customer_display_name = models.CharField(max_length=50, default=0)
customer_name = models.CharField(max_length=50, default=0)
customer_phone = models.CharField(max_length=50, default=0)
customer_website = models.CharField(max_length=50, default=0)
customer_email = models.EmailField(max_length=250, default=0, blank=True, null=True)
shipping_address = models.ManyToManyField(CustomerShippingAddress)
billing_address = models.ManyToManyField(CustomerBillingAddress)
active = models.BooleanField(default=True)
remarks = models.CharField(max_length=500, default=0, blank=True, null=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE) #Change1
user = models.OneToOneField(User, on_delete=models.CASCADE) #Change2
company = models.ForeignKey(Company, on_delete=models.CASCADE) #Change3
Reason
owner - to track who created this Customer
user - to link the Customer to User model
company - to link the company to Customer, although this connection can be find through the user who created this company
is it the right way to approach?
Your logic is fine, however adding non-nullable fields with django is always a bit of a pain. Here is how I do it:
# models.py
class Customer(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE) # No changes
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True) # Nullable
company = models.ForeignKey(Company, on_delete=models.CASCADE, null=True, blank=True) # Nullable
python manage.py makemigrations your_user_app --empty
from django.db import migrations, models
def fill_user_company(apps, schema_editor):
Customer = apps.get_model('your_user_app', 'Customer')
User = apps.get_model('your_user_app', 'User')
for customer in Customer.objects.all():
customer.user = User.objects.get(email=customer.customer_email) # Make your own match logic here
customer.company = customer.user.company
customer.save()
class Migration(migrations.Migration):
dependencies = [
('your_user_app', 'your_previous_migration_that_created_the_fields'),
]
operations = [
migrations.RunPython(fill_user_company),
migrations.AlterField(
model_name='customer',
name='user',
field=models.OneToOneField(
to='auth.User',
on_delete=models.CASCADE,
),
),
migrations.AlterField(
model_name='customer',
name='company',
field=models.ForeignKey(
to='your_company_app.Company',
on_delete=models.CASCADE,
),
),
]
# models.py
class Customer(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE) # No changes
user = models.OneToOneField(User, on_delete=models.CASCADE) # Non-nullable
company = models.ForeignKey(Company, on_delete=models.CASCADE) # Non-nullable
Finally you can apply your migrations, and your new fields will be automatically created and populated.
Note that you can merge your 2 migrations file in a single one if you prefer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With