Building a tuple to be rendered by a form - python

I have a model University which has a field city. I'm trying to build a form where the user can select cities or universities. The universities selection is fine:
universities = University.objects.all()
university = forms.ModelMultipleChoiceField(widget=CheckboxSelectMultiple, queryset=universities)
The method I'm trying to get the cities is what is causing me the problem. Here's what I currently have:
cities = []
for uni in universities:
cities.append(uni.city)
cities = tuple(cities)
city_select = forms.MultipleChoiceField(widget=CheckboxSelectMultiple, choices=cities)
This gives me the error too many values to unpack because the tuple isn't key paired. Is there any easier way to return the choices I've gathered, I feel like I'm going about it in the wrong way. If not, how do I key pair the tuples of cities?

I think a simple change like below, where each entry in cities is a tuple should make this work:
cities = []
for uni in universities:
cities.append((uni.city, uni.city))
cities = tuple(cities)
city_select = forms.MultipleChoiceField(widget=CheckboxSelectMultiple, choices=cities)

MultipleChoiceField doesn't want a tuple, it wants a queryset. You can use values_list to get one with the fields you want:
city_select = forms.MultipleChoiceField(widget=CheckboxSelectMultiple, queryset=University.objects.values_list('id', 'city'))

Related

Django: get users' IDs with field

I have a model, for example:
class Person(models.Model):
name =
surname =
city =
cars =
I need to get a list of the IDs (primary key auto-set) of the 5 users with the highest number of "cars" with a specific name.
I thought I could do something like:
list = Person.objects.filter(name=name,)('-reputation')[5].id
To get a list of the 5 users with the highest number you can use:
list = Person.objects.filter(name=name).order_by('-reputation')[:5]
to get the ID of each you can use for loop:
for user in list:
userID = user.id
You seem to have missed out the call to order_by.
Person.objects.filter(name=name).order_by('-reputation')[5].id
Using the values_list queryset function can reduce this to a single simple line:
Person.objects.values_list('id', flat=True).filter(name=name).order_by('-reputation')[:5]
and will avoid needing to loop.

sorting multi-language country names

I have a list of country names in different languages that I am attempting to sort by their country name. Currently, the sort is based on the index value.
Here is my truncated list of country names:
ADDRESS_COUNTRY_STYLE_TYPES = {}
for language_code in LANGUAGES.iterkeys():
ADDRESS_COUNTRY_STYLE_TYPES[language_code] = OrderedDict()
if 'af' in LANGUAGES.iterkeys():
ADDRESS_COUNTRY_STYLE_TYPES['af'][0] = " Kies 'n land of gebied" # Select a country or territory
ADDRESS_COUNTRY_STYLE_TYPES['af'][1] = "Afganistan" #Afghanistan
ADDRESS_COUNTRY_STYLE_TYPES['af'][2] = "Åland" #Aland
ADDRESS_COUNTRY_STYLE_TYPES['af'][3] = "Albanië" #Albania
....
ADDRESS_COUNTRY_STYLE_TYPES['af'][14] = "Australië" #Australia
ADDRESS_COUNTRY_STYLE_TYPES['af'][15] = "Oostenryk" #Austria
ADDRESS_COUNTRY_STYLE_TYPES['af'][16] = "Aserbeidjan" #Azerbaijan
ADDRESS_COUNTRY_STYLE_TYPES['af'][17] = "Bahamas" #Bahamas
ADDRESS_COUNTRY_STYLE_TYPES['af'][18] = "Bahrein" #Bahrain
ADDRESS_COUNTRY_STYLE_TYPES['af'][19] = "Bangladesj" #Bangladesh
ADDRESS_COUNTRY_STYLE_TYPES['af'][20] = "Barbados" #Barbados
ADDRESS_COUNTRY_STYLE_TYPES['af'][21] = "Wit-Rusland" #Belarus
ADDRESS_COUNTRY_STYLE_TYPES['af'][22] = "België" #Belgium
....
Here is my code I have in my views.py file that calls the country names:
def get_address_country_style_types(available_languages, with_country_style_zero=True):
address_country_style_types = {}
preview_labels = {}
for code, name in available_languages:
address_country_style_types[code] = ADDRESS_COUNTRY_STYLE_TYPES[code].copy()
if not with_country_style_zero:
address_country_style_types[code].pop(0)
preview_labels[code] = ADDRESS_DETAILS_LIVE_PREVIEW_LABELS[code]
# in case preview labels are not defined for the language code
# fall back to 'en', which should always be there
if len(preview_labels[code]) == 0:
preview_labels[code] = ADDRESS_DETAILS_LIVE_PREVIEW_LABELS['en']
address_country_style_types = sorted(address_country_style_types, key=lambda x:x[1])
return address_country_style_types, preview_labels
The above code only returns the index number in the html drop down list. The issue is with the following line of code (or more to the point my lack of knowledge of how to get it working):
address_country_style_types = sorted(address_country_style_types, key=lambda x:x[1])
How do I return the sorted country list ? Am I using lambda in the correct way here? Should I be using lambda here?
I have been working on this over several days, my coding skills are not very strong, and I have read many related posts to no avail, so any help is appreciated.
I have read this blog about sorting a list of multilingual country names that appear in a form HTML select drop down list - which is essentially what I am attempting to do.
EDIT
Commenting out the line of code below in the code above does return a list of country names, but the country names are sorted by the index value not the country name.
address_country_style_types = sorted(address_country_style_types, key=lambda x:x[1])
I have failed to sort the multi-language country names programatically.
Instead, I copied the list into excel and hit the sort button (based on the translated country name - the index value stays uniform), then copied the data back to the file. Works as expected - just a lot of work.
I hope that this helps someone.

SQLAlchemy Flask, match some or all

I have a list of schools (1000's) with a name, city, and state.
There are name, city and state input fields.
I want to search for schools by name. If they leave city or state inputs empty I want to search by any city, any state. If they enter the city (leaving state blank) then search by name and city. Etc etc.
Bottom line: Search with the data that is available and everything else is "any".
Is there a quick way to do this other than writing every possible combination?
I'm writing this as if you're using Flask-SQLAlchemy and WTForms.
...
schools = School.query
if form.name.data:
schools = schools.filter(School.name == form.name.data)
if form.city.data:
schools = schools.filter(School.city == form.city.data)
if form.state.data:
schools = schools.filter(School.state == form.state.data)
# at this point schools is a query filtered with whatever was given
...
This is just an example, reword it, use filters besides equality, etc. I have "filter forms" like this, and would put extra methods on the form, query() and filter(query). Then they can be called like this in a view:
form = FilterForm(request.args) # use get for filtering
schools = form.query()
if form.validate():
schools = form.filter(schools)
return render_template('schools.html', form=form, schools=schools)

Django, filter and group query results by a field

I have this working but I'm sure there must be a better method
The context is a movie/television app so there are titles (movies/tv) and people who act in each, many to many relationship.
I have a "titlepeople" model with information such as:
id, people_fk, title_fk, role_title
On movies where a cast member has alot of roles I need to display their information like:
Tom Hanks: Gardener, Police Man #1, Another Role #4
Is there anyway I can optimize the below way of doing this so the code isn't so lengthy?
cast_unique = list()
for person in cast:
#if not in the unique list, add them
if person.people not in [p.people for p in cast_unique]:
cast_unique.append(person)
else:
# if in the list, append the role information
if person.role_title:
for c in cast_unique:
if c.people == person.people:
# append role info
c.role_title = '{0} / {1}'.format(c.role_title, person.role_title)
Thanks
You should change cast_unique to be a dictionary where you use the cast member as the key. This will allow much greater performance because you won't have to iterate the cast_unique iterable.
Also, your use a list comprehension in the if person.people not in [p.people for p in cast_unique]: requires an entire list to be create of people for every iteration for the test; which, could use a lot of memory plus there's no way to short circuit the list comprehension when a match occurs. Still a dictionary is a much better data type to use for this situation.
cast_unique = {}
for person in cast:
if person.people not in cast_unique:
cast_unique[person.people] = person
else:
cast_unique[person.people].role_title = '{0} / {1}'.format(cast_unique[person.people].role_title, person.role_title)

Need help parsing XML with ElementTree

I'm trying to parse the following XML data:
http://pastebin.com/UcbQQSM2
This is just an example of the 2 types of data I will run into. Companies with the needed address information and companies without the needed information.
From the data I need to collect 3 pieces of information:
1) The Company name
2) The Company street
3) The Company zipcode
I'm able to do this with the following code:
#Creates list of Company names
CompanyList = []
for company in xmldata.findall('company'):
name = company.find('name').text
CompanyList.append(name)
#Creates list of Company zipcodes
ZipcodeList = []
for company in xmldata.findall('company'):
contact_data = company.find('contact-data')
address1 = contact_data.find('addresses')
for address2 in address1.findall('address'):
ZipcodeList.append(address2.find('zip').text)
#Creates list of Company streets
StreetList = []
for company in xmldata.findall('company'):
contact_data = company.find('contact-data')
address1 = contact_data.find('addresses')
for address2 in address1.findall('address'):
StreetList.append(address2.find('street').text)
But it doesn't really do what I want it to, and I can't figure out how to do what I want. I believe it will be some type of 'if' statement but I don't know.
The problem is that where I have:
for address2 in address1.findall('address'):
ZipcodeList.append(address2.find('zip').text)
and
for address2 in address1.findall('address'):
StreetList.append(address2.find('street').text)
It only adds to the list the places that actually have a street name or zipcode listed in the XML, but I need a placemark for the companies that also DON'T have that information listed so that my lists match up.
I hope this makes sense. Let me know if I need to add more information.
But, basically, I'm trying to find a way to say if there isn't a zipcode/street name for the Company put "None" and if there is then put the zipcode/street name.
Any help/guidance is appreciated.
Well I am going to do a bad thing and suggest you use a conditional (ternary) operator.
StreetList.append(address2.find('street').text if address2.find('street').text else 'None')
So this statement says return address2.find('street').text if **address2.find('street') is not empty else return 'None'.
Additionally you could created a new method to do the same test and call it in both places, note my python is rusty but should get you close:
def returnNoneIfEmpty(testText):
if testText:
return testText
else:
return 'None'
Then just call it:
StreetList.append(returnNoneIfEmpty(address2.find('street').text))

Categories

Resources