Link transaction details with Product

Looks good except that you don’t need profile field on Transaction because it’s already on product/Holding item. As well as not clear why need to have ManyToMany on Profile with product.

So I would refactor that as follows (see comments inline):

class Product(models.Model):
    # no need to say 'product_name' because it is on model Product
    name = models.CharField(max_length=255, blank=False, unique=True)
    slug = models.CharField(max_length=50, blank=True,null=True)
    symbol = models.CharField(max_length=50, blank=True,null=True)
    
    # Float does not suite price due to its low precision. Use Decimal instrad
    price = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
    capture_date = models.DateField(blank=True,null=True)
    logo_address = models.URLField(max_length=255, blank=True)

    def __str__(self):
        return self.name

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField(max_length=500, blank=True)
    location = models.CharField(max_length=30, blank=True)
    birth_date = models.DateField(null=True, blank=True)

    # no need of products here - can be find via Holding
    # products = models.ManyToManyField(Product, blank=True, through='Holding')
    website = models.URLField(max_length=50, blank=True)
    twitter = models.CharField(max_length=50, blank=True)
    meta = models.CharField(max_length=50, blank=True)
    github = models.CharField(max_length=50, blank=True)

    def __str__(self):
        return str(self.user)

class Holding(models.Model):
    # the field is not product_name - it is actually `product` itself
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
    product_holding = models.FloatField(max_length=50, blank=True, null=True)

    def __str__(self):
        return str(self.product_name)

class Transaction(models.Model):

    product = models.ForeignKey(Holding, on_delete=models.CASCADE)
    amount = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
    price = models.FloatField(max_length=50, blank=True, null=True)
    transaction_date = models.DateField(null=True, blank=True)
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE)

And filtering:

profile = Profile.objects.get(user = request.user)

transactions = Transaction.objects.filter(
    holding__in=Holding.objects.filter(profile=profile)
)

for t in transactions:
    product_name = t.holding.product.product_name
    price = t.price
    product_holding = t.holding.product_holding

If you want to know the products of a specific user (since we removed ManyToMany):

products = [x.product for x in Holding.objects.filter(profile=profile)]

Or if a specific user hold specific product:

product = Product.objects.get(name='specific_product')
exists = Holding.objects.filter(profile=profile, product=product).exists()

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top