This is solved; thanks to @vmontco's solution: I was missing MEDIA_URL, now it works perfectly. ----------original question below-----------
I welcome suggestions from every angle; I am fairly new to Django and Python. I'm sure I am missing something simple.
Using a Model Form, with a FileField, I upload and save an Excel file to a folder structure under MEDIA_ROOT. This works.
I want to read that same file later to perform operations using Pyexcel. This is where I am stuck. I am attempting to upload the file using the FileField stored in the DB.
This is where I have problems, and I am not sure if am misunderstanding MEDIA_ROOT, or some other aspect of Django.
When I pass the pk to the 2nd view, I then instantiate an object based on the Model. It has the FileField 'docfile', which I am trying to use to access the file to do some operations using Pyexcel,
here is the FileField declaration from models.py:
docfile = models.FileField(
verbose_name="Choose file to upload:",
upload_to='Excel_CSV_Assets/%Y/%m/%d')
EDIT: If I hard-code the pth to the file like this, everything works, including operations afterwards:
thedocfile='site_static/site/original_assets/Excel_CSV_Assets/2016/04/23/Animals_oglc4DV.xlsx'
book=pyexcel.get_book(file_name=thedocfile)
:END OF EDIT
Here is the code from the 2nd view, where I attempt to read the file into memory, and make a 'book' class object using Pyexcel. I am stuck here:
asset = Excel_CSV_Asset.objects.get(id=assetid)
book=pyexcel.get_book(file_name=asset.docfile)
Here is the info right at where my code breaks:
Although it says "Wrong filename", I can see the file is in the folder:
I'm able to open the file by double-clicking; the file is not corrupted.
EDIT: If I cast the 'asset.docfile' to str, like so:
asset = Excel_CSV_Asset.objects.get(id=assetid)
book=pyexcel.get_book(file_name=str(asset.docfile))
I get a different error:
[Errno 2] No such file or directory: 'Excel_CSV_Assets/2016/04/23/Animals_oglc4DV.xlsx'
...but this is the correct directory, located beneath the MEDIA_ROOT file structure.
Here is settings.py MEDIA_ROOT:
MEDIA_ROOT = 'site_static/site/original_assets/'
Here is urls.py:
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^e/', include('excel_to_mongo.urls')),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Here is the url.py of that app:
url(r'^efactory/(?P<assetid>\d+)/$', 'display_sheet_column_choices', {}),
I think your problem is that you don't fully understand the media files management with Django.
Media files are all the files that are user-uploaded (at running time).
You must not mistake them with Static files that are assets needed by your project to work and that you add at development time (CSS, background picture and JS files for instance).
You shouldn't mix them because they are managed differently by the server and that it could lead to security problems (cf. the warning here):
You put your static files as a part of the code either in one static
subdirectory from the installed django applications, either in one of the locations you added to STATICFILES_DIRS
.
Static files have to be gathered before starting the server by calling ./manage.py collectstatic
, this command will collect (copy) the static files into the a directory (STATIC_ROOT
's value).
You then have to set STATIC_URL
to choose with wich url you should serve your static files. An usual choice would be /static/
. To access the static file you should then try to reach /static/path/to/static/file/in/static_root/dir
.
Your media files are added at running time. They are stored in the MEDIA_ROOT
location that has to be an absolute path. Hence the fact I suggested you to join the BASE_DIR
value (an absolute path) and the subdir you would choose with something like :
MEDIA_ROOT = os.path.join(BASE_DIR, "/media/subdir")
You then have to set an URL for your media files, by using the MEDIA_URL
variable. To access your media files, the urls will start with the value you choose :
MEDIA_URL = '/media/'
Then, add this to your urls.py file :
if settings.DEBUG:
urlpatterns = urlpatterns + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
With the current example, your mymediafile.txt
will be located at /path/to/your/project/media/subdir/path/in/media/root/mymediafile.txt
and served at http://127.0.0.1:8000/media/path/in/media/root/mymediafile.txt
.
But this is suitable only for a development use as told here. And this would work only for DEBUG == TRUE
For a production use, you should consider deploying your media files with your http server (apache for instance).
Take the time to understand this. Because I suspect you don't really understood what you did and this lack of understanding could lead to future bugs and errors.