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]
Related
I need to take this dictionary {'1': 9, '2': 5} (or one like it), and replace all the keys with their respective names from a database.
I was able to get the appropriate names from the database and put them in a list as dictionary entries. But now I'm in a bit of a pickle - the first dictionary needs to get their keys replaced with the keys in the names list I created from the database (which keeps giving me errors). The only other solution that I can personally think of is to find a way to get the database names and put them directly into the dictionary as opposed to a blank list, but I can't figure out how to do that using loops.
empty_list = [] **# stores it as [{"name": name1}, {"name":, name2},...]**
for x in range(0, len(dict_key_array)):
data = {
"itm_num": dict_key_array[x]
}
mysql = connectToMySQL("app_database")
query = "SELECT name, price FROM items WHERE items.id = %(itm_num)s;"
pre_empty_list = mysql.query_db(query, data)
empty_list.append(pre_empty_list)
I've tried this so far in order to get the names to take their respective places in the original dictionary:
for k in order_data.keys(): **# go through each key of dictionary**
for x in range(0, len(order_data)): **# create a counter(? I think this would lead to duplicates, but I don't know how to avoid this)**
neym = empty_list[x]['name'] **# template debugger says: "TypeError: list indices must be integers or slices, not str"**
order_data[neym] = order_data[k]
del order_data[k]
I need to get the original dictionary of {'1': 9, '2': 5} (or one like it since this is based on an orders page and different orders will have different keys and values) to show up like {'pasta': 9, 'soda': 5} where 'pasta' and 'soda' are the names found in the database.
I'm not sure if all is correct but it could be
# --- get names ---
mysql = connectToMySQL("app_database")
query = "SELECT name, price FROM items WHERE items.id = %(itm_num)s;"
empty_list = [] # **stores it as [{"name": name1}, {"name":, name2},...]**
for item in dict_key_array:
result = mysql.query_db(query, {"itm_num": item})
empty_list.append(result)
# --- convert keys in order ---
order_data = {'1': 9, '2': 5}
for key in order_data:
index = int(key)-1 # convert str to int # key has value 1,2,3,... but list use 0,1,2,...
name = empty_list[index]['name']
order_data[name] = order_data.pop(key)
#del order_data[key] # .pop() will remove it
But probably you should keep name with itm_num as dict {itm_num1: {'name": name1}, itm_num2: {"name": name2} } or even {itm_num1: name1, itm_num2: name2}
# --- get names ---
mysql = connectToMySQL("app_database")
query = "SELECT name, price FROM items WHERE items.id = %(itm_num)s;"
empty_dict = dict() # **stores it as {itm_num1: {'name": name1}, itm_num2: {"name": name2} }**
for item_num in dict_key_array:
empty_dict[item_num] = mysql.query_db(query, {"itm_num": item_num})
# --- convert keys in order ---
order_data = {'1': 9, '2': 5}
for key in order_data:
name = empty_dict[key]['name']
order_data[name] = order_data.pop(key)
#del order_data[key] # .pop() will remove it
Maybe you could even get it in one query "SELECT id, name, price FROM items"
result = mysql.query_db("SELECT id, name, price FROM items")
for row in result:
empty_dict[row['id']] = row
but it will get all rows for database. But you can get it from database once and use empty_dict all the time with different orders.
I solved it:
empty_list = []
for x in range(0, len(dict_key_array), 2):
data6 = {
"itm_num": int(dict_key_array[x])
}
mysql = connectToMySQL("app_database")
query = "SELECT name, price FROM items WHERE items.id = %(itm_num)s;"
pre_empty_list = mysql.query_db(query, data)
empty_list.append(pre_empty_list[0]['name'])
new_dict = {}
counter = 0
while counter < len(dict_val_array):
for name in empty_list:
new_dict[name] = dict_val_array[counter]
counter+=1
session['new_dict'] = new_dict
Comments: I already had the dictionary of order items along with their quantities. I looped through that and put all the keys into a list, and put all the values into another list (dict_key_array and dict_val_array). What really changed this time around, however, was that instead of saving all my query results as a list, I specified which parts of my query results should be saved in the list, which is why I have above pre_empty_list[0]['name'], that would put the name alone in the list, and after this I used a while loop as a counter so that I enter each name in the list as a key and assign it the value found int he values list (dict_val_array).
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 table Food. It has fields: cust_name, phone_number , order_date
I am trying to build a dictionary where a key of pair (cust_name, phone_number) gives a list of order_date. For that I need to query appropriately in sqlalchemy. I'm using Postgres.
So far I have:
db.session.query(Food.cust_name, Food.phone_number).group_by(Food.cust_name, Food.phone_number).all()
What do I need to change so that I get a corresponding list of order_date
Use the array_agg() aggregate function to produce a list of order dates:
res = db.session.query(Food.cust_name,
Food.phone_number,
db.func.array_agg(Food.order_date).label('order_dates')).\
group_by(Food.cust_name, Food.phone_number).\
all()
the_dict = {(r.cust_name, r.phone_number): r.order_dates for r in res}
So I'm having difficulty with aggregating data within Python.
I wrote a program that extracts data from an Oracle DB and converts it into a list with dictionaries. Each dictionary contains the DB column names as keys
Looking something like this:
[{ColumnName1 : Value, Columnname2 : Value},
{ColumnName1 : Value, Columnname2 : Value}]
The problem I'm having is the redundant columnnames. From this list of dictionaries I would like to create a dictionary containing each column name as a key only once. After that adding a list of the values that belong to that columnname.
Any Ideas?
I'm using Cx_Oracle to extract the data from the DB.
I'm using the following code to create the list of dictionaries.
The reason I'm doing this is because Oracle_CX doesn't return column names, and I really need those.
The code to build the list of dictionaries:
def rows_to_dict_list(cursor):
columns = [i[0] for i in cursor.description]
return [dict(zip(columns, row)) for row in cursor]
Instead of:
def rows_to_dict_list(cursor):
columns = [i[0] for i in cursor.description]
return [dict(zip(columns, row)) for row in cursor]
Try:
def rows_to_dict_list(cursor):
columns = [i[0] for i in cursor.description]
out = {i[0]: [] for i in cursor.description}
for row in cursor:
for key, value in zip(columns, row):
out[key].append(value)
return out
Don't make that list of dictionaries in the first place; build up the dictionary.
def rows_to_lists_dict(cursor):
column_names = [i[0] for i in cursor.description]
columns = {name: [] for name in column_names}
for row in cursor:
for name, column in zip(column_names, row):
columns[name].append(column)
return columns
The previous way of storring your data was indeed not optimal due to the repetition of keys. Try this:
old = [{ColumnName1 : Value11, Columnname2 : Value21, ...}, {ColumnName1 : Value12, Columnname2 : Value22, ...}, ...]
new_dict = {}
for subdict in a:
for k, v in subdict.items():
new_dict.setdefault(k, []).append(v) # thanks to #volcano
print(new_dict) # {ColumnName1: [value11, value12, ...], ColumnName1: [value12, value22, ...], ...}
But to be honest, the best way would be not to build the list of dictionaries in the first place and to go for a dictionary of lists directly. Now to do that effectively one would have to know a bit more about the structure of your DB + I believe that you can do it on your own. Just correlate the indexes of the returned by the query tuples to the column names and you are done.
Hope I helped.
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)