{{{#!python
def validate_file_extension(value: File):
"""Check if uploaded file content is pdf"""
if value.file.content_type != 'application/pdf':
raise ValidationError("Only PDF are allowed")
def user_directory_path(instance: File, filename: str) -> str:
"""Return a unix-like storage path as string with random file name"""
filename = token_urlsafe(5) + '.pdf'
filepath = f"jobs/{filename}"
if Job.objects.filter(file=filepath).exists():
return user_directory_path(instance, filename)
return filepath
class Job(models.Model):
title = models.CharField(max_length=250)
description = models.TextField()
file = models.FileField(upload_to=user_directory_path,
validators=[validate_file_extension], blank=True, null=True)
expired_on = models.DateTimeField(blank=True, null=True)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
}}}
For now I solved it by ignoring AttributeErrors on validation
{{{#!python
class Job(models.Model):
title = models.CharField(max_length=250)
description = models.TextField()
file = models.FileField(upload_to=user_directory_path,
validators=[validate_file_extension], blank=True, null=True)
expired_on = models.DateTimeField(blank=True, null=True)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
def clean_fields(self, exclude=None):
try:
super().clean_fields(exclude=exclude)
except AttributeError:
# Handle missing content_type on file object
pass
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/32852>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* cc: Aiven Timptner (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/32852#comment:1>
* cc: Aiven Timptner (removed)
--
Ticket URL: <https://code.djangoproject.com/ticket/32852#comment:2>
Comment (by Tim Graham):
What's the traceback? Can you explain why Django is at fault?
--
Ticket URL: <https://code.djangoproject.com/ticket/32852#comment:3>
Comment (by João Freires):
Replying to [ticket:32852 Aiven Timptner]:
> I've got a model with a FileField and the corresponding admin page
created with modeladmin. To validate the file type and only allow PDFs I
wrote a custom validator which checks the content_type attribute on user
(staff) uploads. When objects are created or the file itself get changed
everything works as expected. But if I change some others fields on the
model I receive an AttributeError.
Yes, all of your validators will be called when you save a model. And your
a assuming that your file has a `content_type` attribute, but only the
file sent to a request has a content type(the TemporaryUploadedFile), when
you change your model and keep your current file, all of your validators
will receive a File and not TemporaryUploadedFile, and the File object
does not have a content type.
You can assume that all pdf files follow the pattern `*.pdf` and check if
the filename ends with the pattern and/or check the types of File,
something like:
{{{#!python
def validate_file_extension(value: File):
"""Check if uploaded file content is pdf"""
if not value.file.name.endswith(".pdf"):
raise ValidationError("Only PDF are allowed")
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/32852#comment:4>
* status: new => closed
* resolution: => invalid
Comment:
This looks like a support issue. Please see
TicketClosingReasons/UseSupportChannels for appropriate locations.
--
Ticket URL: <https://code.djangoproject.com/ticket/32852#comment:5>