I’m working on an e-commerce app using Django. I’ve got two models: Shopper
and Purchase
. I want to keep the Shopper
’s info when they make a Purchase
, but also let them delete their account if they want to.
Right now, my Purchase
model looks like this:
class Purchase(models.Model):
buyer_email = models.EmailField()
buyer_first_name = models.CharField(max_length=50)
buyer_last_name = models.CharField(max_length=50)
buyer = models.ForeignKey(Shopper, on_delete=models.SET_NULL)
def prepare_data(self):
if not self.buyer_first_name:
self.buyer_first_name = self.buyer.first_name
if not self.buyer_last_name:
self.buyer_last_name = self.buyer.last_name
if not self.buyer_email:
self.buyer_email = self.buyer.email
def save(self, *args, **kwargs):
self.prepare_data()
super().save(*args, **kwargs)
This feels like I’m repeating myself a lot. Is there a better way to do this without copying fields from the Shopper
model? Or do I just have to deal with the duplication? Any ideas would be great!
hey sophie, maybe try using a separate model for storing historical data? when a shopper deletes their account, copy their info to this model and link it to the purchase. This way u keep the purchase data without duplicating fields in the Purchase model. it’s a bit more work upfront but could save you headaches later on!
I’ve faced a similar issue in my Django projects. Instead of duplicating fields, consider using a soft delete approach for your Shopper model. Add an ‘is_active’ boolean field to Shopper and override the delete method to set it to False instead of actually deleting the record. This way, you maintain the integrity of your Purchase data while allowing users to ‘delete’ their accounts.
For the Purchase model, you can simplify it by relying on the ForeignKey relationship:
class Purchase(models.Model):
buyer = models.ForeignKey(Shopper, on_delete=models.SET_NULL, null=True)
@property
def buyer_email(self):
return self.buyer.email if self.buyer else None
@property
def buyer_full_name(self):
return f'{self.buyer.first_name} {self.buyer.last_name}' if self.buyer else None
This approach eliminates field duplication and simplifies your code while preserving all necessary data.
Hey Sophie26! Your question’s got me thinking about some cool ways to handle this. Have you considered using a custom manager for your Shopper model? It could be a neat solution!
Here’s an idea: create a custom manager that handles ‘deleting’ a shopper by anonymizing their data instead of actually removing it. Something like this:
class ShopperManager(models.Manager):
def delete(self, *args, **kwargs):
self.update(
first_name='Deleted',
last_name='User',
email=f'deleted_{uuid.uuid4()}@example.com'
)
class Shopper(models.Model):
# Your existing fields here
objects = ShopperManager()
This way, when a shopper ‘deletes’ their account, you’re just updating their info to anonymous data. Your Purchase model can stay as is, keeping the link to the Shopper without duplicating fields.
What do you think about this approach? It might solve your problem without adding too much complexity. Have you tried anything similar before?