I'm trying to upload some files through a form on my project and have the files save to disk. Currently, I am able to get the data to insert into the DB (postgreSQL
), but the data is not being written to disk. I've done some looking around, and using a modelform
and calling save
should take care of everything (but apparently I missed something?). Any help is appreciated.
Here's my code: views.py (for uploading files related to a job)
# Upload files to a Job (Developer)
@login_required()
@user_passes_test(lambda u: u.groups.filter(name='Developer').exists(), login_url='/login/', redirect_field_name='not allowed')
@require_http_methods(['POST'])
def job_file_upload(request, jobid):
# Get the Job
job = Jobs.objects.get(id=jobid)
fileform = JobFileSubmitForm(request.POST, request.FILES)
if fileform.is_valid():
jfs = fileform.save(commit=False)
file = request.FILES['file']
jfs.user_id = request.user.id
jfs.job_id = jobid
jfs.file = file.name
jfs.uploadDate = datetime.now()
# Save to DB
jfs.save()
return redirect('view_job', jobid=jobid, slug=job.slug)
models.py (DB for holding file data and holding saving to the correct path)
from django.core.files.storage import FileSystemStorage
fs = FileSystemStorage(location='/media/')
...
def upload_job_file_path(instance, filename):
return os.path.join('/uploads/job_meta/files/', instance.id, filename)
# Submit Files for a Job (Developer Role)
class JobFileSubmit(models.Model):
job = models.ForeignKey(Jobs)
user = models.ForeignKey(User)
file = models.FileField(storage=fs, upload_to=upload_job_file_path, blank=False, null=False)
uploadDate = models.DateTimeField(auto_now=True)
forms.py
class JobFileSubmitForm(forms.ModelForm):
class Meta:
model = JobFileSubmit
fields = 'file',
def save(self, commit=True):
jobfilesubmit = super(JobFileSubmitForm, self).save(commit=False)
if commit:
jobfilesubmit.save()
return jobfilesubmit
view.html
<form method="post" action="/job/job_file_upload/j{{ job.id }}/" class="form-inline btn-group" enctype="multipart/form-data">
{% csrf_token %}
<div class="span6 inline">
<label class="control-label">Attach Files: </label>{{ job_file_submit.file }}
<p class="help-block">Attach files that go with this Job.</p>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-success btn-med pull-left"><i class="fa fa-check-circle"></i> Attach Files</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</form>
TL;DR: Currently the form submits, inserts into the DB, but the data is not written to the disk and to the dynamic path it should. For instance, the data is not being written to:
/media/uploads/job_meta/files/{{job.id}}/{{file.name}}
Thanks for taking the time to read this! Any help is much appreciated!
I am not sure if this is the final answer but its easier to write codeblock here
The upload_job_file_path needs to return a relative path from the MEDIA_ROOT. If I understand it right, the id is the job_id of the instance not its id. This way the following function should work. (It might be that FileField has to be below the job field in the code)
models.py
def upload_job_file_path(instance, filename):
return 'uploads/job_meta/files/%s/%s' % (instance.job_id, filename)
class JobFileSubmit(models.Model):
job = models.ForeignKey(Jobs)
user = models.ForeignKey(User)
file = models.FileField(upload_to=upload_job_file_path, blank=False, null=False)
uploadDate = models.DateTimeField(auto_now=True)
I am not too familiar with modeforms but i think the save method should handle the fileupload too. So this might be enough
views.py
if fileform.is_valid():
jfs = fileform.save(commit=True)