How to set csrf token cookie when a view return a json data? - ajax

Here is my signup view, and I use ajax to post.
I have followed the official document. If the csrftoken cookie exists, it works fine.
However, the view returning json data didn't set the csrftoken. How to deal with this?
def signup(request):
if request.method == "POST":
postdata = request.POST.copy()
form = UserCreationForm(postdata)
if form.is_valid():
form.save()
user = postdata.get('username', '')
password = postdata.get('password1', '')
from django.contrib.auth import login, authenticate
new_user = authenticate(username=user, password=password)
if new_user and new_user.is_active:
login(request, new_user)
data = json.dumps({'success': 'true'})
return HttpResponse(data, mimetype='application/json')
else:
data = json.dumps({'username': '该用户处于非正常状态'})
return HttpResponse(data, mimetype='application/json')
else:
error_list = {}
for ek in form.errors:
error_list[ek] = form.errors[ek][0]
data = json.dumps(error_list)
return HttpResponse(data, mimetype='application/json')
else:
return HttpResponseRedirect("/")

You'll need to set the X-CSRFToken header in your ajax call, refer to the offical docs on csrf with ajax for details.
https://docs.djangoproject.com/en/1.5/ref/contrib/csrf/#ajax

Related

Adding permissions to a django rest api

I am working on a django rest api and i want to add permission to it
. I decided to go with IsAuthenticatedOrReadOnly to allow none authenticated people to read only and allow authenticated people to add data
setting.py:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]}
views.py:
#api_view(['GET','POST'])
#permission_classes([IsAuthenticatedOrReadOnly])
def list_drinks(request, format=none):
if request.method == 'GET':
drinks = Drink.objects.all()
serializer = DrinkSerializer(drinks, many=True)
return Response(serializer.data)
if request.method == 'POST':
serializer = DrinkSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
when i try to access the api without authentification, i can only read but when i try to do a modification while adding a username and a password, i get the message "detail": "You do not have permission to perform this action." even though i am authenticated as admin (a superuser)
what's the problem?
Make sure you have the necessary authentication classes in your REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"] settings.
For basic authentication add "rest_framework.authentication.BasicAuthentication" to the list.
If you are using the browsable API you need to add session authentication "rest_framework.authentication.SessionAuthentication"

Django rest framework authentication issue

I have custom token creating and decoding methods. Now everytime I get request I need to decode token to get request user or I get anonymous user. How can I decode it without repeating every time these lines?
auth = get_authorization_header(request).split()
if auth and len(auth) == 2:
token = auth[1].decode('utf-8')
id = decode_access_token(token)
You can create a middleware, where you decode the token and pass the info about the user to the class/function view
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
auth = get_authorization_header(request).split()
user = None
if auth and len(auth) == 2:
token = auth[1].decode('utf-8')
id = decode_access_token(token)
user = ... # get user
response = self.get_response(request, user)
# Code to be executed for each request/response after
# the view is called.
return response
And in your view
#method_decorator(SimpleMiddleware, name='dispatch')
class SimpleView(View):
def post(self, request, user):
pass

Django testing - test the view which handles an ajax call

In testing Django, the view is returning 200 code but not sending any error message related.
def ajax_view(request):
msg = ''
if request.is_ajax():
username = request.POST['username']
user = User.objects.get(username=username)
msg = 'user exists'
return HttpResponse(msg)
In tests.py
response = self.client.post(reverse('ajax_view'), data={'username': 'hello'})
self.assertEqual(200, response.status_code)
self.assertContains(response, 'exist')
It seems it is not going through the request.is_ajax().. How can I mock the ajax call in Django testing?
The docs on the test client mention this; you need to pass the HTTP_X_REQUESTED_WITH header, which you can do as a keyword argument.
Also, if you pass content_type as 'application/json', Django will automatically serialize to JSON. So:
response = self.client.post(
reverse('ajax_view'),
data={'username': 'hello'},
content_type='application/json',
HTTP_X_REQUESTED_WITH='XMLHttpRequest'
)
Not entirely sure this will resolve the entire issue but your method may be expecting the data in a json format:
json_data = json.dumps({'username': 'hello'})
response = self.client.post(reverse('ajax_view'), data=json_data)

JQuery ajax call with django session

I have a site that uses custom authentication in Django that authenticates to a web service using a username, password, and domain. I need to store this information for every subsequent view's request object.
All seems to be going well until I try to make a jquery $.ajax call, debugging the view that gets called from the ajax request I have no session information and the user is AnonymousUser.
I need the session variables to make subsequent calls to the web service for data to display. I've tried a few things in there but nothing seems to work correctly. I want to make sure users a logged in before being able to submit these web service queries as I want to keep the username/domain to lookup the password (and not have it on the client side) in the view and ensure the user is always logged in.
views.py
def login(request):
if settings.DEBUG == True:
print "views.login:Attempting loging at views.login(request)"
if request.method == 'POST':
if settings.DEBUG:
print "views.login: method is POST"
form = LoginForm(request.POST)
if form.is_valid():
if settings.DEBUG:
print "Form is valid, attepmting to authenticate"
Login(request, form.get_user())
str = reverse('cm_base.views.index')
request.session['username']=form.get_user()
request.session['domain']=form.get_domain()
return render_to_response('cm_base/index.html',
{"DEBUG": True,
"user":request.session.get('username'),
'tabs': settings.TAB_LIST},
context_instance=RequestContext(request))
else:
# Their password / email combination must have been incorrect
pass
else:
form = LoginForm()
return render_to_response('cm_base/login.html',
{"DEBUG": True,
'form' : form
},
context_instance=RequestContext(request))
#login_required()
def index(request):
if request.method == 'POST':
print "POSTING"
if settings.DEBUG == True:
print "views.index:Opening index"
return render_to_response('cm_base/index.html',
{"DEBUG": True,
"user":"user",
'tabs': settings.TAB_LIST},
context_instance=RequestContext(request))
#login_required()
def scorecard(request):
user = CustomUser.objects.get(username=request.session.get('username'),
domain=request.session.get('domain'))
*fails on the above line with DoesNotExist: CustomUser matching query does not exist. Lookup parameters were {'username': None, 'domain': None}
base.js
$.ajax({
url : path,
data: $(this).serialize(),
headers: {'X-CSRFToken':getCookie('csrftoken')
,'sessionid':getCookie('sessionid')
},
success : function(data) {
console.log($(this));
//refresh right div
$('#contentpane').empty();
$('#contentpane').html(data.rhtml);
console.log(data.rhtml);
}
});
Looks like my implementation of the backend that was the problem.
backends.py
class CustomBackend(object)
...
def get_user(self, username):
try:
return CustomUser.objects.get(username=username)
except CustomUser.DoesNotExist:
return None
This is called during session passing and actually uses a the primary key which is a userid, not username so this was always returning no user and defaulting to anonymous user. I misinterpreted when the documentation says the userid can be anything, including username, I thought I could pass that in as such but I have both an auto generated userid as well as a username on the object.

How to use Httpresponse in view in django while using Ajax

I am using this
def ajax_create( request ):
if request.is_ajax():
form = SourceForm()
template = 'ajax_form.html'
data = {
'form': form,
}
return render_to_response( template, data,
context_instance = RequestContext( request ) )
I get this error
ajax_create didn't return an HttpResponse object
Are you sure your request is an ajax call ? It doesn't look like it.
Try:
if request.is_ajax():
...
else:
# If the request is not an ajax call, it will return a 400 Error.
return HttpResponseBadRequest()
Perhaps if request.is_ajax(): is returning False, if that's your entire view function?
Typically, you should follow this pattern when making Django view functions:
def my_view(request):
if request.method == 'POST':
form = MyForm(data=request.POST, files=request.FILES)
if form.is_valid():
# do something with form...
else:
initial = {...}
form = MyForm(initial=initial)
context = {'form':form, ...}
return render_to_response('path/to/template.html', context, context_instance=RequestContext(request))
It's not entering to your "if" scope. it returns None
https://docs.djangoproject.com/en/1.3/ref/request-response/#django.http.HttpRequest.is_ajax
Check your ajax call and make sure it returns something in case the request is not ajax

Resources