Reputation: 9443
I'm currently working with a custom HTML template not using forms on my Django app to upload an image in a specific path.
app structure
src/
media/
app/
img/
app_name/
templates/
app_name/
app_template.html
__init__.py
admin.py
apps.py
models.py
tests.py
urls.py
views.py
proj_name/
__init__.py
settings.py
urls.py
wsgi.py
manage.py
settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
models.py
class Document(models.Model):
doc_file = models.FileField(upload_to='app/img')
views.py
def app_save(request):
if request.method == 'POST':
newdoc = Document(doc_file=request.FILES.get('myfile'))
newdoc.save()
app_template.html
<form id="myform" method="POST" action="{% url 'my_app:save' %}"
enctype="multipart/form-data">
<input type="file" name="myfile">
<input type="submit">
</form>
#Result
After submitting the form I dont have any internal server error and no python traceback. But there was no image uploaded in the app/img
path and in my database, I have a blank record inserted because of newdoc.save()
query.
It is possible to work with file managing without forms?
#UPDATE
i added this on forms.py
class UploadFileForm(forms.Form):
file = forms.FileField()
and updated my app_template.html to:
<form id="myform" method="POST" action="{% url 'my_app:save' %}"
enctype="multipart/form-data">
{{ form.file }}
<input type="submit">
</form>
then i would like to include the function of loading the app_template.html in views.py
:
def index(request):
form = UploadFileForm()
return render(request, 'app_name/app_template.html', { 'form': form })
And also updated the app_save()
function to:
def app_save(request):
form = UploadFileForm(request.POST, request.FILES)
if request.method == 'POST':
if form.is_valid():
newdoc = Document(doc_file=request.FILES.get('file')) # note 'file' is the name of input file of a form.
newdoc.save()
The problem now is
There is no error found in the application but there is no media/app/img
path create with the uploaded image file. What went wrong? I think I missed something here.
Upvotes: 5
Views: 20989
Reputation: 1636
There is ContentFile
in django.core.files
and it's so handy to use it to save your file as your model field.
Suppose that you declared a field as FileField
and you may need to create a file and save it attached to the field. Then you can do this as following.
from django.core.files.base import ContentFile
from django.db import models
class YourModel(models.Model):
content = models.FileField(upload_to="any_path_or_callable")
...
def save_file(self, content: str):
temp_file = ContentFile(content)
self.content.save(f'{self.pk}.txt', temp_file)
I hope this would help you.
Thank you
Upvotes: 0
Reputation: 7787
Your backend code is fine. The problem is with a frontend. You can't submit file input with jQuery.ajax like other fields. Use FormData:
$('#myform').submit(function(event) {
if(window.FormData !== undefined) {
event.preventDefault();
var formData = new FormData(this);
var xhr = new XMLHttpRequest();
xhr.open('POST', $(this).attr('action'), true);
xhr.setRequestHeader('X-REQUESTED-WITH', 'XMLHttpRequest')
xhr.onreadystatechange = function() {
if(xhr.readyState == 4) {
if(xhr.status == 200) {
result = JSON.parse(xhr.responseText);
// Code for success upload
}
else {
// Code for error
}
}
};
xhr.send(formData);
}
});
Upvotes: 1
Reputation: 599550
I don't understand why you don't want to use a modelform; it'll make things a lot easier.
However, if you really do want to do it without one, you'll need to take care of the actual uploading yourself. The documentation has a good example of what you'll need to do; basically you just take the file from request.FILES
and save it to the location you want.
Upvotes: 0