There is such a dictionary:

{'Junior': {'Shoes': set(), 'Accessories': set()}, 'Men': {'Shoes': {'New Balance', 'Asics', 'adidas', 'Nike', 'Saucony', 'Jordan Brand', 'Puma', 'Reebok Classic'}, 'Accessories': {'socks', 'Hats', 'bags'}}, 'Women': {'Shoes': {'Converse', 'Reebok Classic', 'adidas', 'Nike'}, 'Accessories': {'backpacks'}}} 

Which is generated here by such a dictionary generator:

  q = Products.query genders = q.filter(Products.gender !=0).group_by(Products.gender) categories = q.filter(Products.category != 0, Products.category != 'Clothing').group_by(Products.category).all() gen = {gender.gender: {category.category: {subcategory.subcategory for subcategory in q.filter(Products.gender == gender.gender, Products.category == category.category, Products.subcategory != 0).group_by(Products.subcategory)} for category in categories} for gender in genders} 

I'm not sure that the generator is written correctly, but it works almost as it should.

I tried to use #gen = defaultdict(lambda:None,gen) but then I realized that it works according to a different principle.

The fact is that in the database there are really no elements satisfying the selection condition (filter), so this is the picture {'Junior': {'Shoes': set(), 'Accessories': set()}

Such a dictionary can not be parsed, nor lead to JSON, again, because of set()

The task is to write None or False instead of set ().

  • It is possible either when generating or after it to bring the sets to lists, then it will normally be converted to json. - insolor
  • @insolor, do not quite understand how to do it. - Narnik Gamarnik

1 answer 1

It is possible either at generation or after it to bring the set 's to the lists, then it will normally be converted to json.

Option 1 - generate lists immediately if there are no repetitions in the original sequences. Just change the braces in one of the generators to square:

 gen = { gender.gender: { category.category: [ subcategory.subcategory for subcategory in q.filter(Products.gender == gender.gender, Products.category == category.category, Products.subcategory != 0).group_by(Products.subcategory) ] for category in categories } for gender in genders } 

Option 2 - if subcategories are possible to repeat, then simply wrap the set 'generator and in the list(...) :

 gen = { gender.gender: { category.category: list({ subcategory.subcategory for subcategory in q.filter(Products.gender == gender.gender, Products.category == category.category, Products.subcategory != 0).group_by(Products.subcategory) }) for category in categories } for gender in genders } 

3 option - to bring the sequence of subcategories to the lists after the generation, but I am too lazy to implement it)

The result will be something like this:

 {'Junior': {'Shoes': [], 'Accessories': []}, 'Men': {'Shoes': ['New Balance', 'Asics', 'adidas', 'Nike', 'Saucony', 'Jordan Brand', 'Puma', 'Reebok Classic'], 'Accessories': ['socks', 'Hats', 'bags']}, 'Women': {'Shoes': ['Converse', 'Reebok Classic', 'adidas', 'Nike'], 'Accessories': ['backpacks']}} 

which is great on json:

 >>> json.dumps(s) '{"Women": {"Shoes": ["Converse", "Reebok Classic", "adidas", "Nike"], "Accessories": ["backpacks"]}, "Junior": {"Shoes": [], "Accessories": []}, "Men": {"Shoes": ["New Balance", "Asics", "adidas", "Nike", "Saucony", "Jordan Brand", "Puma", "Reebok Classic"], "Accessories": ["socks", "Hats", "bags"]}}' 

Update. In case you need to insert None instead of empty set 's, you can use the property that empty set in logical expressions is equivalent to False , and if the left argument of the or operator is false, the right argument will return, i.e. set() or None is None :

 gen = { gender.gender: { category.category: { subcategory.subcategory for subcategory in q.filter(Products.gender == gender.gender, Products.category == category.category, Products.subcategory != 0).group_by(Products.subcategory) } or None for category in categories } for gender in genders }