I need to query all models where the ID matches the 'id' attribute of JSON array, something like that:
I have 3 saved model objects with respective ID's:
ID 1
ID 3
ID 4
I have a JSON array like that:
[{'id' : 1}, {'id' : 2}, {'id' : 5}]
I want to filter in that way:
model.objects.filter('Objects by ID that is not listed in the JSON array')
The result of the filter should be a list with models objects that the ID is not in the JSON:
result = [model_pk=3, model_pk=4]
Any ideas?
You can use exclude method to achieve that:
ids = [i['id'] for i in json_array]
qs = model.objects.exclude(id__in=ids)
Related
When an output is received in the below form after running the query
<QuerySet [<key: value object (ad5bb6b4-8035)>]>
I want to get ad5bb6b4-8035 string only for further operations.
So I tried
course_qs = <QuerySet [<key: value object (ad5bb6b4-8035)>]>
for course in course_qs:
print(course)
which returned
value object (ad5bb6b4-8035)
How to get only ad5bb6b4-8035.?
getting values of QuerySet in django
How to extract numerical value from Django queryset?
Extracting message from django queryset
values() is extract key,value for the specific column from queryset it's return list of dictionaries.
value1 = User.objects.all().values('username')
#output = <QuerySet [{'username': 'one'}, {'username': 'three'}, {'username': 'two'}]>
values_list() is extract only values for the specific column from queryset it's return list of tuples.
value2 = User.objects.all().values_list('username')
#output = <QuerySet [('one',), ('three',), ('two',)]>
Is there an elegant way to load many entities from the database with SqlAlchemy if I have a list of composite primary keys?
One object can be loaded with Query.get(*primary_key).
What about a list of them? For instance:
primary_keys = [
{"type":"user", "id": 1},
{"type":"user", "id": 2},
{"type":"user", "id": 3},
]
instances = ssn.query(models.Object)#...?
Just iterate over inspect(models.Object).primary_key and build a condition manually:
from sqlalchemy import or_, and_, inspect
instances = ssn.query(models.Object).filter(or_( # or_()ed together
# and_()ed condition on all PK fields
and_(*(
# column == value
column == pk_dict[column.key]
for column in inspect(models.Object).primary_key # list of PK columns
))
for pk_dict in primary_keys
))
A more elegant solution by #vdmit11 that uses SQL tuples:
from sqlalchemy import inspect, tuple_
# List of Column objects of the primary key
pk_columns = inspect(models.Object).primary_key
pk_names = [col.key for col in pk_columns]
# Build the condition: (primary-key-tuple) IN (....)
condition = tuple_(*pk_columns).in_(
# Every object is represented by its primary key tuple
tuple(entity_dict[pk_field] for pk_field in pk_names)
for entity_dict in primary_keys
)
instances = ssn.query(models.Object).filter(condition).all()
It will generate a query which looks like this:
SELECT *
FROM users
WHERE (uid, login) IN ((1, 'vdmit11'), (2, 'kolypto'));
A part of the model that I have, which uses Django Model field, is like the following:
class SalesModel(models.Model):
some_data = models.PositiveIntegerField(db_index=True)
some_other_data = models.CharField(max_length=50)
json_data = JSONField(blank=True, null=True)
Now following is the format of the JsonData field:
[{"id": val, "contribution": "some_val", }, {"id": some_val, "contribution": "some_other_val",}, {"id": other_val, "contribution": "some_another_val"}]
i.e., the format is:
[{'id':XX, 'contribution':XX},{'id':YY, 'contribution':YY},{'id':ZZ, 'contribution':ZZ}]
Currently I can filter the Django table with the val of ID. I would now, like to know the contribution of that particular ID.
For eg, if val = 1, I would like to filter the model SalesModel which has JsonField with id = 1, and I want to show the related contribution. So, that would mean, out of the 3 possible dictionaries (as per the field construction), I would only show one dictionary (filtered by the 'ID' key of that dictionary). That would mean, if the 2nd dictionary has a matching ID, show only the 2nd contribution, if the 1st ID is matching show only the 1st contribution, and similarly for the 3rd dictionary.
Is there a way that can be done?
You could restructure your JSONField differently, by giving it a dict where the key, value pairs are id: contribution directly. This way you could use the has_key filter and KeyTransform will work, as I'm not sure it works on an array of dicts. So assuming your json_data looks like this:
{1: 'xx', 3: 'yy', 9: 'zz'}
you could query this way, based on #vanojx1 contribution:
SalesModel.filter(json_data__has_key=id)\
.annotate(contrib=KeyTransform(id, 'json_data')\
.values('contrib')
Alternatively, using raw jsonb in postgresql:
SalesModel.filter(json_data__has_key=id)\
.extra(select={'contrib': "json_data->{0}".format(id)})\
.values('contrib')
This should work DOC
SalesModel.objects.filter(json_data__id=1).values('id', 'json_data__contribution')
Yes, I guess. If I have understood it right, you will have an id to be matched or a list of ID's. So if your ID is 2:
my_id = 2
dict1 = [{"id":1, "contribution":10},{"id":2, "contribution":20},{"id":3, "contribution":30}]
for i in dict1:
if i["id"] == my_id:
print(i["contribution"])
I have a model with a CharField with choices. I want to aggregate the model and get a list of all of the choices and the number of models in each choice. So if i have:
model1: a
model2: b
model3: c
model4: a
model5: c
model6: c
I want to build a django query set to get the following result (in json if i can)
{a: 2, b: 1, c: 3}
Is this even possible with the django orm or do i need to run a pure sql query?
Thanks.
This should give you the dict you are looking for. Be careful, however, with the order of annotate and values:
from django.db.models import Count
d = {
x['field_name']: x['count']
for x in model.objects
.annotate(count=Count('field_name'))
.values('field_name', 'count')
.distinct()
}
If you want to convert this to json use the json module:
import json
json_string = json.dumps(d)
I have a table bucket_items with columns bucket_id and item_id i want to group item_ids by bucket_id, using
ItemBucket.objects.values('bucket_id', 'item_id') this returns list of dictionary containing bucket_id and item_id, what i want is a list of dictionary with bucket id as key and list of item_ids as value something like
[{1: [1,2,3]}, {3: [7,3,2]}]
Using values_list will be better here instead of values, which returns tuples instead of dicts. So you can do something like
final_dict = dict()
for (bucket_id, item_id) in ItemBucket.objects.values_list('bucket_id', 'item_id'):
final_dict.setdefault(bucket_id, []).append(item_id)
final_list = [{bucket_id: final_dict[bucket_id]} for bucket_id in final_dict]