get unique values from query_set Django - django

I'm trying to get unique results from s query_set.
Example.
ID | NOMBRE | CLASIFICACION
1 Escoba Limpieza
2 Trapeador Limpieza
3 Tornillo Herramienta
I want to get "Limpieza and Herramienta" only. currently I'm getting "Limpieza, Limpieza and Herramineta"
my views.py:
class ItemListView(ListView):
model= Items
def get_context_data(self,**kwargs):
context = super(ItemListView, self).get_context_data(**kwargs)
context['clasificacion'] =Items.objects.order_by('nombre').distinct('clasificacion')
return context
my models.py
from django.db import models
# Create your models here.
class Items(models.Model):
nombre = models.CharField(max_length=250)
descripcion = models.CharField(max_length=250)
codigo_proveedor = models.CharField(max_length=250)
clasificacion = models.CharField(max_length=250)
c_minima = models.IntegerField()
c_actual = models.IntegerField()
proveedor = models.ForeignKey('Proveedores',on_delete=models.CASCADE)
active = models.BooleanField()
def __str__(self):
return self.nombre + ' ----- ' +
self.clasificacion + ' ----- ' +
str(self.c_actual)
class Proveedores(models.Model):
nombre = models.CharField(max_length=250)
telefono = models.CharField(max_length=250)
direccion1 = models.CharField(max_length=250)
direccion2 = models.CharField(max_length=250, null=True)
active = models.BooleanField()
def __str__(self):
return self.nombre
Thanks for the help!

Will's response is correct, but I think you want to do the order_by() operation first to ensure you are getting the correct results.
context['clasificacion'] =(Items
.objects
.order_by('clasification', 'nombre')
.distinct('clasificacion'))

context['clasificacion'] = Items.objects.order_by('clasificacion', 'nombre').distinct('clasificacion')
distinct() must match the leftmost order_by(). So making the column you use in distinct() the first column in the order_by() makes it work.

Related

Moving logic from Django views to models

This is my model:
class Car(models.Model):
make = models.CharField(max_length=30)
model = models.CharField(max_length=30)
rating = models.PositiveIntegerField(validators=[MinValueValidator(1), MaxValueValidator(5)], default=0, blank=True)
avg_rating = models.FloatField(default=0, blank=True)
rates_number = models.IntegerField(default=0, blank=True)
def __str__(self):
return self.make + ' ' + self.model
What's the best way to move the logic from the following perform_create function (in views.py) to my models?
class CarRate(generics.CreateAPIView):
serializer_class = CarRatingSerializer
queryset = Car.objects.all()
def perform_create(self, serializer):
pk = serializer.validated_data['car_id']
rating = serializer.validated_data['rating']
queryset = Car.objects.all()
car_queryset = get_object_or_404(queryset, pk=pk)
if car_queryset.rates_number == 0:
car_queryset.avg_rating = rating
else:
car_queryset.avg_rating = (car_queryset.avg_rating + rating)/2
car_queryset.avg_rating = round(car_queryset.avg_rating, 1)
car_queryset.rates_number = car_queryset.rates_number + 1
car_queryset.save()
It would be much better to create two models. Think about how you are counting average rating. This would be some better idea for now:
class Car(models.Model):
make = models.CharField(max_length=30)
model = models.CharField(max_length=30)
def rates_number(self):
return self.rates.all().count()
def avg_rating(self):
# count average_rating from relation to Rate objects and return it
return average_rating
class CarRate(models.Model):
value = models.PositiveIntegerField(validators=[MinValueValidator(1), MaxValueValidator(5)], default=0, blank=True)
car = models.ForeignKey(Car, on_delete=models.CASCADE, related_name='rates')

How can I filter manytomany models?

I would like to filter my plots objects on the fruit ex.pear. The Inputs are linked via a manytomany to the plots. This is the structure:
This is the data I get out of it:
What i would like to have:
result:
I tried the following:
plots = Plot.objects.filter(fruittype__fruit="Pear")
inputs = Input.objects.filter(plot__in=plots).distinct()
This gives me already a close solution for my problem but not what I want.
Now I only would like to filter out the other plots that still show up with apple.
models inputs:
class Product (models.Model):
type = models.ForeignKey(Type, on_delete=models.CASCADE)
product = models.CharField(max_length=70)
standaard_dosis = models.FloatField()
def __str__(self):
return self.product
class Input (models.Model):
datum = models.DateField()
plot = models.ManyToManyField(Plot)
def __str__(self):
return str(self.datum)
class ProductInputs (models.Model):
input = models.ForeignKey(Inputs, on_delete=models.CASCADE, default="")
product = models.ForeignKey(Product, on_delete=models.CASCADE, default="")
dosis = models.FloatField()
def __str__(self):
string = str(self.product)
return string
models plots:
class Fruit(models.Model):
fruit = models.CharField(max_length=30, primary_key=True)
def __str__(self):
return self.fruit
class Meta:
verbose_name_plural = "fruits"
class Fruittype(models.Model):
fruit = models.ForeignKey(Fruit, on_delete=models.CASCADE)
fruittype = models.CharField(max_length=30, primary_key=True)
def __str__(self):
return self.fruittype
class Meta:
verbose_name_plural = "fruitypes"
class Plot(models.Model):
name = models.CharField(max_length=30)
fruittype = models.ForeignKey(Fruittype, on_delete=models.CASCADE)
def __str__(self):
return str(self.fruittype.fruit) + " | " + self.name
class Meta:
verbose_name_plural = "plots"
Your Plot queryset is not going as deep as it should. I think you should change to something like this (although this is it's a bit of overkill)
plot_ids = Plot.objects.filter(fruittype__fruit__fruit="Pear").values_list('pk', flat=True)
or
plot_ids = Plot.objects.filter(fruittype__fruittype="Pear").values_list('pk', flat=True) # I don't know what fruittype is but I guess this would help you
Then your "inputs"
inputs = Input.objects.filter(plot__pk__in=plot_ids).distinct()
You might wanna try this as well:
from django.db.models import Prefetch
Input.objects.prefetch_related(
Prefetch('plot', queryset=Plot.objects.filter(fruittype__fruit__fruit="Pear"))
)
It worked with:
all_inputs=Input.objects.filter(plot__pk__in=plot_ids).distinct().prefetch_related(Prefetch('plot', queryset=Plot.objects.filter(fruittype__fruit__fruit="Pear")))

Optimization of querys in django eliminating querys duplicates

I'm trying to get the number of products that have each category, but each category is in turn parent of other categories, so I want to know how many children have that category and their daughter categories, I have simplified the query to the maximum in the following way, but in the django debug I keep showing that I have 66 querys duplicates.
How can I eliminate these duplications?
With the first line of views.py, he managed to get the number of products in a category, but the problem is essentially to tell him to return me from the category and his daughters.
models.py
class Categoria(models.Model):
nombre = models.CharField(max_length=200)
slug = models.SlugField(max_length=100)
padre = models.ForeignKey('self', blank=True, null=True,
related_name='cat_padre')
pub_date = models.DateTimeField('date published',
auto_now_add=True)
upd_date = models.DateTimeField('date updated', auto_now=True)
def __str__(self):
return self.nombre + ' ' + self.pais.iso
class Producto(models.Model):
nombre = models.CharField(max_length=200)
slug = models.SlugField(max_length=100)
categoria = models.ForeignKey(Categoria)
views.py
cats = Categoria.objects.annotate(num_productos=Count('producto')).filter(pais__iso=pais, padre__isnull=True).order_by('-num_productos')
for c in cats:
num_p = Producto.objects.filter(categoria__padre=c).count()
c.num_productos += num_p
contexto = {
'categorias_padre': cats,
}
return render(request, 'web/pruebitas/product.html', contexto)
Django debug:
SELECT COUNT(*) AS "__count" FROM "web_producto" INNER JOIN "web_categoria" ON ("web_producto"."categoria_id" = "web_categoria"."id") WHERE "web_categoria"."padre_id" = '790'
Duplicated 62 times.
Conexión: default
/home/luis/PycharmProjects/lco_web/web/middleware.py in __call__(29)
response = self.get_response(request)
/home/luis/PycharmProjects/lco_web/web/views.py in index(11)
return categoria(request, '', '/')
/home/luis/PycharmProjects/lco_web/web/views.py in categoria(170)
'categorias': categorias(pais, categoria.id if categoria else 0),
/home/luis/PycharmProjects/lco_web/web/views.py in categorias(29)
num_p = Producto.objects.filter(categoria__padre=c).count()
You could achieve this by using reverse lookup to child categories using cat_padre and Count with distinct=True.
cats = Categoria.objects.annotate(
num_productos=Count('cat_padre__producto', distinct=True) +
Count('producto', distinct=True)).filter(
pais__iso=pais, padre__isnull=True).order_by('-num_productos')
P.S. I have tested that on fake data so please compare what you have got earlier with what returns this query.

QuerySet in Django - returns exception

I am trying to understand how exactly query works on Django, i followed the tutorials it´s not working I am not sure what i am doing wrong.
When I run
BeneficientePagar.objects.filter(nome__contains="Joao Pedro")
it returns
"Choices are %s" %s (name, ",".join(available))) django.core.exceptions.FieldError: Cannot resolve keyword "nome into field. Choices are: ID, beneficiente, beneficiente_id,join, join_id, moeda
from django.db import models
# Create your models here.
class Moeda(models.Model):
moeda_ficticia = models.FloatField()
class Join(models.Model):
nome = models.CharField(max_length=150)
nascimento = models.DateField()
cpf = models.IntegerField(primary_key=True)
endereco = models.CharField(max_length=150)
email = models.EmailField()
def __str__(self):
return self.nome
class Beneficiente(models.Model):
ID = models.AutoField(primary_key=True)
nome = models.CharField(max_length=150)
CNPJ = models.IntegerField(max_length = 10)
def __str__(self):
return self.nome
class Favores(models.Model):
ID = models.AutoField(primary_key=True)
favor = models.CharField(max_length=150)
dataInserido = models.DateField()
usuarios = models.ForeignKey(Join)
def __str__(self):
return self.favor
class BeneficientePagar(models.Model):
ID = models.AutoField(primary_key=True)
moeda = models.IntegerField()
beneficiente = models.ForeignKey(Beneficiente)
join = models.ForeignKey(Join)
def __str__(self):
return self.ID
Thanks in advance
If using BeneficientPager, you need to do
BeneficientePagar.objects.filter(beneficient__nome__contains="Joao Pedro")
You are getting the error because nome is a field on Beneficiente, not BeneficientePagar.
You can either do
Beneficiente.objects.filter(nome__contains="Joao Pedro")
which will return a queryset of Beneficientes. Or if you need BeneficientePagar you can query through the foreign key.
BeneficientePagar.objects.filter(beneficiente__nome__contains="Joao Pedro")

Django ORM - filter with another table like LEFT JOIN adding a column

Well i got a problem with Django i want to acces to all the "Reaccion" but add a column (like in the image) if exists a relationship with "ReaccionPost" including "id_post" ,'status', and id_reaccion, but if it's not exist, in the colum should be a 0 por '' and if exists should be 1 or another true statement,
Thank you for reading my issue.
https://drive.google.com/file/d/0B3suBvZgwQ0JVmtxb1pzbmxGZW8/view?usp=sharing
class Reaccion(models.Model):
nombre = models.CharField(max_length=40)
descripcion = models.CharField(max_length=300)
icono = models.CharField(max_length=300)
def __unicode__(self):
return self.nombre
class Post(models.Model):
usuario= models.ForeignKey(User)
tipo= models.ForeignKey(Tipo)
creacion = models.DateTimeField(auto_now_add=True)
status = models.ForeignKey(Estado,default=1)
def __unicode__(self):
return self.titulo
class ReaccionPost(models.Model):
ESTADO = (
(1, 'Activo'),
(2, 'Inactivo'),
)
id_post= models.ForeignKey(Post)
usuario = models.ForeignKey(User)
id_reaccion = models.ForeignKey(Reaccion)
creacion = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=ESTADO,default=1)
def __unicode__(self):
return str(self.usuario) +" "+ str(self.id_post) +" "+ str(self.id_reaccion)