there are tons of relevant posts:
- https://docs.djangoproject.com/en/3.2/topics/http/file-uploads/
- Uploading A file in django with ModelForms
- https://github.com/axelpale/minimal-django-file-upload-example
I am creating a simple app that allow user to upload css file:
First, validate field field to make sure the file is css and the max size does not exceed 5MB.
fields.py
from django.db import models
from django import forms
from django.template.defaultfilters import filesizeformat
def mb(n):
return n * 1048576
class FileField(models.FileField):
def __init__(self, *args, **kwargs):
self.content_types = kwargs.pop('content_types', [])
self.max_upload_size = kwargs.pop('max_upload_size', [])
super().__init__(*args, **kwargs)
def clean(self, *args, **kwargs):
data = super().clean(*args, **kwargs)
file = data.file
try:
content_type = file.content_type
if content_type in self.content_types:
if file.size > self.max_upload_size:
raise forms.ValidationError('Please keep filesize under {}. Current filesize {}'
.format(filesizeformat(self.max_upload_size), filesizeformat(file.size)))
else:
raise forms.ValidationError('File type rejected')
except AttributeError:
pass
return data
second, implement validation into model
models.py
# Create your models here.
class Css(models.Model):
file = FileField(
upload_to='css',
content_types=['text/css'],
max_upload_size=mb(5),
)
third, create form for model creation
forms.py
class CssCreateForm(forms.ModelForm):
class Meta:
model = Css
fields = ['file']
last, write a callable view
views.py
# Create your views here.
def cssUploadView(request):
if request.method == 'POST':
print(request.POST['file'])
print(type(request.POST['file']))
print(request.FILES)
form = forms.CssCreateForm(request.POST, request.FILES)
if form.is_valid():
print('---------')
print(form.cleaned_data['file'])
else:
print('not valid')
else:
form = forms.CssCreateForm()
return render(request, 'css/css_create.html', {
'form': form,
})
template
<form method="POST">
{% csrf_token %}
<div class="form-title">Upload a new CSS file</div>
{{ form.as_p }}
<div class="button-area">
<button id="go" type="submit">Go</button>
</div>
</form>
The expected result is that
- when uploading html file, or css file larger than 5MB,
ValidationError
will be raised
However, in view
- Both
request.FILES
andform.cleaned_data['file']
fails to retrieve uploaded file. form.is_valid
always returnsTrue
for example, when I upload
clean.py
:
clean.py
<class 'str'>
<MultiValueDict: {}>
---------
None
I wonder why file fails to upload and validation does not work. Any suggestion will be appreciated.
CodePudding user response:
You have to specify the data encoding method in your html form.
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-title">Upload a new CSS file</div>
{{ form.as_p }}
<div class="button-area">
<button id="go" type="submit">Go</button>
</div>
</form>