27

I got, following Error messages,

TypeError at /save/ int() argument must be a string or a number, not 'SimpleLazyObject'

While executing following form.


views.py

def bookmark_save_page(request):
    if request.method == 'POST':
        form = BookmarkSaveForm(request.POST)
        if form.is_valid():
            # create or get link
            link, dummy = Link.objects.get_or_create(
                    url = form.cleaned_data['url']
                    )
            # create or get bookmark
            bookmark, created = Bookmark.objects.get_or_create(
                    user=request.user,
                    link=link
                    )
            # update bookmarks title
            bookmarks.title = form.cleaned_data['title']
            # if the bookmark is being updated, clear old tag list.
            if not created:
                bookmark.tag_set.clear()
            # create new tag list
            tag_names = form.cleaned_data['tags'].split()
            for tag_name in tag_names:
                tag, dummy = Tag.objects.get_or_create(name=tag_name)
                bookmark.tag_set.add(tag)
            # save bookmark to database.
            bookmark.save()
            return HttpResponseRedirect(
                    '/user/%s/' % request.user.username
                    )
    else:
        form = BookmarkSaveForm()
    variables = RequestContext(request, {
        'form': form
    })
    return render_to_response('bookmark_save.html', variables)

I thought I got error because I passed link at

bookmark, created = Bookmark.objects.get_or_create(
                    user=request.user,
                    link=link
                    )

But I can not figure out how to fix it. How can I fix it?

yup
  • 319
  • 1
  • 4
  • 8
  • 1
    Well, the error you're getting should have a bit more information, maybe if you could post the whole trace that would help. – Martin B. Apr 08 '13 at 12:54

6 Answers6

57

The likely cause is that you're setting user = request.user, where request.user is not a real User object, but a SimpleLazyObject instance. See django: Purpose of django.utils.functional.SimpleLazyObject? for more details, but using request.user.id should fix your issue.

Community
  • 1
  • 1
Martin B.
  • 1,928
  • 12
  • 24
  • 2
    Thanks! But I still have error... Cannot assign "1": "Bookmark.user" must be a "User" instance. – yup Apr 08 '13 at 13:51
  • OK well, then try loading the user object - did you read the link I posed? Might do something like `user = auth.get_user(request)`. Then again I can still only guess where your error occurs without a more detailed error trace. – Martin B. Apr 08 '13 at 15:26
  • After I tried lots of other methods, I figured out the first one I got error (user=request.user) proved to be varid... so strange..., I am new to django, so I may need to understand django through reading documentation entirely. But thank-you Martin, for helping me to grasp the concept about User object and SimpleLazyObject. – yup Apr 09 '13 at 02:17
  • Thank you this helped me; from now on it's explicit FOO__pk for me. This highlights one short coming of duck typing - at some point you have to be assured of the input type, if you don't then you will trade a type check against some potential exception deeper in your code, in this case Django is trying to bail early but means it doesn't realize SimpleLazyObject will resolve properly. – Daniel Sokolowski May 31 '13 at 15:17
  • I can filter using request.user with no errors on my local environment but in production I get the mentioned error. Has anyone experienced similar? If so, I'm curious what differences in production and development environments could be causing this. – Will Farley Sep 08 '14 at 21:21
  • `request.user.id` was the ticket - great call, and makes sense. – kyleturner Jul 27 '15 at 05:05
  • Thanks @Martin I have the same error but in one of my functions in my own context_processor and the `request.user.id` solved that error when the user was an `AnonymousUser` – M. Gar Mar 04 '16 at 00:59
11

You have to login when running this piece of code on localhost. Otherwise the request.user will be a SimpleLazyObject, then the errors comes out.

Paul Richter
  • 10,908
  • 10
  • 52
  • 85
fmx
  • 111
  • 1
  • 3
  • 3
    This can happen if you have a view that tries to lookup `request.user` in the database, and you forget to add the `login_required` decorator, and you try to access the view without being logged in. – qris Mar 03 '14 at 18:39
9

Here you trying to create a Bookmark object based on request.user , but request.user is a SimpleLazyObject , so we can get a more secure user object by :

from django.contrib import auth

current_user = auth.get_user(request)

and further your query should be

bookmark, created = Bookmark.objects.get_or_create(
                    user=current_user,
                    link=link
                    )
Arun V Jose
  • 3,321
  • 2
  • 24
  • 24
Vidya Sagar
  • 1,496
  • 14
  • 23
5

Most likely the user who is loading the page is not authenticated. Therefor the error is thrown. If you want to save a request.user reference to the database, you obviously have to ensure that only authenticated users are able to call the function.

In your case there are two possibilities - add the "@login_required" decorator to the function or check if the user is authenticated inside the code. Here are the snippets:

With Decorator:

from django.contrib.auth.decorators import login_required

@login_required
def bookmark_save_page(request):
    if request.method == 'POST':
        form = BookmarkSaveForm(request.POST)
        if form.is_valid():
            # Do something

OR - checking inside the code if the user is authenticated:

def bookmark_save_page(request):
    if request.method == 'POST' and request.user.is_authenticated():
        form = BookmarkSaveForm(request.POST)
        if form.is_valid():
            # Do something
Khaled Al-Ansari
  • 3,910
  • 2
  • 24
  • 27
dh1tw
  • 1,411
  • 2
  • 23
  • 29
1

Thats strange, I had the same problem and the same solution. After trying a bunch of alternatives I went back to user = request.user and it worked

theptrk
  • 730
  • 9
  • 17
0

if you want to set an addition request attr, based on user -> you need to use lazy Django function which is correctly handled by Field.get_prep_value

   from django.utils.functional import lazy
   request.impersonator = lazy(lambda: request.user.id, int)()
pymen
  • 5,737
  • 44
  • 35