10

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 Answers 2

38

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/">
Sign up to request clarification or add additional context in comments.

3 Comments

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.
I did the same thing and this saved a ton of time trying to debug. StackOverflow is awesome!
enctype="multipart/form-data" The web. Sums of little pieces added time after time that makes the biggest mess ever done on earth. I'm so fed up with that. And I must code in that mess, and with that mess. Sigh
6

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.

4 Comments

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).
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.
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', '')
Thanks Soviut. I was following too closely some existing code for that piece for sure.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.