只返回一个选项列表,如果它们存在于两个Django模型中。

huangapple go评论93阅读模式
英文:

Return a list of options only if they exist in two Django Models

问题

我在models.py文件中有两个模型:

口味模型(Flavour model):

  1. class Flavour(models.Model):
  2. flavour_choice = models.CharField(null=True, blank=True, max_length=254)
  3. def __str__(self):
  4. return self.flavour_choice

和产品模型(Product model):

  1. class Product(models.Model):
  2. category = models.ForeignKey(
  3. 'Category', null=True, blank=True, on_delete=models.SET_NULL
  4. )
  5. slug = models.SlugField()
  6. sku = models.CharField(max_length=254, null=True, blank=True)
  7. name = models.CharField(max_length=254)
  8. brand = models.TextField()
  9. has_flavours = models.BooleanField(default=False, null=True, blank=True)
  10. flavours = models.ForeignKey(
  11. 'Flavour', null=True, blank=True, on_delete=models.SET_NULL
  12. )
  13. has_strength = models.BooleanField(default=False, null=True, blank=True)
  14. strength = models.ForeignKey(
  15. 'Strength', null=True, blank=True, on_delete=models.SET_NULL
  16. )
  17. description = models.TextField()
  18. price = models.DecimalField(max_digits=6, decimal_places=2)
  19. rating = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True)
  20. image_url = models.URLField(max_length=1024, null=True, blank=True)
  21. image = models.ImageField(null=True, blank=True)
  22. display_home = models.BooleanField(blank=True)
  23. created_at = models.DateTimeField(auto_now_add=True)
  24. class Meta:
  25. ordering = ('-created_at',)
  26. def __str__(self):
  27. return self.name

我想要能够将口味添加到口味表,并选择它们是否出现在特定的产品中。我应该如何做到这一点?我知道我可以将口味直接添加到产品中,但我希望许多产品具有相同的口味。

我需要能够在数据库层面完成这个操作,而不仅仅是在程序中进行操作,这样管理员用户可以通过前端产品管理页面添加口味和产品。

英文:

I have two models in my models.py file:

Flavour model:

  1. class Flavour(models.Model):
  2. flavour_choice = models.CharField(null=True, blank=True, max_length=254)
  3. def __str__(self):
  4. return self.flavour_choice

and Product model:

  1. class Product(models.Model):
  2. category = models.ForeignKey(
  3. 'Category', null=True, blank=True, on_delete=models.SET_NULL
  4. )
  5. slug = models.SlugField()
  6. sku = models.CharField(max_length=254, null=True, blank=True)
  7. name = models.CharField(max_length=254)
  8. brand = models.TextField()
  9. has_flavours = models.BooleanField(default=False, null=True, blank=True)
  10. flavours = models.ForeignKey(
  11. 'Flavour', null=True, blank=True, on_delete=models.SET_NULL
  12. )
  13. has_strength = models.BooleanField(default=False, null=True, blank=True)
  14. strength = models.ForeignKey(
  15. 'Strength', null=True, blank=True, on_delete=models.SET_NULL
  16. )
  17. description = models.TextField()
  18. price = models.DecimalField(max_digits=6, decimal_places=2)
  19. rating = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True)
  20. image_url = models.URLField(max_length=1024, null=True, blank=True)
  21. image = models.ImageField(null=True, blank=True)
  22. display_home = models.BooleanField(blank=True)
  23. created_at = models.DateTimeField(auto_now_add=True)
  24. class Meta:
  25. ordering = ('-created_at',)
  26. def __str__(self):
  27. return self.name

I want to able to add flavours to the flavours table and then choose if they appear for particular products. How would I go about this? I know I could just add the flavours to the product but so many of the products I want to have, have the same flavours.

I need to be able to do this database side and not just programmatically so admin users can add flavours and products via a front-end product management page.

答案1

得分: 0

你可以使用ManyToMany关系,其中许多口味可以用于许多不同的产品。
更多解释请参考这里:https://docs.djangoproject.com/en/4.1/topics/db/examples/many_to_many/

英文:

You can use a ManyToMany relationship, where many flavours can be used for many different products.
More explanation here : https://docs.djangoproject.com/en/4.1/topics/db/examples/many_to_many/

答案2

得分: 0

关于您的模型和字段,您可以在Flavour模型中使用model choices,但这不一定是必需的。您可以去掉has_flavourshas_strength字段,使用model property以及flavoursstrengths关系来获取所需的输出。

此外,如其他回答中提到的,将FlavourProduct之间的关系替换为多对多关系,以避免数据库中的重复记录。最后,image_url也是不必要的,因为您正在使用models.ImageField,可以通过属性例如instance.image.url来访问图像URL。

models.py

  1. class Product(models.Model):
  2. category = models.ForeignKey(
  3. 'Category', null=True, blank=True, on_delete=models.SET_NULL
  4. )
  5. slug = models.SlugField()
  6. sku = models.CharField(max_length=254, null=True, blank=True)
  7. name = models.CharField(max_length=254)
  8. brand = models.TextField()
  9. flavours = models.ManyToManyField('Flavour')
  10. strength = models.ForeignKey(
  11. 'Strength', null true, blank=true, on delete=models.SET NULL
  12. )
  13. description = models.TextField()
  14. price = models.DecimalField(max_digits=6, decimal_places=2)
  15. rating = models.DecimalField(max_digits=6, decimal_places=2, null=true, blank=true)
  16. image = models.ImageField(null=true, blank=true)
  17. display_home = models.BooleanField(blank=true)
  18. created_at = models.DateTimeField(auto_now_add=true)
  19. class Meta:
  20. ordering = ('-created_at',)
  21. def __str__(self):
  22. return self.name
  23. @property
  24. def has_flavours(self):
  25. return True if self.flavours.count() > 0 else False
  26. @property
  27. def has_strength(self):
  28. return True if self.strength.count() > 0 else False

一个简单的示例,演示如何将风味与特定产品关联起来:

tests.py

  1. class ProductTestCase(TestCase):
  2. def setUp(self):
  3. self.flv1 = Flavour.objects.create(flavour_choice='Flavour One')
  4. self.flv2 = Flavour.objects.create(flavour_choice='Flavour Three')
  5. self.product = Product.objects.create(
  6. slug='product-one', name='Product One',
  7. brand='Brand', description='Product Description',
  8. price=decimal.Decimal(100), display_home=True
  9. )
  10. self.another_product = Product.objects create(
  11. slug='another-product', name='Another Product',
  12. brand='Brand', description='Another Product Description',
  13. price=decimal.Decimal(100), display_home=True
  14. )
  15. def test_product_with_specific_flavour(self):
  16. self.product.flavours.add(self.flv1)
  17. self.product.flavours.add(self.flv2)
  18. self.another_product.flavours.add(self.flv2)
  19. queryset = Product.objects.filter(flavours=self.flv2)
  20. # queryset contains both products
  21. self.assertEqual(queryset.count(), 2)
  22. queryset = Product.objects.filter(flavours=self.flv1)
  23. # queryset contains only 'Product One'
  24. self.assertEqual(queryset.count(), 1)
  25. self.assertEqual(queryset[0], self.product)
  26. def test_product_flavour_property(self):
  27. # Associate flavour with poduct one
  28. self.product.flavours.add(self.flv1)
  29. # Product One has flavour and another_product does not.
  30. self.assertEqual(self.product.has_flavours, True)
  31. self.assertNotEqual(self.another_product.has_flavours, True)

我还建议考虑创建一个brand = models.TextField()模型,具有一对多关系。

英文:

First about your models and fields. You can use model choices at Flavour model, but it is not necessarily required. You can get rid of has_flavours and has_strength fields, use a model property and flavours and strengths relations to obtain the desired output.

Also, as mentioned on the other answer, substitute the relation between Flavour and Product with a many-to-many relation in order to avoid duplicates in your database. Lastly, image_url is also not necessary, since you are using models.ImageField it is possible to access the image url via attribute e.g. instance.image.url.

models.py

  1. class Product(models.Model):
  2. category = models.ForeignKey(
  3. 'Category', null=True, blank=True, on_delete=models.SET_NULL
  4. )
  5. slug = models.SlugField()
  6. sku = models.CharField(max_length=254, null=True, blank=True)
  7. name = models.CharField(max_length=254)
  8. brand = models.TextField()
  9. flavours = models.ManyToManyField('Flavour')
  10. strength = models.ForeignKey(
  11. 'Strength', null=True, blank=True, on_delete=models.SET_NULL
  12. )
  13. description = models.TextField()
  14. price = models.DecimalField(max_digits=6, decimal_places=2)
  15. rating = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True)
  16. image = models.ImageField(null=True, blank=True)
  17. display_home = models.BooleanField(blank=True)
  18. created_at = models.DateTimeField(auto_now_add=True)
  19. class Meta:
  20. ordering = ('-created_at',)
  21. def __str__(self):
  22. return self.name
  23. @property
  24. def has_flavours(self):
  25. return True if self.flavours.count() > 0 else False
  26. @property
  27. def has_strength(self):
  28. return True if self.strength.count() > 0 else False

A simple example, on how you would associate a flavour with a specific product:

tests.py

  1. class ProductTestCase(TestCase):
  2. def setUp(self):
  3. self.flv1 = Flavour.objects.create(flavour_choice='Flavour One')
  4. self.flv2 = Flavour.objects.create(flavour_choice='Flavour Three')
  5. self.product = Product.objects.create(
  6. slug='product-one', name='Product One',
  7. brand='Brand', description='Product Description',
  8. price=decimal.Decimal(100), display_home=True
  9. )
  10. self.another_product = Product.objects.create(
  11. slug='another-product', name='Another Product',
  12. brand='Brand', description='Another Product Description',
  13. price=decimal.Decimal(100), display_home=True
  14. )
  15. def test_product_with_specific_flavour(self):
  16. self.product.flavours.add(self.flv1)
  17. self.product.flavours.add(self.flv2)
  18. self.another_product.flavours.add(self.flv2)
  19. queryset = Product.objects.filter(flavours=self.flv2)
  20. # queryset contains both products
  21. self.assertEqual(queryset.count(), 2)
  22. queryset = Product.objects.filter(flavours=self.flv1)
  23. # queryset contains only 'Product One'
  24. self.assertEqual(queryset.count(), 1)
  25. self.assertEqual(queryset[0], self.product)
  26. def test_product_flavour_property(self):
  27. # Associate flavour with poduct one
  28. self.product.flavours.add(self.flv1)
  29. # Product One has flavour and another_product does not.
  30. self.assertEqual(self.product.has_flavours, True)
  31. self.assertNotEqual(self.another_product.has_flavours, True)

I would also consider the possibility of creating a model for brand = models.TextField() with a one-to-many relation.

答案3

得分: 0

I went a different route in the end as I was overcomplicating the issue.

I added a Variation model:

  1. class Variation(models.Model):
  2. product = models.ForeignKey('Product', null=True, blank=True, on_delete=models.SET_NULL)
  3. flavour = models.CharField(max_length=254, null, blank=True)
  4. strength = models.CharField(max_length=254, null, blank=True)

And now I can just use an if statement to call the flavours into the template in a for loop that iterates over all the flavours associated with the product in the product variation model.

  1. {% if product.has_flavours %}
  2. <div class="col-12">
  3. <p><strong>Flavour:</strong></p>
  4. <select class="form-control rounded-0 w-50" name="product_flavour" id="id_product_flavour">
  5. {% for variation in variations %}
  6. <option value="{{ variation.flavour }}">{{ variation.flavour }}</option>
  7. {% endfor %}
  8. </select>
  9. </div>
  10. {% endif %}
英文:

I went a different route in the end as I was overcomplicating the issue.

I added a Variation model:

  1. class Variation(models.Model): product = models.ForeignKey( &#39;Product&#39;, null=True, blank=True, on_delete=models.SET_NULL ) flavour = models.CharField(max_length=254, null=True, blank=True) strength = models.CharField(max_length=254, null=True, blank=True)

And now I can just use an if statement to call the flavours into the template in a for loop that iterates over all the flavours associated with the product in the product variation model.

  1. {% if product.has_flavours %}
  2. &lt;div class=&quot;col-12&quot;&gt;
  3. &lt;p&gt;&lt;strong&gt;Flavour:&lt;/strong&gt;&lt;/p&gt;
  4. &lt;select class=&quot;form-control rounded-0 w-50&quot; name=&quot;product_flavour&quot; id=&#39;id_product_flavour&#39;&gt;
  5. {% for variation in variations %}
  6. &lt;option value=&quot;{{ variation.flavour }}&quot;&gt;{{ variation.flavour }}&lt;/option&gt;
  7. {% endfor %}
  8. &lt;/select&gt;
  9. &lt;/div&gt;
  10. {% endif %}

huangapple
  • 本文由 发表于 2023年2月23日 22:09:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/75545932.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定