Django validator not triggering on file upload - python

I have wrote a Django app for the user to upload files and see a list of uploaded files. I want to restrict the uploads to only using gif format and wrote a simple validator. Then I pass that validator in the Model, however it never triggers and the file is saved regardless of the format. Here's what I got so far.
views.py
def list(request):
# Handle file upload
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
newdoc.save()
messages.add_message(request, messages.INFO, "Saved")
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('list'))
else:
form = DocumentForm() # A empty, unbound form
# Load documents for the list page
documents = Document.objects.all()
# Render list page with the documents and the form
return render(
request,
'list.html',
{'documents': documents, 'form': form}
)
checkformat.py
def validate_file_type(upload):
if not (upload.name[-4:] == '.gif'):
raise ValidationError('File type not supported.')
models.py
from .checkformat import validate_file_type
def content_file_name(instance, filename):
return '/'.join(['documents', str(filename), filename])
class Document(models.Model):
docfile = models.FileField(upload_to=content_file_name, validators=[validate_file_type], null=False, verbose_name="File")
forms.py
class DocumentForm(forms.Form):
docfile = forms.FileField(
label='Select a file', widget=forms.FileInput(attrs={'accept':'image/gif'})
)
Is there something I'm missing? I've just started learning Django. Also, I know this is not a sercure way to check for a file type, but I just want to see it work to continue. Thank you for your time.

if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
if not '.gif' in newdoc.name:
raise ValidationError('File type not supported.')
else:
newdoc.save()
messages.add_message(request, messages.INFO, "Saved")
try this simple solution, hope it works as you need

Looks right so far. Maybe it's simply a lower/upper case issue?
A more accurate solution might be:
import os
def validate_file_type(upload):
if os.path.splitext(upload.name)[1].lower() != '.gif':
raise ValidationError('File type not supported.')
If it's still not working try to add a break point within the validation method and check the value of upload.name.

I think the problem is the form is derived from a simple Model class, but in your case you must use ModelForm instead.
This way the form knows about the Document model, and you can do some fancy operations, like calling the save mehond in the Form object so save the model instance. Also the is_valid method calls all the validations defined in the model, in addition to the validations defined in the Form itself.

Related

How to pass a variable value from model to view using ValidationError (Django)

I am developing an app in Django.
In this app there is a file form.
In the view function associated to base.html I have implemented a message system that publishes a message if the user has not copleted the form correctly and tries to submit it.
messages.error(request, ('ERROR: Compile the form properly!'))
In my models.py I have a clean function that prevents form validation by raising a validation error and printing a message in the console:
def clean(self):
if not (self.file):
raise ValidationError("No file selected.")
if not self.Glossary_file.lower().endswith('.xls', '.xlsx', '.xlsm' '.csv', '.xml', '.xlt'):
raise ValidationError("The selected file is not a spreadsheet.")
However, these two messages gets overwritten by the string in views.py.
Let's imagine I re-write my clean method like this:
def clean(self):
if not (self.file):
error_message="No file selected."
raise ValidationError("who cares, it gets overwritten by view message")
if not self.Glossary_file.lower().endswith('.xls', '.xlsx', '.xlsm' '.csv', '.xml', '.xlt'):
error_message="The selected file is not a spreadsheet."
raise ValidationError("who cares, it gets overwritten by view message")
I would need something like this in my views.py, replacing the other line:
messages.error(request, (error_message))
but I don't know how to pass error_message from models.py to views.py.
The ValidationError prevents me to add a return in my clean function, which I could use to return error_message.
Here is my view function corresponding to form page:
def add_file(request):
if request.method=='POST':
form = file_form(request.POST, request.FILES)
if form.is_valid():
form.save()
insert_attempt_output="correct"
messages.success(request, ("ok"))
return redirect('add_file_template')
else:
insert_attempt_output="error"
messages.error(request, ('ERROR: Compile the form properly!'))
return render(request, 'add_file_template.html', {'insert_attempt_output':insert_attempt_output})
else:
return render(request, 'add_file_template.html', {})

Django delete models based on form input

I have a form and a model, in my views I take the data from form and use it to delete the object from my model, but it does not delete the object at all, even though if I use the shell and create the same query set with the same syntax it works. What am I missing here?? Thx
Code from views:
form = SecondForm()
query_list = DictWord.objects.all()
dict_DictWord = {'words': query_list,"form":form}
if request.method == "POST":
form = SecondForm(request.POST)
if form.is_valid():
##Does not delete the object from models
data = form.cleaned_data['name']
DictWord.objects.filter(name=data).delete()
return render(request, 'appone/index.html', context = dict_DictWord)
else:
messages.error(request, "Error")
return render(request,'appone/index.html',context=dict_DictWord)
But if I use manage.py shell, I import my model and this syntax works, and it returns the dict with the deleted object:
from app.models import DictWord
DictWord.objects.filter(name="SomeName").delete()
#try this
record=DictWord.objects.get(name=data)
record.delete()
return render(request, 'appone/index.html', context = dict_DictWord)

Django - difficulty in image upload using forms

I want to upload an image from django forms and process it using OpenCV. Here is the code I've written with the help of Django documentation:
1.forms.py:
class UploadFileForm(forms.Form):
image = forms.ImageField()
2.views.py:
def upload_file(request):
context = {'status':'not working'}
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
context['status'] = 'working'
process(request.FILES['test_01.png'])
return render(request,'create.html',context)
else:
form = UploadFileForm()
return render(request, 'create.html', {'form': form})
Here process() is the function which processes the uploaded image.Running this code gives me MultiValueDictKey Error on the line where I call process()
After searching for the error, referring to this SO answer I changed process(request.FILES['test_01.png']) to process(request.FILES.get('test_01.png')) I get Attribute Error on the same line(which I guess is because I'm not able to retrieve the uploaded image properly)
Where am I going wrong and what is the correct way of doing so?

Upload file with Django Views

I am working on a feature for a Django application that uploads files (images in my context) to the server. Everything is working fine but I am wondering how I can receive as callback the uploaded file path.
Here is my View:
def post(self, request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['uploadedFile'])
return redirect('/')
else:
form = UploadFileForm()
return render_to_response('index.html', {'form': form})
My Form:
class UploadFileForm(forms.Form):
uploadedFile = forms.FileField()
And my handler:
def handle_uploaded_file(source):
fd, filepath = tempfile.mkstemp(prefix=source.name, dir=FILE_UPLOAD_DIR)
with open(filepath, 'wb') as dest:
shutil.copyfileobj(source, dest)
return filepath
I know that handle_uploaded_file(request.FILES['uploadedFile']) from my view is the required string that I need as callback but how to receive it in the response?
It is possible to receive instead of my index.html (it is there just for testing purposes) the path of the image for further manipulation in the frontend part.
I might sound like a noob but I really want if that works somehow.
Also is there a way for my View to handle multiple file upload? It is something that I need to change in my handler?
Sorry for putting so many questions...
Try this:
file_path = handle_uploaded_file(request.FILES['uploadedFile'])
return render_to_response('index.html', {'form': form, 'file_path': file_path})

Django self.cleaned_data not working

I'm new to the technology, so I apologyze in advance if the question is too simple.
I'm using self.cleaned_data to get the selected data entered by the user. And it works when clean is called, but not on my save method.
Here is the code
Forms.py
def clean_account_type(self):
if self.cleaned_data["account_type"] == "select": # **here it works**
raise forms.ValidationError("Select account type.")
def save(self):
acc_type = self.cleaned_data["account_type"] # **here it doesn't, (NONE)**
if acc_type == "test1":
doSomeStuff()
Any ideas why that's not working when I call save?
Here is my views.py
def SignUp(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
Thanks in advance.
The clean_<field_name methods on the form must return the clean value or raise a ValidationError. From the docs https://docs.djangoproject.com/en/1.4/ref/forms/validation/
Just like the general field clean() method, above, this method should
return the cleaned data, regardless of whether it changed anything or
not.
The simple change would be
def clean_account_type(self):
account_type = self.cleaned_data["account_type"]
if account_type == "select":
raise forms.ValidationError("Select account type.")
return account_type

Categories

Resources