Reputation: 123
I'm doing a Django project which expects non-ascii characters, like àéã, etc. So far I have been able to navigate well this encoding hell, but I'm having problems with path names of uploaded files.
I have a model that reads thus:
class Property (models.Model):
#...
city = models.CharField(max_length = 100, choices = CITIES_LIST)
pdf_file = models.FileField(upload_to = generateUploadPath)
The upload_to calls a function that creates the path to store the file, based on the city field (which is the field that can have non-ascii characters):
def generateUploadPath (instance, file):
city = instance.city
storage_path = r'Property\{city}\{file}'.format(city = city, file = file)
return storage_path
This works well. The folders are created, if they do not exist, with the correct names, and the files are stored there correctly. Problem is, I have a post_save signal that reads said file and processes it in a particular way:
@receiver(signals.post_save, sender = Property)
def fileProcessing (sender, instance, created, **kwargs):
file_path = instance.pdf_file.path
pdf_file = open(file_path, 'r')
Here's where the code breaks. If done like that, running a form the following error pops: UnicodeEncodeError: 'ascii' codec can't encode character u'\xe1' in position 7: ordinal not in range(128). If I, instead, force an encoding with:
file_path = instance.pdf_file.path.encode('utf-8')
I get the following error: IOError: [Errno 2] No such file or directory: 'C:\Django_project\Storage\Property\Bras\xc3\xadlia\test_file.pdf', even though the folder is correctly created in Windows as '..\Property\Brasília\'.
The entire project is in UTF-8, I'm using Python 2.7.11, Django 1.9.4, db is Postgres 9.5, with the database encoding also set to UTF-8. My models.py has # -*- coding: utf-8 -*- on the top, with unicode_literals imported.
Upvotes: 0
Views: 1260
Reputation: 3516
Use python_2_unicode_compatible decorator:
from django.utils.encoding import python_2_unicode_compatible, force_text
@python_2_unicode_compatible
class Property (models.Model):
#...
city = models.CharField(max_length = 100, choices = CITIES_LIST)
pdf_file = models.FileField(upload_to = generateUploadPath)
def __str__(self):
return force_text(self.pdf_file.path)
def __unicode__(self):
return force_text(unicode(self.pdf_file.path))
def get_file_path(self):
return force_text(unicode(self.pdf_file.path))
Upvotes: 1