Django query annotate and agregate - django

How can I write a query like this in Django?
select sum(kolvo), reason
from(
select count(reason) kolvo, reason
from contacts group by reason) group by reason

Your query looks semantically equivalent to:
SELECT count(reason) AS kolvo,
reason
FROM contacts
GROUP BY reason
So without the outer query.
You can make such query in Django's ORM with:
Contacts.objects.values('reason').annotate(
kolvo=Count('id')
).order_by('reason')
This will then return a QuerySet that wraps dictionaries, like:
< QuerySet [
{ 'reason': 'some reason', 'kolvo': 13 },
{ 'reason': 'some other reason', 'kolvo': 2 },
] >

Related

Django form - the same field multiple times

how can I process a form with a field:
order = ModelChoiceField(
required=False,
queryset=OrderOd.objects.filter(Q(status='DN') | Q(status='DI')),
widget=Select(
attrs={
"class": "form-select form-select-md form-select-solid",
"data-control": "select2",
"data-multiple": "true",
"multiple": "multiple",
"data-placeholder": _("Vyberte objednávku ..."),
"id": 'order'
}
)
)
In front-end, I can select multiple orders (looks like pills/tags) and in the request sent to the server it looks like this:
movement: f2b7c234-fbdb-4059-bcb6-8ada46cef72c
account: dbabefb7-f053-4edf-a2e3-787bf6bfc371
date: 2022-09-12
order: eb2fc726-3e97-4af2-a8b2-08f20771cfef
order: 8398925b-fca6-4b25-8c48-e12940a5b5c3
order: bfa35391-5cf8-4ed8-8c44-a797da875cb4
order: 07be93ac-20b3-459c-8038-c8b023db6d66
When I inspect self.data, I got
'order': ['eb2fc726-3e97-4af2-a8b2-08f20771cfef', '8398925b-fca6-4b25-8c48-e12940a5b5c3', 'bfa35391-5cf8-4ed8-8c44-a797da875cb4', '07be93ac-20b3-459c-8038-c8b023db6d66'],
but when I check the output of logger.info(self.data['order']), it gives me only the first UUID.
[INFO] form.py 123: 07be93ac-20b3-459c-8038-c8b023db6d66
What I need is to access all UUIDs in the array (order) and process them instance by instance.
Any idea, how to do it?
Thanks
You can use self.data.getlist('order') to return the data in the array form.
see more info in Django documentation

Django Rest Framework filtering a set of item to include only latest entry of each type

I have a list of object of this kind of structure returned in my api
SomeCustomModel => {
itemId: "id",
relatedItem: "id",
data: {},
created_at: "data string"
}
I want to return a list that contains only unique relatedItemIds, filtered by the one that was created most recently.
I have written this and it seems to work
id_tracker = {}
query_set = SomeCustomModel.objects.all()
for item in query_set:
if item.relatedItem.id not in id_tracker:
id_tracker[item.relatedItem.id] = 1
else:
query_set = query_set.exclude(id=item.id)
return query_set
This works by I am wondering if there is cleaner way of writing this using only django aggregations.
I am using Mysql so the distinct("relatedItem") aggregation is not supported.
You should try to do this within sql. You can use Subquery to accomplish this. Here's the example from the django docs.
from django.db.models import OuterRef, Subquery
newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')
Post.objects.annotate(newest_commenter_email=Subquery(newest.values('email')[:1]))
Unfortunately, I haven't found anything that can replace distict() in a django-esque manner. However, you could do something along the lines of:
list(set(map(lambda x: x.['relatedItem_id'], query_set.order_by('created_at').values('relatedItem_id'))))
or
list(set(map(lambda x: x.relatedItem_id, query_set.order_by('created_at'))))
which are a bit more Pythonic.
However, you are saying that you want to return a list yet your function returns a queryset. Which is the valid one?

django_filter ModelMultipleChoiceFilter - Bad Request on miss

I have a ViewSet that has a filter_class that is like this:
class OrderFilter(django_filters.FilterSet):
......
product = django_filters.ModelMultipleChoiceFilter(
field_name='product',
queryset=Product.objects.all(),
)
With this, I can specify a product id, and make a get request like this /orders/?product=<product_id>.
I'm seeing the following behavior in three situations:
If there are order(s) with the given product_id, it will return those orders ... good!
If there are NO orders with that given product_id, it will return a successful 200, with an empty results (e.g. {count: 0, next: null, previous: null, results: [ ]} ... good!
If that product_id doesn't exist, it returns a 400 Bad Request with a ValidationError and this response:
{ product: [ "Select a valid choice. %(value)s is not one of the available choices." ]} ... wtf!
This last situation seems odd to me. Shouldn't the response be the same if (a) the given object relationship isn't there and (b) the object itself doesn't exist? This dual behavior would seemingly indicate to the FE if that product exists or not, and perhaps they shouldn't know that information.
How can I change my filters such that it always returns a 200 with a result set that is empty in those two cases?
I'm on Django==1.11.15 and django-filter==2.0.0
Thanks!

Mongodb Search Query with Populate and regex

I want regex search on mongodb with NodeJS.
First One is Users and Second one is categories. Here I have saved categories id in Users
collection. I want a search Query that filter my records.
Users collection
{_id:'mongo_id', name:"User First",cat_id:2}
{_id:'mongo_id', name:"User Second",cat_id:2}
{_id:'mongo_id', name:"User Third",cat_id:1}
{_id:'mongo_id', name:"User Fourth",,cat_id:4}
Categories
Suppose id is numeric. For demo purpose I have written numeric values.
{_id:'1', name:"Salesman",}
{_id:'2', name:"Carpanter"}
{_id:'3', name:"Plumber"}
{_id:'4', name:"Engineer"}
I have a text input if I will type Carpanter or Carpan(regex) then I want 2 records, or
When I type User Second or second I want 1 Record
var query = {
'name': {
$regex: req.body.name,
$options: 'i'
}
};
innerQuery = {
path: 'category',
select: 'name'
}
Users.find(query)
.populate(innerQuery)
.sort({
'createdDate': -1
})
Your user record looks like this:
{_id:'mongo_id': name:"User First",cat_id:2}
I'll assume the extra : is a typo.
Aside from that, you are attempting to query for title. There is no path title in that record, so you can't query for it.
You're also trying to populate the path category, but there is no field with that name in the user records. The only related field I see is cat_id.
If you want to, for example, query by name and populate the cat_id, you can do something like this:
var query = {
'name': {
$regex: req.body.title,
$options: 'i'
}
};
var innerQuery = {
path: 'cat_id',
model: 'Category',
select: 'name'
};
This is entirely dependent on whether you named your model Category, and also what your schemas actually look like.
(PS, you're also trying to sort by createdDate, but I don't see that field in any of your records, either).

Django Union Query

I need to develop a UNION query in Django with 3 models namely WebQuery,WebReply and BusinessOwners and the output should be of the form below.
{
"(#conversation_id#)_(#b_id#)": {
"from": "(#user_id)",
"email": "(#user_email)",
"date_time": "#get from db",
"query": "are you open ?",
"from_r_id": "(#representative_id)",
"from_r_name": "(#rep_name)",
"business_registered": "FALSE"
"to_business_name": "CCD saket",
"chat": [{
"direction": 1,
"text": "yes sir",
"date_time": "424 577"
}, {
"direction": 0,
"text": "ok",
"date_time": "424 577"
}]
},
I know how to query when only one model is involved, but not sure of the union query.
How will this be achieved?
I personally would say that if this is going to be a common query then I would recommend making a SQL View then querying that.
w3schools has a VERY simple overview of what a view is : http://www.w3schools.com/sql/sql_view.asp
In SQL, a view is a virtual table based on the result-set of an SQL statement.
This means you can write your required sql statement and create a view using this. Then create a django model which mirrors that view which you can then use to query.
So, you will create an SQL view:
CREATE VIEW view_name AS
SELECT a, b, c
FROM table_name
WHERE condition
Then create a django model, which has a slight difference to a normal model:
class view_name(models.Model):
class Meta:
# https://docs.djangoproject.com/en/1.5/ref/models/options/#django.db.models.Options.managed
managed = False
a = models.CharField(max_length)
....
managed = false > https://docs.djangoproject.com/en/1.5/ref/models/options/#django.db.models.Options.managed
You can then query this using the normal django orm syntax
Or there is similar questions:
Previous stackoverflow question, union in django orm
How can I find the union of two Django querysets?
How can I find the union of two Django querysets? provides an example of a union using the '|' operator. I'm not sure how different your models are. If there's common fields you could place those in a separate model and use model inheritance