Search code examples
pythondjangodjango-2.0django-2.1

Adding values to Django QuerySet


Is there any way to append a non-Django supplied value to a query?

For instance, to find out if a store closed, I may run a function called get_closed_stores() which returns a list of closed stores.

Stores Closed

[00090, 00240, 00306, 00438, 03005, 05524]

Great, now we have store numbers for stores that are closed. Lets get those actual store objects.

Query

Store.objects.filter(
store_number__in=[00090, 00240, 00306, 00438, 03005, 05524]
)

We now have the QuerySet, but we have absolutely no way to detect when the store closed, because the database doesn't contain any information about emergency closings, but Sharepoint does. So back at get_closed_stores() we can return the Date Closed alongside the store number so our Closed Stores List (dictionary) would look more like below:

Store List with Dates

{
    [00090, '1/28/19 5:00PM'], 
    [00240,'1/28/19 5:00PM'], 
    [00306, '1/28/19 5:00PM'], 
    [00438,'1/28/19 5:00PM'], 
    [03005,'1/28/19 5:00PM'], 
    [05524, '1/28/19 5:00PM']
}

Now that the dates are with my store numbers, I can add this to my Queryset (ideally) and access it from my front end.

So annotate() would be ideal here if I were working with anything Django ORM related, but when it comes to "injecting" external data, what is it I'm looking for?

I can absolutely just make the call for each store from JS on my front end but I would rather not if I can get around it


Solution

  • A QuerySet in itself isn't anything magical or special, in the end its still a dictionary, so I had the random notion to append to the dictionary the way I typically would, and it worked.

    My function is now returning a dictionary:

    { "store_number": "close_date" }
    

    My view takes this dictionary and uses the keys (store numbers) to Query the database and then appends the store's close date as store.close_date by simply saying:

    store.close_date = store_list[store_number]
    

    This is likely to change, but I want to keep it close to the original question to make it readable for future readers. Below is my view.

    @login_required
    def store_closures(request):
        store_list = get_closed_stores()
        store_nums = store_list.keys()
        closed_stores = Store.objects.filter(store_number__in=store_nums)
        for store in closed_stores:
            store.close_date = store_list["{:05d}".format(store.store_number)]
        return render(request, 'all_store_closures.html', {'closed_stores':closed_stores})
    

    So if you want to add a non Django value to a queryset, you can just use the standard method of appending to a dictionary.

    for obj in query:
        obj.desired_name = 'desired_value'
    

    Which is, of course, accessed using {{ object.desired_name }} from your template.