9

I am trying to create a dict with key as name and value as corresponding User object.

I am using Python shell from Django shell wrapper python manage.py shell:

>>> from django.contrib.auth.models import User
>>> names = ['carl', 'jim', 'jack', 'john', 'mark']
# Now using some dict comprehension
>>> u = {name: User.objects.get(username=name) for name in names}
NameError: global name 'User' is not defined

However, this works for me:

u = {}
for name in names:
    u[name] = User.objects.get(username=name)

And I get the desired output, which is:

{ 
  'carl': <User: carl>,
  'jack': <User: jack>,
  'jim' : <User: jim>,
  'john': <User: john>,
  'mark': <User: mark>
}

I know, there are other ways to accomplish this, but I am curious why are the dict comprehensions not working here.

Any tips?
Am I missing something here?

I159
  • 29,741
  • 31
  • 97
  • 132
Dhruv Baldawa
  • 158
  • 1
  • 10
  • I don't see any issue like that, you might be missing something! – Rohan Oct 30 '12 at 08:33
  • Might be that the dictionary closure isn't getting access to the same namespace as the shell. Does `U = User; u = {name: U.objects.get(username=name) for name in names}` make any difference? (just wondering if this is a bug) – Dunes Oct 30 '12 at 08:39
  • @Rohan , what are the steps you are following ? @Dunes , no that doesn't work either, I get `NameError: global name 'U' is not defined` – Dhruv Baldawa Oct 30 '12 at 08:43
  • @DhruvBaldawa, this is what I tried. `>>> type(User) >>> u = {name: User.objects.get(username=name) for name in names} >>> u {'admin': , 'u1': } >>> ` – Rohan Oct 30 '12 at 08:46
  • is there problem IPython-specific, let me try it out on default shell – Dhruv Baldawa Oct 30 '12 at 08:47
  • Try with ./manage.py shell --plain, I already had the same kind of import problems. – mutantacule Oct 30 '12 at 08:48
  • 1
    Yes, it works with --plain, then this seems to be a IPython-specific problem. I will file a bug report in their project ! Thanks :-) – Dhruv Baldawa Oct 30 '12 at 08:49
  • Issue filed at: https://github.com/ipython/ipython/issues/2532 – Dhruv Baldawa Oct 30 '12 at 11:09

1 Answers1

2

I believe python's issue tracer is the best answer for you.

In short: it won't work in shell. The same applies to function definition in shell. The imports are unaccesible there.

In regard for your problem I advise:

names = [...]
users = User.objects.filter(username__in=names)
name_to_user = {user.username: user for user in users}

It does one sql query instead of len(names).

Krzysztof Szularz
  • 5,151
  • 24
  • 35