Last active
August 29, 2015 14:10
-
-
Save SmileyChris/6be4815cf5751a4ae9ed to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
array_qs = re.compile(r'(\w+)\[(\d*)\]$') | |
class UnPHPify(object): | |
def process_request(self, request): | |
""" | |
Iterate request.GET, request.POST and request.FILES and amend the dict | |
with lists for any PHP-style arrays. | |
""" | |
self.process_request_attr(request, 'GET') | |
self.process_request_attr(request, 'POST') | |
self.process_request_attr(request, 'FILES') | |
def process_request_attr(self, request, attr): | |
multi_value_dict = getattr(request, attr) | |
if not multi_value_dict: | |
return | |
# request.GET and .POST are QueryDicts that are usually immutable. | |
immutable = not getattr(multi_value_dict, '_mutable', True) | |
new_dict = self.process_multi_value_dict(multi_value_dict, immutable) | |
if not new_dict: | |
return | |
if immutable: | |
multi_value_dict._mutable = False | |
setattr(request, attr, multi_value_dict) | |
def process_multi_value_dict(self, multi_value_dict, immutable=False): | |
""" | |
Add keys to the dictionary containing lists if PHP-style arrays are | |
found in the multi-value dictionary. | |
Processes both indexed ("names[2]") and unordered ("aliases[]") arrays. | |
For example:: | |
>>> from django.request import QueryDict | |
>>> q = QueryDict('names[2]=chris&names[1]=joe', mutable=True) | |
>>> UnPHPify().process_multi_value_dict(q).getlist('names') | |
['joe', 'chris'] | |
""" | |
indexed_lists = {} | |
unindexed_lists = {} | |
for key, value in multi_value_dict.items(): | |
match = array_qs.match(key) | |
if not match: | |
continue | |
name, index = match.groups() | |
# If the un-arrayed name exists already in the dict, skip it. | |
if name in multi_value_dict: | |
continue | |
if index: | |
indexed_list = indexed_lists.getdefault(name, {}) | |
indexed_list[int(index)] = value | |
else: | |
unindexed_list = unindexed_lists.getdefault(name, []) | |
unindexed_list.append(value) | |
if not indexed_lists and not unindexed_lists: | |
return | |
if immutable: | |
multi_value_dict = multi_value_dict.copy() | |
# First, iterate the indexed lists and make lists of the correct length | |
# then populate them with the indexed array values. | |
for name, ordered_values in indexed_lists.items(): | |
new_list = unindexed_lists.getdefault(name, []) | |
extra = max(ordered_values) - len(new_list) | |
if extra > 0: | |
new_list += [None] * extra | |
for index, value in ordered_values.items(): | |
new_list[index] = value | |
# Now fill the dictionary with all populated lists. | |
for name, new_list in unindexed_lists.items(): | |
multi_value_dict.setlist(name, new_list) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment