Retaining customer info after account deletion in Django e-commerce setup

Help with Django e-commerce models

I’m working on an online store using Django. I’ve got two main models: Buyer and Purchase. I want to keep the Buyer’s info when there’s a sale, even if they delete their account later. But I’m not sure how to do this without copying all the Buyer fields into the Purchase model.

Here’s what I’ve tried:

from django.contrib.auth import get_user_model
from django.db import models

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(get_user_model(), null=True, on_delete=models.SET_NULL)

    def before_save(self):
        if self.buyer:
            self.buyer_email = self.buyer.email
            self.buyer_first_name = self.buyer.first_name
            self.buyer_last_name = self.buyer.last_name

    def save(self, *args, **kwargs):
        self.before_save()
        super().save(*args, **kwargs)

This works, but it feels like I’m repeating myself. Is there a better way to keep buyer info without duplicating fields? Or is this just how it has to be done? Any tips would be great!

hey sky_dreamer, i’ve dealt with this before. one trick is to use a JSONField in ur Purchase model to store buyer info. it’s flexible and keeps everything in one place. like this:

class Purchase(models.Model):
    buyer_info = models.JSONField(default=dict)
    buyer = models.ForeignKey(get_user_model(), null=True, on_delete=models.SET_NULL)

then u can just dump the buyer data into buyer_info when saving. no need for seperate fields. whatcha think?

I’ve encountered this dilemma in my e-commerce projects. One effective approach is to utilize a custom Manager for your Purchase model. This allows you to encapsulate the logic for saving buyer information without cluttering your model.

Here’s a potential implementation:

class PurchaseManager(models.Manager):
    def create_with_buyer(self, buyer, **kwargs):
        purchase = self.model(**kwargs)
        purchase.buyer = buyer
        purchase.buyer_email = buyer.email
        purchase.buyer_first_name = buyer.first_name
        purchase.buyer_last_name = buyer.last_name
        purchase.save()
        return purchase

class Purchase(models.Model):
    # Your existing fields here
    objects = PurchaseManager()

This method keeps your model clean while providing a convenient way to create purchases with buyer information. It’s a balance between flexibility and data integrity that has served me well in similar scenarios.

Hey Sky_Dreamer! That’s an interesting challenge you’ve got there. I’ve been tinkering with Django for a while, and I’ve run into similar issues before.

Have you considered using a separate BuyerInfo model? Something like this might work:

class BuyerInfo(models.Model):
    email = models.EmailField()
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)

class Purchase(models.Model):
    buyer_info = models.ForeignKey(BuyerInfo, on_delete=models.PROTECT)
    buyer = models.ForeignKey(get_user_model(), null=True, on_delete=models.SET_NULL)

This way, you’re not duplicating fields, and you can keep the buyer info even if the user account is deleted. What do you think about this approach?

Also, I’m curious - how are you handling situations where a buyer makes multiple purchases? Are you storing any aggregated data about their buying history?