16

I was doing django project about processing request.data and from.cleaned_data issues. When user only inputs specify fields, it will send request to my server. Next, the form class process the request, except processing inputed fields and return no inputted fields from form built-in fields.

This is request data:

<QueryDict: {u'is_public': [u'True']}>

This is cleaned data from from class:

{'name': u'', 'devie_type': u'', 'is_public': True, 'serial_num': u'', 'is_online': False, 'operation_system': u''}

I know these are dictionary type. I hope getting their union keys of them and values of cleaned data. I expect that it returns:

{u'is_public': True}

This is my attempt:

a = {}
for k in request.data:
    if k in the_form.cleaned_data:
        a[k] = the_form.cleaned_data[k]
print a

Is it readable? or is there any built-in functions about processing union dictionary in python?

Burger King
  • 2,945
  • 3
  • 20
  • 45

3 Answers3

8

You can use intersection operations (which sounds like what you really want, not union) to efficiently limit iteration to keys common to both dicts, then use a dict comprehension to achieve this fairly efficiently:

a = {k: the_form.cleaned_data[k]
     for k in request.data.viewkeys() & the_form.cleaned_data.viewkeys()}

So when a key exists in both the request and the cleaned data, you'll have a mapping from that key to the cleaned data. All other keys that appear in only one input dict or the other are dropped. In Python 3, you'd replace .viewkeys() with just .keys() (and this won't work before Python 2.7, which is where .viewkeys() was introduced).

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • Let me edit my problem. My environment is `python-2.7` – Burger King Oct 28 '15 at 03:11
  • @BurgerKing: I assumed it was. This will work just fine with `.viewkeys()` on Python 2.7, I just included the Python 3 differences for completeness. – ShadowRanger Oct 28 '15 at 03:12
  • list and list can do union? or is it available on python3? – Burger King Oct 28 '15 at 03:15
  • `.viewkeys()` is not a `list`, it's a special "keys view" object, that is set-like live view of the `dict`'s keys. In Python 3, `.keys()` is the same as Py 2.7's `.viewkeys()` (`.iterkeys()` and the Py2-style `.keys()` returning `list` are removed; the views already iterate, and you can just wrap `.keys()` calls in the `list` constructor if you need an actual `list`). – ShadowRanger Oct 28 '15 at 03:19
  • @BurgerKing: You can see more details at [What's new in Python 3.0: Views and iterators instead of lists](https://docs.python.org/3/whatsnew/3.0.html#views-and-iterators-instead-of-lists), which describes how many built-ins went from producing `list`s to producing views or iterator/generator objects, to reduce the creation of unnecessary intermediate data copies. – ShadowRanger Oct 28 '15 at 03:21
  • Oh, I see. I have read python 3 document as you said. I appreciate your answer. I had upvote for you. – Burger King Oct 28 '15 at 03:22
3

There's nothing inherently wrong with what you're doing, all totally fine. However, the more pythonic way to do this would be to use a dictionary comprehension:

a = {
   k: the_form.cleaned_data[k]
   for k in request.data
   if k in the_form.cleaned_data
}
dursk
  • 4,435
  • 2
  • 19
  • 30
  • Great! It's my wanted. – Burger King Oct 28 '15 at 03:09
  • 1
    This is the same basic concept as my answer, though it won't allow Python to optimize for cases where the request.data dict is large and the cleaned_data is small (because it must loop and check them all, where intersection operations can choose to iterate the smaller input and membership test the larger input, to reduce the work to the lesser of the two inputs' lengths). – ShadowRanger Oct 28 '15 at 03:11
0

just do: request_data.update(form.cleaned_data)

labheshr
  • 2,858
  • 5
  • 23
  • 34
  • Sorry, the return is not my expect: `` – Burger King Oct 28 '15 at 03:01
  • i modified my answer a couple of times..which one did you try out? – labheshr Oct 28 '15 at 03:03
  • Please check your code before posting your answer. My expectation is `{u'is_public': True}` – Burger King Oct 28 '15 at 03:06
  • your question's title is misleading...my answer correctly posts the union of two dicts with request_data getting the right value of public **in addition** to contents of cleaned_data - which is what union means...also this question is closed in favor of a question that allows for **union** of two dicts, not exactly what you want .... – labheshr Oct 28 '15 at 03:10
  • run this as is and you'll see what i mean : request_data = {u'is_public': [u'True']} cleaned_data = {'name': u'', 'devie_type': u'', 'is_public': True, 'serial_num': u'', 'is_online': False, 'operation_system': u''} request_data.update(cleaned_data) print request_data – labheshr Oct 28 '15 at 03:11