Using Requests python library to connect Django app failed on authentication
Question: Maybe a stupid question here: Is Requests(A python HTTP lib) support Django
1.4 ?

I use **Requests** follow the Official Quick Start like below:

    
    
    requests.get('http://127.0.0.1:8000/getAllTracks', auth=('myUser', 'myPass'))
    

but i never get authentication right.(Of course i've checked the url,
username, password again and again.)

The above url '**http://127.0.0.1:8000/getAllTracks** ' matches an url pattern
of the url.py of a Django project, and that url pattern's callback is the
'**getAllTracks** ' view of a Django app.

If i comment out the authentication code of the '**getAllTracks** ' view, then
the above code works OK, but if i add those authentication code back for the
view, then the above code never get authenticated right.

The authentication code of the view is actually very simple, exactly like
below (The second line):

    
    
    def getAllTracks(request):
        if request.user.is_authenticated():
            tracks = Tracks.objects.all()
            if tracks:
                # Do sth. here
    

Which means if i delete the above second line(with some indents adjustments of
course), then the **requests.get()** operation do the right thing for me, but
if not(keep the second line), then it never get it right.

Any help would be appreciated.


Answer: In Django authentication works in following way:

  * There is a SessionMiddleware and AuthenticationMiddleware. The process_request() of both these classes is called before any view is called.
  * SessionMiddleware uses cookies at a lower level. It checks for a cookie named `sessionid` and try to associate this cookie with a user.
  * AuthenticationMiddleware checks if this cookie is associated with an user then sets `request.user` as that corresponding user. If the cookie `sessionid` is not found or can't be associated with any user, then `request.user` is set to an instance of `AnonymousUser()`.
  * Since Http is a stateless protocol, django maintains session for a particular user using these two middlewares and using cookies at a lower level.

Coming to the code, so that `requests` can work with django.

You must first call the view where you authenticate and login the user. The
response from this view will contain `sessionid` in cookies.

You should use this cookie and send it in the next request so that django can
authenticate this particular user and so that your
`request.user.is_authenticated()` passes.

    
    
    from django.contrib.auth import authenticate, login
    
    def login_user(request):
        user = authenticate(username=request.POST['username'],  password=request.POST['password'])
        login(request, user)
        return HttpResponse("Logged In")
    
    def getAllTracks(request):
        if request.user.is_authenticated():
            return HttpResponse("Authenticated user")
        else:
            return HttpResponse("Non Authenticated user")
    

Making the requests:

    
    
    import requests
    
    resp = requests.post('http://127.0.0.1:8000/login/', {'username': 'akshar', 'password': 'abc'})
    
    print resp.status_code
    200 #output
    
    print resp.content
    'Logged In' #output
    
    cookies = dict(sessionid=resp.cookies['sessionid'])
    
    print cookies
    {'sessionid': '1fe38ea7b22b4d4f8d1b391e1ea816c0'}  #output
    
    response_two = requests.get('http://127.0.0.1:8000/getAllTracks/', cookies=cookies)
    

Notice that we pass cookies using `cookies` keyword argument

    
    
    print response_two.status_code
    200  #output 
    
    print response_two.content
    'Authenticated user'  #output
    

So, our `request.user.is_authenticated()` worked properly.

    
    
    response_three = requests.get('http://127.0.0.1:8000/hogwarts/getAllTracks/')
    

Notice we do not pass the cookies here.

    
    
    print response_three.content
    'Non Authenticated user' #output
    

