How to use Httpresponse in view in django while using Ajax - 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

Related

Overriding generic.ListView methods for AJAX requests DJANGO

I recently started using django's inbuilt generic views (Create, Update, etc) So I'm updating most of my old views to use them, one of them is the ListView, with pagination. So now, it works right,when i GET that page, it displays the objects as directed, and the pagination works fine. But i want to use AJAX on the pagination so that i just click a "More" button and it gets the next page's objects via ajax and are appended onto the end of the . So i've modified some generic views before to incorporate AJAX like the:
class Delete(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
login_url = LOGIN_URL
model = Items
success_url = reverse_lazy('web:member-area')
def test_func(self):
return not self.request.user.is_superuser and self.get_object().created_by == self.request.user
def delete(self, request, *args, **kwargs):
response = super().delete(request)
if self.request.is_ajax():
return JsonResponse({'success': 1}, status=200)
else:
return response
In the above snippet you can see i included the part where it returns something different if the request is AJAX
The current View that i'm working on is as follows:
class Items(ListView):
model = Items
paginate_by = 5
context_object_name = 'items'
template_name = 'web/items/index.html'
which works fine on normal GET requests, so the problem is i dont know which super() method(s) to override and return a different response if its AJAX on that ListView
Use dispatch
class Items(ListView):
def dispatch(request, *args, **kwargs):
response = super().dispatch(request, *args, **kwargs)
if request.is_ajax():
return JsonResponse({'success': 1}, status=200)
else:
return response

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)

Django POST data dictionary is empty when posting from test client

I am trying to test and AJAX view in my Django Project. When submit the post from JQuery the data is correctly accessible in the Django View but when I try to make queries for the Django test client it is emplty.
Here is the code I use:
The view
def add_item(request):
if request.is_ajax() and request.method == 'POST':
post_data = request.POST
print post_data ## <----- THIS IS EMPTY
name = post_data.get('name')
# Render the succes response
json_data = json.dumps({"success":1})
return HttpResponse(json_data, content_type="application/json")
else:
raise Http404
And the test
class TestAddItem(TestCase):
def test_some_test(self):
data = {
'description':"description",
}
response = self.client.post('theurl', data, content_type='application/json')
Any Idea what I might be doing wrong?
I tried also without content type and also using plain url like thurl/?name=name without succes.
Any help will be appreciated.
Olivier
After trying different combinations of parameter formating, content types, etc..
I found one solution that works :
response = self.client.post(reverse('theurl'), data,
**{'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'})
And I get the following dictionary on the POST parameters of the request:
<QueryDict: {u'name': [u'name']}>
Edit I love testing :)

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

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

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.

Resources