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

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

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

问题

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

口味模型(Flavour model):

class Flavour(models.Model):
    flavour_choice = models.CharField(null=True, blank=True, max_length=254)

    def __str__(self):
        return self.flavour_choice

和产品模型(Product model):

class Product(models.Model):
    category = models.ForeignKey(
        'Category', null=True, blank=True, on_delete=models.SET_NULL
    )
    slug = models.SlugField()
    sku = models.CharField(max_length=254, null=True, blank=True)
    name = models.CharField(max_length=254)
    brand = models.TextField()
    has_flavours = models.BooleanField(default=False, null=True, blank=True)
    flavours = models.ForeignKey(
        'Flavour', null=True, blank=True, on_delete=models.SET_NULL
    )
    has_strength = models.BooleanField(default=False, null=True, blank=True)
    strength = models.ForeignKey(
        'Strength', null=True, blank=True, on_delete=models.SET_NULL
    )
    description = models.TextField()
    price = models.DecimalField(max_digits=6, decimal_places=2)
    rating = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True)
    image_url = models.URLField(max_length=1024, null=True, blank=True)
    image = models.ImageField(null=True, blank=True)
    display_home = models.BooleanField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ('-created_at',)

    def __str__(self):
        return self.name

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

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

英文:

I have two models in my models.py file:

Flavour model:


class Flavour(models.Model):
    flavour_choice = models.CharField(null=True, blank=True, max_length=254)

    def __str__(self):
        return self.flavour_choice

and Product model:

class Product(models.Model):
    category = models.ForeignKey(
        'Category', null=True, blank=True, on_delete=models.SET_NULL
        )
    slug = models.SlugField()
    sku = models.CharField(max_length=254, null=True, blank=True)
    name = models.CharField(max_length=254)
    brand = models.TextField()
    has_flavours = models.BooleanField(default=False, null=True, blank=True)
    flavours = models.ForeignKey(
        'Flavour', null=True, blank=True, on_delete=models.SET_NULL
        )
    has_strength = models.BooleanField(default=False, null=True, blank=True)
    strength = models.ForeignKey(
        'Strength', null=True, blank=True, on_delete=models.SET_NULL
        )
    description = models.TextField()
    price = models.DecimalField(max_digits=6, decimal_places=2)
    rating = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True)
    image_url = models.URLField(max_length=1024, null=True, blank=True)
    image = models.ImageField(null=True, blank=True)
    display_home = models.BooleanField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ('-created_at',)

    def __str__(self):
        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

class Product(models.Model):
    category = models.ForeignKey(
        'Category', null=True, blank=True, on_delete=models.SET_NULL
        )
    slug = models.SlugField()
    sku = models.CharField(max_length=254, null=True, blank=True)
    name = models.CharField(max_length=254)
    brand = models.TextField()
    flavours = models.ManyToManyField('Flavour')
    strength = models.ForeignKey(
        'Strength', null true, blank=true, on delete=models.SET NULL
        )
    description = models.TextField()
    price = models.DecimalField(max_digits=6, decimal_places=2)
    rating = models.DecimalField(max_digits=6, decimal_places=2, null=true, blank=true)
    image = models.ImageField(null=true, blank=true)
    display_home = models.BooleanField(blank=true)
    created_at = models.DateTimeField(auto_now_add=true)

    class Meta:
        ordering = ('-created_at',)

    def __str__(self):
        return self.name

    @property
    def has_flavours(self):
        return True if self.flavours.count() > 0 else False

    @property
    def has_strength(self):
        return True if self.strength.count() > 0 else False

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

tests.py

class ProductTestCase(TestCase):
    def setUp(self):
        self.flv1 = Flavour.objects.create(flavour_choice='Flavour One')
        self.flv2 = Flavour.objects.create(flavour_choice='Flavour Three')

        self.product = Product.objects.create(
            slug='product-one', name='Product One',
            brand='Brand', description='Product Description',
            price=decimal.Decimal(100), display_home=True
        )

        self.another_product = Product.objects create(
            slug='another-product', name='Another Product',
            brand='Brand', description='Another Product Description',
            price=decimal.Decimal(100), display_home=True
        )

    def test_product_with_specific_flavour(self):
        self.product.flavours.add(self.flv1)
        self.product.flavours.add(self.flv2)
        self.another_product.flavours.add(self.flv2)

        queryset = Product.objects.filter(flavours=self.flv2)
        # queryset contains both products
        self.assertEqual(queryset.count(), 2)

        queryset = Product.objects.filter(flavours=self.flv1)
        # queryset contains only 'Product One'
        self.assertEqual(queryset.count(), 1)
        self.assertEqual(queryset[0], self.product)

    def test_product_flavour_property(self):
        # Associate flavour with poduct one
        self.product.flavours.add(self.flv1)

        # Product One has flavour and another_product does not.
        self.assertEqual(self.product.has_flavours, True)
        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

class Product(models.Model):
    category = models.ForeignKey(
        'Category', null=True, blank=True, on_delete=models.SET_NULL
        )
    slug = models.SlugField()
    sku = models.CharField(max_length=254, null=True, blank=True)
    name = models.CharField(max_length=254)
    brand = models.TextField()
    flavours = models.ManyToManyField('Flavour')
    strength = models.ForeignKey(
        'Strength', null=True, blank=True, on_delete=models.SET_NULL
        )
    description = models.TextField()
    price = models.DecimalField(max_digits=6, decimal_places=2)
    rating = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True)
    image = models.ImageField(null=True, blank=True)
    display_home = models.BooleanField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ('-created_at',)

    def __str__(self):
        return self.name

    @property
    def has_flavours(self):
        return True if self.flavours.count() > 0 else False

    @property
    def has_strength(self):
        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

class ProductTestCase(TestCase):
    def setUp(self):
        self.flv1 = Flavour.objects.create(flavour_choice='Flavour One')
        self.flv2 = Flavour.objects.create(flavour_choice='Flavour Three')

        self.product = Product.objects.create(
            slug='product-one', name='Product One',
            brand='Brand', description='Product Description',
            price=decimal.Decimal(100), display_home=True
        )

        self.another_product = Product.objects.create(
            slug='another-product', name='Another Product',
            brand='Brand', description='Another Product Description',
            price=decimal.Decimal(100), display_home=True
        )

    def test_product_with_specific_flavour(self):
        self.product.flavours.add(self.flv1)
        self.product.flavours.add(self.flv2)
        self.another_product.flavours.add(self.flv2)

        queryset = Product.objects.filter(flavours=self.flv2)
        # queryset contains both products
        self.assertEqual(queryset.count(), 2)

        queryset = Product.objects.filter(flavours=self.flv1)
        # queryset contains only 'Product One'
        self.assertEqual(queryset.count(), 1)
        self.assertEqual(queryset[0], self.product)

    def test_product_flavour_property(self):
        # Associate flavour with poduct one
        self.product.flavours.add(self.flv1)

        # Product One has flavour and another_product does not.
        self.assertEqual(self.product.has_flavours, True)
        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:

class Variation(models.Model):
    product = models.ForeignKey('Product', null=True, blank=True, on_delete=models.SET_NULL)
    flavour = models.CharField(max_length=254, null, blank=True)
    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.

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

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

I added a Variation model:

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.

{% if product.has_flavours %}
                        &lt;div class=&quot;col-12&quot;&gt;
                            &lt;p&gt;&lt;strong&gt;Flavour:&lt;/strong&gt;&lt;/p&gt;
                            &lt;select class=&quot;form-control rounded-0 w-50&quot; name=&quot;product_flavour&quot; id=&#39;id_product_flavour&#39;&gt;
                                {% for variation in variations %}
                                &lt;option value=&quot;{{ variation.flavour }}&quot;&gt;{{ variation.flavour }}&lt;/option&gt;
                                {% endfor %}
                            &lt;/select&gt;
                        &lt;/div&gt;
                        {% 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:

确定