What's the difference between these two in settings.py of Django project
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
The function abspath will create a clean directory name, from root. For example ../dir may be converted to /path/to/dir (Or C:\... for Windows).
However the double dirname call does not seem useful.
Related
As part of my view logic I need to check if Latitude and Longitude points are withing city boundaries.
To do that, I am using city shapefiles with geopandas. It all works ok locally in plain python code.
However, when I run the following code in Django:
LA_geo_df = gpd.read_file('./City_Boundaries/City_Boundaries.shp')
I get the error:
DriverError at /
./City_Boundaries/City_Boundaries.shp: No such file or directory
What is the proper Django way of loading such files?
Auto-generated Django settings file will have a BASE_DIR setting that looks like this
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
This is an absolute file path to the root of your Django app. You can use this setting to build an absolute path to your file
CITY_BOUNDARIES_FILE_PATH = os.path.join(BASE_DIR, 'City_Boundaries', 'City_Boundaries.shp')
Then where you want to load the file you can use the setting
from django.conf import settings
LA_geo_df = gpd.read_file(settings.CITY_BOUNDARIES_FILE_PATH)
I have a Django app that I just added to the already deployed Django web on Apache.
Because it is ran by Apache, path of the media folder seems to be different.
My app lets the user upload an excel file which then changes numbers and save as csv file.
(only showed relevant folders/code snippets)
Current directory
converts\
_init_.py
apps.py
forms.py
models.py
converter.py
urls.py
views.py
main\
settings.py
urls.py
wsgi.py
meida\
excels\
example.xlsx
csvs\
example.csv
static\
manage.py
settings.py
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
main\urls.py
urlpatterns = [
path('', RedirectView.as_view(url='/converts/')),
path('converts/', include('converts.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
The part that causes the problem is the following in converts/converter.py:
def convertExcel(name):
path = 'media/excels/'
key = path + name
wb = load_workbook(key)
Originally in development, a function in view calls convertExcel(example.xlsx) and the workbook, via media/excels/example.xlsx, finds the correct file to work with the loaded workbook. But in production server, it gives
FileNotFoundError: [Errno 2] No such file or directory: 'media/excels/example.xlsx'
My Question is:
Do I have to back track from where apache2.conf is to find the path? Or is there a way to set path to my django project so i can just set path in my convertExcel() as 'media/excels'? Or is there any other way I can call the uploaded workbook?
Any kind of help/comment would be appreciated.
Please comment if additional information is needed.
My guess is that you should use MEDIA_ROOT variable because it points to the uploaded files. So you would have
def convertExcel(name):
from django.conf import settings
path = os.path.join(settings.MEDIA_ROOT, 'excels')
key = os.path.join(path, name)
wb = load_workbook(key)
Django 1.11
The documentation shows that we should place, say, images to
/var/www//media/
https://docs.djangoproject.com/en/1.11/ref/settings/#media-root
But in the book "Two Scoops of Django" they recommend:
# Configuring MEDIA_ROOT
# ’DONT DO THIS! Hardcoded to just one user's preferences
MEDIA_ROOT = "/Users/pydanny/twoscoops_project/media"
And then suggest their way:
root = lambda *dirs: join(abspath(BASE_DIR), *dirs)
# Configuring MEDIA_ROOT
MEDIA_ROOT = root("media")
Do you accept the way Two Scoops of Django recommends?
In this case MEDIA_ROOT will be inside the project itself. This is bad, I think. This is somehow a mix of code and user data.
So, I like what the documentation of Django recommends: just hardcode a path to /var/www/example.com/media/.
MEDIA_ROOT is not even STATIC_ROOT. Static files are collected from inside the project. And they contain something which is more or less (CSS) a code. Whereas user uploaded files are definitely the data, not the code.
Could you comment? What your MEDIA_ROOT looks like?
Shall I use different MEDIA_ROOTS for my local machine and the production serve?
I once used following :
ENV_PATH = os.path.abspath(os.path.dirname(__file__))
MEDIA_ROOT = os.path.join(ENV_PATH, 'media/')
This will automatically detect the absolute path to the settings.py file and create media_root path.
In the new template for settings django 1.6 generates the following code:
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
However this has never worked for me and I keep changing it to
import os
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
Is their code wrong or am I missing something? The idea of this BASE_DIR is to avoid hardcoding dir names.
The idea behind os.path.dirname(os.path.dirname(__file__)) is to get two directories above your settings directory.
Your code os.path.abspath(os.path.dirname(__file__)) is the same as os.path.dirname(__file__).
You probably changed where your settings.py resides and for that you must change its path.
Ok so I recall there are some commands you could put in the settings.py file so that basically when you move your django project to another directory it won't get foo-bar'd up.
I know I could just do this by having a string variable everywhere it mentions the home directory but is there a more elegant way of doing this?
The architecture of a project in Django
root/
app1/
app2/
...
main/
settings.py
Inside settings.py:
SITE_ROOT = os.path.dirname(os.path.realpath(__file__)) -> gives the path of the file settings.py: root/main/. This is NOT THE ROOT OF THE PROJECT
PROJECT_PATH = os.path.abspath(os.path.dirname(__name__)) -> gives the root of the project: root/. This is THE ROOT OF THE PROJECT.
Django 1.8 already includes the project root directory as BASE_DIR:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
And you can use it in your app by importing settings:
from django.conf import settings
...
...
print(settings.BASE_DIR)
Grab the __file__ global, and use the various functions in os.path on it.
import os.path
SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
PROJECT_PATH = os.path.abspath(os.path.dirname(__name__))