django 在 ListViews 中与众不同
django distinct in the ListViews
我在 ListViews 中遇到不同的问题
我在“Allergeni”和“Ingredient”之间有一个 M2M 连接,在“Product”和“Ingredient”之间有另一个 M2M,它通过 table“Materiali”。
我需要获得一个 table,其中包含整个“产品”列表,其中包含一个额外字段“Allergeni”,该字段仅包含原始
中所有值的唯一版本
成分型号:
class Ingredient (models.Model):
nome = models.CharField(max_length=200)
categoria = models.ForeignKey("Categoria")
costokg = models.DecimalField(max_digits=20,decimal_places=2,default=Decimal('0.00'))
resa = models.IntegerField()
prezzopulito = models.DecimalField(max_digits=20,decimal_places=3,default=Decimal('0.00'))
componenti = models.TextField()
allergeni = models.ManyToManyField("Allergeni", blank=True)
def __str__(self):
return self.nome
def get_absolute_url(self):
return reverse("ingredients:detail", kwargs={"pk": self.pk})
class Allergeni (models.Model):
allergene = models.CharField(max_length=100)
产品型号:
class Product (models.Model):
nome = models.CharField(max_length=250)
descrizione = models.TextField(blank=True, null=True)
prezzo = models.DecimalField(max_digits=20,decimal_places=2,default=Decimal('0.00'))
peso_finale = models.DecimalField(max_digits=20,decimal_places=2,default=Decimal('0.00'))
categoria = models.ForeignKey("Categoria")
tag = models.ManyToManyField("Tag", blank=True)
componenti = models.ManyToManyField(Ingredient, through='Materiali', through_fields=('object_id', 'ingrediente'))
creazione = models.DateTimeField(auto_now=False, auto_now_add=True)
aggiornamento = models.DateTimeField(auto_now=True, auto_now_add=False)
def __str__(self):
return self.nome
def get_absolute_url(self):
return reverse("products:detail", kwargs={"pk": self.pk})
class Materiali (models.Model):
object_id = models.ForeignKey("Product", on_delete=models.CASCADE)
ingrediente = models.ForeignKey(Ingredient, on_delete=models.CASCADE, related_name="materia_prima")
peso = models.DecimalField(max_digits=20,decimal_places=2,default=Decimal('0.00'))
def __str__(self):
return self.ingrediente.nome
产品浏览
def product_list(request):
queryset = Product.objects.all() \
.annotate(total=Round((Sum((F('materiali__ingrediente__prezzopulito')/1000) * F('materiali__peso'))) / (F('peso_finale'))) * 1000 )
materiali = Materiali.objects.all()
allergeni= materiali.values_list('ingrediente__allergeni__allergene', flat=True).distinct()
context = {
"object_list" : queryset,
"title": "List",
"allergeni": allergeni,
}
return render(request, "product/product_list.html", context)
代码https://pastebin.com/LcyPF8v8
使用“values_list”我获得了唯一值但没有被forloop中的对象过滤,我不能使用TemplateTag,所以如果可能我更喜欢其他选项。
我该怎么做?
最佳,
这样不行吗?
allergeni= materiali.distinct('ingrediente__allergeni__allergene').values_list('ingrediente__allergeni__allergene', flat=True)
您可以使用 set of python 可以自动区分不同的数组类型对象所以不需要使用 distinct()对于数组类型的对象。
allergeni = set(materiali.values_list('ingrediente__allergeni__allergene', flat=True))
基于Allergeni的foo filter product queryset,你可以在下面使用
queryset = Product.objects.all() \
.annotate(total=Round((Sum((F('materiali__ingrediente__prezzopulito')/1000) * F('materiali__peso'))) / (F('peso_finale'))) * 1000 )
materiali = Materiali.objects.all()
allergeni= materiali.values_list('ingrediente__allergeni__allergene', flat=True).distinct()
queryset = queryset.filter(materiali__ingrediente__allergeni__in=allergeni)
现在您将获得具有 过敏原
的独特产品
您必须修改您的模型:
class Ingredient (models.Model):
...
allergeni = models.ManyToManyField("Allergeni", blank=True,
related_name="ingredienti")
...
class Product (models.Model):
...
componenti = models.ManyToManyField(Ingredient,
through='Materiali', through_fields=('product', 'ingrediente'),
related_name="prodotti")
...
class Materiali(models.Model):
...
# Don't use object_id this is an object
product = models.ForeignKey("Product", on_delete=models.CASCADE)
# use plural for 1..* related_name
ingrediente = models.ForeignKey(Ingredient,
on_delete=models.CASCADE,
related_name="materie_prime")
...
所以在您看来:
def product_list(request):
queryset = Product.objects.all().annotate(total=Round((Sum((F('materiali__ingrediente__prezzopulito')/1000) * F('materiali__peso'))) / (F('peso_finale'))) * 1000 )
product_info = {}
for product in queryset:
product_allergeni = Allergeni.objects.filter(ingredienti__prodotti=product).values_list('allergene', flat=True)
product_info.update({product.id:list(product_allergeni)})
context = {
"object_list" : queryset,
"title": "List",
"product_info": product_info,
}
return render(request, "product/product_list.html", context)
在您的模板中,改为:
<ul>
{% for product in object_list %}
<li>
<p>Product : {{product.name}}</p>
<ol>Allergeni :
{% for product_id,allergeni in product_info.items %}
{% if product_id == product.id %}
{% for allergene in allergeni %}
<li>{{ allergene }}</li>
{% endfor %}
{% endif %}
{% endfor %}
</ol>
</li>
{% endfor %}
</ul>
N.B.
- 要直接访问您的 product_info 字典,您可以使用 this trick :而不是循环每个键,值
- 始终使用英文变量,让非意大利语程序员更好地帮助和理解您;)
希望对你有帮助
我在 ListViews 中遇到不同的问题 我在“Allergeni”和“Ingredient”之间有一个 M2M 连接,在“Product”和“Ingredient”之间有另一个 M2M,它通过 table“Materiali”。
我需要获得一个 table,其中包含整个“产品”列表,其中包含一个额外字段“Allergeni”,该字段仅包含原始
中所有值的唯一版本成分型号:
class Ingredient (models.Model):
nome = models.CharField(max_length=200)
categoria = models.ForeignKey("Categoria")
costokg = models.DecimalField(max_digits=20,decimal_places=2,default=Decimal('0.00'))
resa = models.IntegerField()
prezzopulito = models.DecimalField(max_digits=20,decimal_places=3,default=Decimal('0.00'))
componenti = models.TextField()
allergeni = models.ManyToManyField("Allergeni", blank=True)
def __str__(self):
return self.nome
def get_absolute_url(self):
return reverse("ingredients:detail", kwargs={"pk": self.pk})
class Allergeni (models.Model):
allergene = models.CharField(max_length=100)
产品型号:
class Product (models.Model):
nome = models.CharField(max_length=250)
descrizione = models.TextField(blank=True, null=True)
prezzo = models.DecimalField(max_digits=20,decimal_places=2,default=Decimal('0.00'))
peso_finale = models.DecimalField(max_digits=20,decimal_places=2,default=Decimal('0.00'))
categoria = models.ForeignKey("Categoria")
tag = models.ManyToManyField("Tag", blank=True)
componenti = models.ManyToManyField(Ingredient, through='Materiali', through_fields=('object_id', 'ingrediente'))
creazione = models.DateTimeField(auto_now=False, auto_now_add=True)
aggiornamento = models.DateTimeField(auto_now=True, auto_now_add=False)
def __str__(self):
return self.nome
def get_absolute_url(self):
return reverse("products:detail", kwargs={"pk": self.pk})
class Materiali (models.Model):
object_id = models.ForeignKey("Product", on_delete=models.CASCADE)
ingrediente = models.ForeignKey(Ingredient, on_delete=models.CASCADE, related_name="materia_prima")
peso = models.DecimalField(max_digits=20,decimal_places=2,default=Decimal('0.00'))
def __str__(self):
return self.ingrediente.nome
产品浏览
def product_list(request):
queryset = Product.objects.all() \
.annotate(total=Round((Sum((F('materiali__ingrediente__prezzopulito')/1000) * F('materiali__peso'))) / (F('peso_finale'))) * 1000 )
materiali = Materiali.objects.all()
allergeni= materiali.values_list('ingrediente__allergeni__allergene', flat=True).distinct()
context = {
"object_list" : queryset,
"title": "List",
"allergeni": allergeni,
}
return render(request, "product/product_list.html", context)
代码https://pastebin.com/LcyPF8v8
使用“values_list”我获得了唯一值但没有被forloop中的对象过滤,我不能使用TemplateTag,所以如果可能我更喜欢其他选项。
我该怎么做?
最佳,
这样不行吗?
allergeni= materiali.distinct('ingrediente__allergeni__allergene').values_list('ingrediente__allergeni__allergene', flat=True)
您可以使用 set of python 可以自动区分不同的数组类型对象所以不需要使用 distinct()对于数组类型的对象。
allergeni = set(materiali.values_list('ingrediente__allergeni__allergene', flat=True))
基于Allergeni的foo filter product queryset,你可以在下面使用
queryset = Product.objects.all() \
.annotate(total=Round((Sum((F('materiali__ingrediente__prezzopulito')/1000) * F('materiali__peso'))) / (F('peso_finale'))) * 1000 )
materiali = Materiali.objects.all()
allergeni= materiali.values_list('ingrediente__allergeni__allergene', flat=True).distinct()
queryset = queryset.filter(materiali__ingrediente__allergeni__in=allergeni)
现在您将获得具有 过敏原
的独特产品您必须修改您的模型:
class Ingredient (models.Model):
...
allergeni = models.ManyToManyField("Allergeni", blank=True,
related_name="ingredienti")
...
class Product (models.Model):
...
componenti = models.ManyToManyField(Ingredient,
through='Materiali', through_fields=('product', 'ingrediente'),
related_name="prodotti")
...
class Materiali(models.Model):
...
# Don't use object_id this is an object
product = models.ForeignKey("Product", on_delete=models.CASCADE)
# use plural for 1..* related_name
ingrediente = models.ForeignKey(Ingredient,
on_delete=models.CASCADE,
related_name="materie_prime")
...
所以在您看来:
def product_list(request):
queryset = Product.objects.all().annotate(total=Round((Sum((F('materiali__ingrediente__prezzopulito')/1000) * F('materiali__peso'))) / (F('peso_finale'))) * 1000 )
product_info = {}
for product in queryset:
product_allergeni = Allergeni.objects.filter(ingredienti__prodotti=product).values_list('allergene', flat=True)
product_info.update({product.id:list(product_allergeni)})
context = {
"object_list" : queryset,
"title": "List",
"product_info": product_info,
}
return render(request, "product/product_list.html", context)
在您的模板中,改为:
<ul>
{% for product in object_list %}
<li>
<p>Product : {{product.name}}</p>
<ol>Allergeni :
{% for product_id,allergeni in product_info.items %}
{% if product_id == product.id %}
{% for allergene in allergeni %}
<li>{{ allergene }}</li>
{% endfor %}
{% endif %}
{% endfor %}
</ol>
</li>
{% endfor %}
</ul>
N.B.
- 要直接访问您的 product_info 字典,您可以使用 this trick :而不是循环每个键,值
- 始终使用英文变量,让非意大利语程序员更好地帮助和理解您;)
希望对你有帮助