Avoiding Django's QueryDict List limitations - ajax

I'm trying to send data from a webpage to a django view to be saved as serialized json to a database. If possible, I would like to avoid django's QueryDict object and just read the request with simplejson, flatten, and save to the database. What is the best way to send the data so simplejson can flatten it?
var languages = {};
languages['english'] = ['mark', 'james'];
languages['spanish'] = ['amy', 'john'];
$.ajax({
type: 'POST',
url: '/save/',
data: languages,
dataType: 'json'
});
.
if request.is_ajax() and request.method == 'POST':
for key in request.POST:
print key
valuelist = request.POST.getlist(key)
print valuelist

I doubt that it is possible to make django avoid creating QueryDict, but you can ignore it (from iphone Json POST request to Django server creates QueryDict within QueryDict):
def view_example(request):
data=simplejson.loads(request.raw_post_data)

Have you tried the QueryDict.lists() or QueryDict.dict() methods? https://docs.djangoproject.com/en/dev/ref/request-response/#querydict-objects

You can try http://code.google.com/p/jquery-json/ and make json string on client side.
var languages = {};
languages['english'] = ['mark', 'james'];
languages['spanish'] = ['amy', 'john'];
var json_languages = $.toJSON(languages);//'{"plugin":"jquery-json","version":2.2}'
// '{"spanish": ["amy", "john"], "english": ["mark", "james"]}'
$.post('/save/', {data: json_languages});
in view just:
if request.is_ajax() and request.method == 'POST':
data = request.POST.get('languages')
it's not the best practice, but it works fine for me sometimes.

Related

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)

How to return a string in a class based view using ajax

I want to transmit a string from a class based view to the client via ajax.
Here's my view, which inherits from another view
class TeamCreateView_Ajax(TeamCreateView):
def render_to_response(self, context, **response_kwargs):
return HttpResponse("asdf")
For some reason, this transmits the entire web page that would've been rendered by TeamCreateView instead of the string "asdf".
class TeamCreateView_Ajax(TeamCreateView):
def dispatch(self, request, *args, **kwargs):
return HttpResponse("asdf")
On the other hand, this correctly transmits "asdf".
What gives?
Usually, using ajax, we communicate using either json/xml to send information from server to webpage. For example:
class SomeView(TemplateView): #I used template view because it has get method
def render_to_response(self, context, **response_kwargs):
data = {}
data['some_data'] = 'asdf'
return HttpResponse(json.dumps(data), content_type="application/json")
And in Script:
$.ajax({ url: url,
type: "get",
success: function (data) {
alert(data.some_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 can i make django file upload work with valums/file-uploader

I want to make valums/file-uploader run with django upload, using it with model fields (FileField)
basic django model:
class Image(models.Model):
user = models.ForeignKey(User)
url = models.FileField(upload_to='%Y/%m/%d')
basic view, working with non ajax upload:
def ajax_upload(request):
if request.method == 'POST':
newfile = Image()
newfile.user = request.user
file_content = ContentFile(request.FILES['file'].read())
file_name = request.FILES['file'].name
newfile.url.save(file_name, file_content)
results = {'url': newfile.url, 'id': newfile.id}
return HttpResponse(json.dumps(results))
raise Http404
The problem is that valums uploader does not put the files in "request" files, it put it in the POST, and django get it as a querydic.
Using it with the top code django says:
"Key 'file' not found in "
If i change:
file_content = ContentFile(request.POST)
django says:
expected read buffer, QueryDict found
I can make it work but i still want to hold on django's native file upload, it's much cleaner.
Use request.body (or request.raw_post_data if older than 1.4)

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