Reputation: 2439
I'm using django with jquery to upload files using ajax. However, after the file has uploaded (and the files do upload correctly; the database is updated and they are on the server) javascript returns with an SyntaxError: Unexpected token <
error.
I don't know if this is an error in javascript or an error in django; other questions I saw seemed to recommend making sure the information is indeed in JSON format, but it seems to be properly formatted in my case. I don't really understand why there is an error, since everything seems to work fine. There are no errors in my logs.
If I could only see a more helpful error message, I would have a much easier time fixing the issue.
Here's my views.py:
def response_mimetype(request):
if "application/json" in request.META['HTTP_ACCEPT']:
return "application/json"
else:
return "text/plain"
class JSONResponse(HttpResponse):
"""JSON response class."""
def __init__(self,obj='',json_opts={},mimetype="application/json",*args,**kwargs):
content = simplejson.dumps(obj,**json_opts)
a = super(JSONResponse,self).__init__(content,mimetype,*args,**kwargs)
class UploadedFileCreateView(CreateView):
model = UploadedFile
form_class = UploadedFileForm
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.project_id = self.kwargs['proj_key']
self.object.save()
f = self.request.FILES.get('file')
data = [{
'name': self.object.name(),
'url': "/uploads/xmlfiles/" + self.object.name().replace(" ", "_"),
'delete_url': reverse('fileupload:upload-delete',
kwargs={'pk':self.object.id,
'proj_key':self.kwargs['proj_key']}),
'delete_type': "DELETE"}]
response = JSONResponse(data, {}, response_mimetype(self.request))
response['Content-Disposition'] = 'inline; filename=files.json'
return super(UploadedFileCreateView, self).form_valid(form)
def get_context_data(self, **kwargs):
context = super(UploadedFileCreateView, self).get_context_data(**kwargs)
context['files'] = UploadedFile.objects.all()
context['proj'] = int(self.kwargs["proj_key"])
return context
And here's my models.py:
class UploadedFile(models.Model):
"""This represents a file that has been uploaded to the server."""
STATE_UPLOADED = 0
STATE_ANNOTATED = 1
STATE_PROCESSING = 2
STATE_PROCESSED = 4
STATES = (
(STATE_UPLOADED, "Uploaded"),
(STATE_ANNOTATED, "Annotated"),
(STATE_PROCESSING, "Processing"),
(STATE_PROCESSED, "Processed"),
)
status = models.SmallIntegerField(choices=STATES,
default=0, blank=True, null=True)
file = models.FileField(upload_to=settings.XML_ROOT)
project = models.ForeignKey(Project)
def __unicode__(self):
return self.file.name
def name(self):
return os.path.basename(self.file.name)
def save(self, *args, **kwargs):
if not self.status:
self.status = self.STATE_UPLOADED
super(UploadedFile, self).save(*args, **kwargs)
def delete(self, *args, **kwargs):
os.remove(self.file.path)
self.file.delete(False)
super(UploadedFile, self).delete(*args, **kwargs)
def get_absolute_url(self):
return u'/upload/projects/%d' % self.id
class UploadedFileForm(ModelForm):
class Meta:
model = UploadedFile
exclude = ('project',)
Upvotes: 2
Views: 4596
Reputation: 2866
According to the documentation here, the form_valid()
method needs to return the JSON as a HTTPResponse
. Calling the form_valid()
on the super class will, instead, overwrite the response created on the previous two lines.
Edit - This is working for me:
def response_mimetype(request):
if "application/json" in request.META['HTTP_ACCEPT']:
return "application/json"
else:
return "text/plain"
class UploadedFileCreateView(CreateView):
model = UploadedFile
form_class = UploadedFileForm
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.project_id = self.kwargs['proj_key']
self.object.save()
f = self.request.FILES.get('file')
data = [{
'name': self.object.name(),
'url': "/uploads/xmlfiles/" + self.object.name().replace(" ", "_"),
'type': "application/xml",
'size': self.object.file.size,
'delete_url': reverse('fileupload:upload-delete',
kwargs={'pk':self.object.id,
'proj_key':self.kwargs['proj_key']}),
'delete_type': "DELETE"}]
return HttpResponse(simplejson.dumps(data), content_type = response_mimetype(self.request))
The code in the link above bundles the ajax response code as a Mixin which would allow other forms in the project to reuse the code.
Viewing the response to the Ajax call in the Firefox plugin Firebug, Net tab or Chrome equivalent will help. These will show both the request and response headers ensuring the correct settings are being sent and returned.
Upvotes: 3