Свяжите детали транзакции с продуктом
Я пытаюсь связать несколько моделей вместе, чтобы показать, какой продукт держит пользователь, а также цену, которую он заплатил, и сумму, которую он держит. Которые будут отображаться в таблице.
У меня есть модели Profile Product, Holding, и я хочу добавить модель Transaction, которая связана с моделью Profile, и Holding, чтобы можно было добавить количество купленного и цену.
Я не уверен, какой лучший способ связать эти модели, чтобы можно было легко представить данные в таблице.
Модели:
class Product(models.Model):
product_name = models.CharField(max_length=255, blank=False, unique=True)
product_slug = models.CharField(max_length=50, blank=True,null=True)
product_symbol = models.CharField(max_length=50, blank=True,null=True)
product_price = models.FloatField(blank=True,null=True)
product_capture_date = models.DateField(blank=True,null=True)
product_logo_address = models.URLField(max_length=255, blank=True)
def __str__(self):
return str(self.product_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)
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):
product_name = 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.FloatField(max_length=50, 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)
Я создал модель транзакций и связал ее с FK с холдингом и профилем - похоже, это работает для распределения данных в модели и позволяет мне добавить несколько транзакций к продукту для профиля.
Но я думаю, что есть лучший способ работы в представлении, учитывая, что продукт может иметь несколько назначенных транзакций, и не будут ли все транзакции перечислять только общую сумму и среднюю цену.
profile = Profile.objects.get(user = request.user)
transact = Transaction.objects.filter(profile = profile)
Итак, в моей таблице я хочу показать product_name, transaction.price и product_holding.
Выглядит хорошо, за исключением того, что вам не нужно поле profile на Transaction, потому что оно уже есть на product/Holding товаре. Также не понятно, зачем нужно ManyToMany на Profile с product.
Так что я бы рефакторизовал это следующим образом (см. комментарии в строке):
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)
И фильтрация:
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
Если вы хотите узнать продукты конкретного пользователя (с тех пор как мы убрали ManyToMany):
products = [x.product for x in Holding.objects.filter(profile=profile)]
Или если конкретный пользователь держит конкретный продукт:
product = Product.objects.get(name='specific_product')
exists = Holding.objects.filter(profile=profile, product=product).exists()