Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to get (txt) file content from FileField?

I have a problem with opening a text file in django that is stored in my database. I want to access it via FileField of my model... the model looks something like this

   class MyModel(models.Model):
      saved_file = FileField()

I upload a test file via admin interface, which works ok. In my view I want to access this file. If I open it with standard python open() it works ok...

 f = open(path, 'r')
 a = f.readlines()
 return render_to_response('base.html', {'content': a}, context_instance=RequestContext(request))

this displays lines of the file ok... according to https://docs.djangoproject.com/en/dev/ref/models/fields/#filefield one gets a FieldFile proxy when FileField from a model is called, so

 f = MyModel.objects.all().get(id=0).saved_file

should store FieldFile in f, furthermore documentation states that one opens a file from model by casting .open(mode='rb') on FieldFile, so

file = f.open(mode='rb') 

should work like python .open() as stated in the documentation. So to get lines I do

file.readlines()

should return me list of lines. What happens is that I get an error saying that .readlines() atribute does not exist. I do not need the file to display it, this is just a way to test if opening a file works, but I need the file content in a variable in my view to further use it in my business logic. Could anyone suggest a way to get the file content out of a FileField frem a model?

like image 545
user1035617 Avatar asked Nov 16 '12 08:11

user1035617


2 Answers

The documentation states that files are opened in 'rb' mode by default, but you would want to open in 'r' to treat the file as a text file:

my_object = MyModel.objects.get(pk=1)
try:
    my_object.saved_file.open('r')
    lines = my_object.saved_file.readlines()
finally:
    my_object.saved_file.close()

Even better, you can use a context manager in Django v2.0+

my_object = MyModel.objects.get(pk=1)
with my_object.saved_file.open('r') as f:
    lines = f.readlines()
like image 136
mattdedek Avatar answered Sep 19 '22 14:09

mattdedek


Since Django 2.0 File.open does return you a file, so suggested way to work is as with context manager:

saved_file = MyModel.objects.all().get(id=0).saved_file
with saved_file.open() as f:
    data = f.readlines()

Applies to old versions of Django < 2

FieldFile.open opens the file, but doesn't return anything. So in your example file is None.

You should call readlines on FieldFile. In your example it would be:

f = MyModel.objects.all().get(id=0).saved_file
try:
    f.open(mode='rb') 
    lines = f.readlines()
finally:
    f.close()

UPD: I added try/finally block, as the good practice is to always close the resource, even if exception happened.

like image 33
Igor Avatar answered Sep 23 '22 14:09

Igor