views:

238

answers:

2

Howdy - I've written a very simple app to accept job applications including a resume upload.

Running the bundled server for development locally, I can successfully upload files via the web form on the front end and the admin interface. Running it on the remote server (Apache with mod_python) I can successfully upload files via the admin interface but attempts over the web front end yield no uploaded file.

I've added FILE_UPLOAD_PERMISSIONS = 0644 to settings, checked the two settings files, and looked for similar problems described elsewhere. Figure I'm either forgetting a setting or need to go about this a different way. Any suggestions?

For reference, code included.

The model:

class Application(models.Model):
    job = models.ForeignKey('JobOpening')
    name = models.CharField(max_length=100)
    email = models.EmailField()
    date_applied = models.DateField()
    cover_letter = models.TextField()
    resume = models.FileField(upload_to='job_applications', blank=True)

    def __str__(self):
     return self.name

    def save(self):
     if not self.date_applied:
      self.date_applied = datetime.today
     super(Application, self).save()

The form:

class JobApplicationForm(ModelForm):    
    class Meta:
     model = Application

    def save(self, commit=True, fail_silently=False):
     super(JobApplicationForm, self).save(commit)

The view:

def job_application(request):
    ajax = request.GET.has_key('ajax')
    if request.method == 'POST':
     form = JobApplicationForm(request.POST, request.FILES)
     if form.is_valid():
      new_application = form.save()
      return HttpResponseRedirect('/about/employment/apply/sent/')
    elif request.GET.has_key('job'):
     job = request.GET['job']
     form = JobApplicationForm({'job': job})
    else:
     return HttpResponseRedirect('/about/')
    t = loader.get_template('employment/job_application.html')
    c = Context({
     'form': form,
    })
    return HttpResponse(t.render(c))
+2  A: 

You don't show the template. If I had to guess, seeing as the upload works via the admin interface, I'd say you've forgotten to put the enctype in your form tag:

<form enctype="multipart/form-data" method="post" action="/foo/">
Daniel Roseman
I'd forgotten to commit the form template and thinking I had, didn't check the form on dev. Thank you for making me look at what should have been obvious.
bennylope
+1  A: 

First, Have you made sure your template has the enctype="multipart/form-data" flag in it?

<form action="." method="POST" enctype="multipart/form-data">
    ...
</form>

First, there's no need to override save() in your ModelForm since you're not doing any extra work in it.

Second, there's no need to store the new_application variable, simply call form.save().

Third, you should be using a slug field in your JobOpening model and passing that in the querystring. Remember, this isn't PHP, use pretty urls like /jobs/opening/my-cool-job-opening/, that's what slugs are for; unique human readable urls. Your GET code in your view is very fragile as it stands.

Finally, you may want to use the render_to_response shortcut function as it will save you having to verbosely call template loaders, create context and render them manually.

Soviut
Good points - I am overriding the save function because I had originally - and will again - have some messaging functions called. I'm using GET instead of a slug as that seemed to make it easier to call the page with an AJAX call later (maybe I'm wrong there).
bennylope
You can just as easily call a pretty url with ajax. The only time I use any data in JQuery is on POST requests via ajax.
Soviut
Also, use the dictionary get() method so that if the variable doesn't exist in the GET/POST dictionary you can assign it a default value so your code won't crash. example: request.POST.get('myvalue', '')
Soviut
Thanks Soviut. I was following too closely some existing code for that piece for sure.
bennylope