processing form with multiple selection options - python

I have a cgi script that contains a select box where the end user can submit multiple options or only one option. This selection tag is named "parameters". See here for an example....
http://www.w3schools.com/tags/tryit.asp?filename=tryhtml_select_multiple
When this form is submitted with multiple options selected the URL looks something like this...
http........mycgiscript.py?parameters=option1value&parameters=option2values
or if the user only selected one option it looks like this...
http........mycgiscript.py?parameters=option3value
My form is declared as...
import cgi
form = cgi.FieldStorage()
So when the user selects multiple options and submits the form, the data type of form['parameters'] is a list, however, when the user only selects one option and submits, the data type of form['parameters'] is an instance...
Multiple Options (returned as list):
[MiniFieldStorage('parameters', 'option1value'), MiniFieldStorage('parameters', 'option2value')]
Single Option (returned as instance):
MiniFieldStorage('parameters', 'option3value')
My question is....
Since the form['parameters'] can be a list or instance depending on what the user submits; what is the best way to process these two data types ? The output I want is a list variable containing the optionsXvalues selected on the form. So far the best I can do is this...
if type(form['parameters']) == type([]):
l = [ x.value for x in form['parameters'] ]
else:
l = [form['parameters'].value]
I've done it this way because simply using form['parameters'].value produces the following exception when the user selects multiple options.
AttributeError: 'list' object has no attribute 'value'
So is there a better way than my if/else statement based suggestion above? I was hoping some of you python guru's would be able to suggest a better way to do this.

What you could do is use:
form.getlist('parameters')
This provides the value of all the different input types with the same name, namely parameters.
This is what i gathered from http://docs.python.org/2/library/cgi.html in 20.2.2 where they suggest this is the case when you expect there could be multiple items with the same name field.
Hope this helps though i reckon you already found this yourself.

Related

Can you access a parent field from a child object in Django?

tl;dr: I want to express something like [child.child_field_value, child.parent_field_value] on a Django child model and get an iterable like ['Alsatian', 'Dog'] or similar.
Context: I'm trying to prepare a dict for a JSON API in Django, such that I have two models, Evaluation and its parent Charity.
In the view I filter for all Evaluations meeting certain parameters, and then use a dict comp nexted in a list comp on evaluation.__dict__.items() to drop Django's '_state' field (this isn't the focus of this question, but please tell me if you know a better practice!):
response = { 'evaluations': [{
key:value for key, value in evaluation.__dict__.items()
if key not in ['_state']} for evaluation in evaluations]}
But I want a good way to combine the fields charity_name and charity_abbreviation of each Evaluation's parent charity with the rest of that evaluation's fields. So far the best way I can find/think of is during the dict comp to conditionally check whether the field we're iterating through is charity_id and if so to look up that charity and return an array of the two fields.
But I haven't figured out how to do that, and it seems likely to end up with something very messy which isn't isn't functionally ideal, since I'd rather that array was two key:value pairs in line with the rest of the dictionary.

How to set reverse argument in sort_url in Flask table through Python without JS or HTML modifications of table?

Given the following table
class ProductsTable(Table):
allow_sort=True
id=Col('ID', show=False)
price=Col('Price')
available_online=Col('Available online?')
available_num=Col('In stock')
edit=ButtonCol('Edit', url_kwargs=dict(id='id'), endpoint='/products')
def sort_url(self, col_id, reverse=False):
if reverse:
order = 'desc'
else:
order = 'asc'
return '?sort={}&order={}'.format(col_id, order)
From this I get the following example paths:
http://localhost:5000/products?sort=price&order=asc
http://localhost:5000/products?sort=available_num&order=asc
I use the parameters to generate an SQL query, which I execute on my SQLite DB and render the respective sorted table.
Now my issue comes from the reverse argument in my sort_url. I am unable to find any example that doesn't have it as optional argument and hence I'm unable to find anything that tells me how this argument can be set.
Of course I can always alter the URL. For the two examples above this would mean
http://localhost:5000/products?sort=price&order=desc
http://localhost:5000/products?sort=available_num&order=desc
However I want the order to change whenever the user clicks on the head of the specific table column.
How do I do that? Do I have to employ the actual HTML (and also add JavaScript) or is it possible to do it through Flask. Tables I've seen online normally have the arrows up/down symbol
that, whenever clicked, toggle the sorting order.
This involves JS and HTML modifications. I'd like to stick to Flask and Python if possible. The way Flask tables currently seem to work is a click cannot toggle the value of reverse.
Even if I expose the reverse parameter to the constructor of my own table like this
def __init__(self, items, reverse):
super().__init__(items, sort_reverse=reverse)
so that I can set it depending on the value extracted from the URL, my question how to actually set the value remains unanswered.

LDAP Query Filter User's with Groups Like *x*

I'm currently using Python and LDAP to query Active Directory for users.
I have a list of names that are First Last. Not specific enough to find the exact user.
I would like a filter that would find all users matching 'Last, First*'
and belonging to any group with a keyword in it.
_filter = '''(& (objectclass=user)
(objectcategory=person)
(name={}*) )'''.format(search_string)
and I've tried adding...
(memberOf=CN=*Keyword*,OU=Delegated,OU=Groups,DC=amr,DC=corp,DC=xxxxxx,DC=com)
To my filter, but with no success.
If this was SQL, I would write something like:
Select *
From
Users
Where
Users.name like 'First, Last%'
and Users.memberOf like 'Keyword%'
Update:
After reviewing Gabriel's answer I'm running this.
def get_idsids(self, search_string):
_filter = '''(& (objectclass=user)
(objectcategory=person)
(anr={}) )'''.format(search_string)
# Search for user.
# Will return list of users matching criteria.
# The results are wrapped up as a list(tuple(dict))) where the dict vals are binary strings or lists of binary strings.
users = self.con.search_s(ActiveDirUser.BASEDN, ldap.SCOPE_SUBTREE, _filter, ['displayName', 'sAMAccountName', 'memberOf'])
# This line is ugly... It just converts the results to a list of ids
# So long as the user has at least one group with 'Keyword' in the name.
# upper() is used to make the Keyword requriement case insensitive.
return [user[1]['sAMAccountName'][0].decode() for user in users if 'KEYWORD' in ''.join(map(str, user[1]['memberOf'])).upper()]
I do wonder though, could I search for groups with 'Keyword' in the name and build filters from that? Further, would that be faster? I assume it would as AD probably hashes group membership.
I will go do some reading, but I assume group names are wildcard searchable?
I suggest you use Ambiguous Name Resolution:
_filter = '''(& (objectclass=user)
(objectcategory=person)
(anr={}) )'''.format(search_string)
Read that documentation to understand how it works, but it can find users if you give it a string of "first last". This is what the search box in AD Users and Computers uses.
Just be aware that you can get doubles if people have similar names. If you take my name for example: if you would search for "Gabriel Luci", and there was someone else with the name "Gabriel Luciano", you would find both of us.
This:
(memberOf=CN=*Keyword*,OU=Delegated,OU=Groups,DC=amr,DC=corp,DC=xxxxxx,DC=com)
doesn't work because you can't use wildcards on any attribute that is a distinguishedName, like memberOf.
That's for Active Directory anyway. Other LDAP directories might allow it.
If you need to check if the users are members of groups, then you can tell your search to return the memberOf attribute in the search (I don't know phython, but you should have a way of telling it which attributes you want returned). Then you can loop through the groups in the memberOf attribute and look for that keyword.

Getting POST values from a Django request when they start with the same string

I have a form on my site that allows the user to add names to an object. The user can hit a plus button to add another name or a minus button to remove a name. I need to be able to easily pull all POST variables that start with a name.
For example. A user adds two names so we have two text boxes names 'name0' and 'name1'. Is there a way that I can pull those two values without know how many I may have?
One reason I want to do this without knowing is because they could do any number of add and remove functions on the list of names. So I could end up with this:
'name2', 'name10', 'name11'
for the names that come in. I don't want to have to know the exact values. I just want to pull all POST variables that start with 'name'.
Is this possible?
You could iterate through all POST elements and just keep the ones starting with 'name':
names = [v for k, v in request.POST.items() if k.startswith('name')]
but that's really the wrong way to do it. You shouldn't be calling your fields different names at all: just have all the fields as 'name'. HTTP happily posts all the data as different elements of the same variable, and you can get them back in Django via request.POST.getlist('name').
yeah, like Daniel said, so I add the next
posted = [{k.replace('person__',''):v} for k, v in request.POST.items() if k.startswith('person__')]
then I can use a model form with posted data

writing to model field in django / python

i'm trying to populate custom user profile fields with data from social networks. i created profile fields like:
currentjobtitle1
currentjobtitle2
currentjobtitle3
pastjobtitle1
pastjobtitle2
pastjobtitle3
I'm a newb in every way, so i tried to code this more efficiently than normal and have become very confused. I'm sure my code is wrong in more ways than one, but if i can just get it to work:
pnum=0
cnum=0
for x in clean_work_obj[:]:
if x['end_date']:
var='past'
count=pnum+1
else:
var='current'
count=cnum+1
if count>3:
break
else:
SarProfile.var+'jobtitle'+str(count)= x['position']['name']
clean_work_obj is the dict i received thru the social network api.
I had expected it to write out: SarProfile.pastjobtitle1 or SarProfile.currentjobtitle3, for example, and populate that field with the "position / name" data. it breaks because there is no field called "var" in SarProfile.
setattr(SarProfile, '%sjobtitle%d' % (var, count), x['position']['name'])
But you probably want to create an instance of SarProfile first, and use that instead.

Categories