Roberto Ribeiro
Roberto Ribeiro

Reputation: 123

Django encoding problems with path name

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

Answers (1)

dmitryro
dmitryro

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

Related Questions