Dynamic querysets?

48 views
Skip to first unread message

Malik Rumi

unread,
Dec 16, 2016, 6:19:38 PM12/16/16
to Django users

I already got one fast and helpful answer today, so I’m going to be greedy and press my luck.


I have this website. Each state has their own home/landing page off the site’s main page, and from there you will be able to get detail pages about various tidbits about the state of your choice. I have implemented this with a urlconf that looks for the state’s 2 digit postal name:


 url(r'^(?P<twodigit>[A-Z]{2})', include('bench.urls', namespace=twodigit)),

It will come as no surprise that the views and templates associated with each state are identical. However, in order to be DRY, I wanted the view to take the twodigit argument from the url and call the right state’s queryset. To this end, I created a dict

{'AK': 'Alaska',
'AL': 'Alabama',
'AR': 'Arkansas',
...etc…}


naively thinking I would be able to do something like


for k,v in statedict:
 
if twodigit == k:
 state
= Jurisdiction.objects.get(v)


However, this does not work. I’m not sure why. Here are some of the various results I’ve gotten as I tried tweaking it:

for k,v in statedict:
 
if 'VA' == k: # I was thinking of this as almost a default value
 state
= Jurisdiction.objects.get(v)


However, this gets an unbound local error because of the scope, and I don’t know how to assign the variable so that it is accessible outside the scope of the for loop.


k='NE'
print(v)
k
=="US"
print(v)


returned


U
U


Clearly, there is no ‘U’ in Nebraska, so I don’t know what happened there.


This works


print(statedict['US'])
(aishah) malikarumi@Tetuoan2:~/Projects/aishah/jamf35$ python statedict.py
United States


But this does not


File "statedict.py", line 63, in <module>
 
if statedict['k']:
KeyError: 'k'


And this


for k, v in statedict:
 
if k:
 
print('v')


Gets me a ‘v’ for every state.


Variations on


Jurisdiction.objects.filter(statedict[’v']) and
 Jurisdiction.objects.filter(name='
v’)


also failed, and nothing I have found on the internet has helped. Ideas?

Peter of the Norse

unread,
Dec 16, 2016, 7:00:38 PM12/16/16
to django...@googlegroups.com

you are looking for `statedict.items()`.  (Or `statedict.iteritems()` on py2)  By default a dict just loops over the keys.  And then it unpacks your two letter string into k, v.  So the first step of your loop is k='A' and v='K'.

Also, that's not how you use get.

orz...@neomailbox.ch

unread,
Dec 16, 2016, 7:49:53 PM12/16/16
to Malik Rumi, Django users
In your single view that processes every state I would define the
queryset you're interested in:

state_infos = {
# 'Explicit is better than implicit.'
'AK': Jurisdiction.objects.get('Alaska'),
'AL': Jurisdiction.objects.get('Alabama'),
}

Then in the view:

try:
state_data = state_infos[twodigit]
except KeyError:
# something not defined in your dict was entered.
from django.contrib import messages
messages.error(request, "That state hasn't been accepted into the "
"union yet. Try again.")
return HttpResponseRedirect(my_index)


To answer your question more directly, I think what is happening is
you're confusing your variables with your strings.

for k, v in statedict:
if k:
print('v')

This will return 'v' for everything because v is a string. What you
probably meant to do is print the value of each element.

for k, v in statedict:
if k:
print(v)



Hope that helps

- Orin
> --
> You received this message because you are subscribed to the Google Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
> To post to this group, send email to django...@googlegroups.com.
> Visit this group at https://groups.google.com/group/django-users.
> To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/8bc1bfcb-4de5-45c9-b447-d1290e20c4d7%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Andrew Beales

unread,
Dec 24, 2016, 2:35:12 AM12/24/16
to Django users
You can pass strings from URLs as arguments into your Django view functions.

Assuming your Jurisdiction model already has a "name" field, make sure it also has a "postal_code" field (consider renaming the model State?)

Your urls and views can be something like:

# urls.py
url
(r'^(?P<state_code>[A-Z]{2})', views.state_home, name="state_home"),

#views.py
def state_home(request, postal_code):
    state
= Jurisdiction.objects.get(postal_code=postal_code)
   
return render(request, 'mystatetemplate.html', {'state': state})


If you want to have several state-related pages then put the URLs in a dedicated "states" app or similar and 'include' it from your top level URLs file, eg.  url(r'^states/', include('states.urls'))

Andrew Beales

unread,
Dec 24, 2016, 2:39:45 AM12/24/16
to Django users
typo:

# urls.py
url
(r'^(?P<postal_code>[A-Z]{2})', views.state_home, name="state_home"),
Reply all
Reply to author
Forward
0 new messages