Media folder changes in production - python

I'm developing a Django website and I have a media folder where users can upload some stuff. This folder is in my root folder and when I run the server in local (with the ./manage.py runserver) it works fine and put the files in MyApp/media/
The problem is that I have a production server Apache with the website running via mod_wsgi. The folder of my project is in /var/www/MyApp/ and it is creating my media folder in /var/www/media instead of /var/www/MyApp/media.
In my settings I have
STATIC_URL = 'static/'
MEDIA_URL = 'media/'
And the way I'm creating the path for my uploaded files is this:
def generate_path(self, filename):
url = "media/files/users/%s/%s" % (self.user.username, filename)
return url
Any idea of what in production it is changing the directory?
Thanks in advance

Configure your MEDIA_ROOT:
# Project root is intended to be used when building paths,
# e.g. ``os.path.join(PROJECT_ROOT, 'relative/path')``.
PROJECT_ROOT = os.path.abspath(os.path.dirname(__name__))
# Absolute path to the directory that will hold uploaded files.
#
# For more information on ``MEDIA_ROOT``, visit
# https://docs.djangoproject.com/en/1.8/ref/settings/#media-root
MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'uploads/')
Then, use upload_to to specify path relative to your MEDIA_ROOT.

Related

Collectstatic produces inexplicable %20 (space) in static directory urls, so CSS doesn't load

My static files aren't being served correctly because there's a strange space in my folder structure.
development folder structure
static
>css
>lots of css files
>js
>img
When I run collecstatic to serve them properly, collect static puts everything into a folder called staticfiles, here's my settings.py
settings.py
STATIC_DIR = os.path.join(BASE_DIR,'static')
MEDIA_DIR = os.path.join(BASE_DIR, 'media')
STATICFILES_DIRS = [
STATIC_DIR
]
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR,'staticfiles/static')
# MEDIA file defaults
MEDIA_ROOT = os.path.join(BASE_DIR,'staticfiles/media')
MEDIA_URL = '/staticfiles/media/'
I use it this way as this is how its configured on my live server. I now have (in my development env) a folder in the project called staticfiles/static, inside which I can find the a similar folder structure as above.
staticfiles
>img
>media
>static
>css
>admin
>img
>podcast
>js
However, once I've run the server, django thinks my CSS file 'static/%20css/front.css' and so it doesn't load. If I correct the URL to 'static/css/front.css' the css file loads perfectly...?
Here's where it's trying to get the css from:
http://127.0.0.1:8000/static/%20css/front.css
Here's where it actually is:
http://127.0.0.1:8000/static/css/front.css
I've checked the folder name for 'css' on both my development static, and the staticfiles static, and it is correct. It seems to be something to do with the way it's written the folder path?

Configure Django and Google Cloud Storage?

I am not using Appengine.
I have a plain vanilla Django application running on a VM. I want to use Google Cloud Storage for serving my staticfiles, and also for uploading/serving my media files.
I have a bucket.
How do I link my Django application to my bucket? I've tried django-storages. That may work, but what do I have to do to prepare my bucket to be used by my django application? And what baseline configuration do I need in my Django settings?
Current settings:
# Google Cloud Storage
# http://django-storages.readthedocs.org/en/latest/backends/apache_libcloud.html
LIBCLOUD_PROVIDERS = {
'google': {
'type' : 'libcloud.storage.types.Provider.GOOGLE_STORAGE',
'user' : <I have no idea>,
'key' : <ditto above>,
'bucket': <my bucket name>,
}
}
DEFAULT_LIBCLOUD_PROVIDER = 'google'
DEFAULT_FILE_STORAGE = 'storages.backends.apache_libcloud.LibCloudStorage'
STATICFILES_STORAGE = 'storages.backends.apache_libcloud.LibCloudStorage'
Django-storages has a backend for Google Cloud Storage, but it is not documented, I realised looking in the repo. Got it working with this setup:
DEFAULT_FILE_STORAGE = 'storages.backends.gs.GSBotoStorage'
GS_ACCESS_KEY_ID = 'YourID'
GS_SECRET_ACCESS_KEY = 'YourKEY'
GS_BUCKET_NAME = 'YourBucket'
STATICFILES_STORAGE = 'storages.backends.gs.GSBotoStorage'
To get YourKEY and YourID you should create Interoperability keys, in the settings tab.
Hope it helps and you don't have to learn it the hard way :)
Ah in case you haven't yet, the dependencies are:
pip install django-storages
pip install boto
Django-storages is, in fact, a viable alternative. You must be careful with it's Google Cloud backend though
as the url() method it provides causes unnecessary HTTP calls to Google. (Django calls .url() when rendering static files, for example).
https://github.com/jschneier/django-storages/issues/491
settings.py
DEFAULT_FILE_STORAGE = 'config.storage_backends.GoogleCloudMediaStorage'
STATICFILES_STORAGE = 'config.storage_backends.GoogleCloudStaticStorage'
GS_PROJECT_ID = '<google-cloud-project-id>'
GS_MEDIA_BUCKET_NAME = '<name-of-static-bucket>'
GS_STATIC_BUCKET_NAME = '<name-of-static-bucket>'
STATIC_URL = 'https://storage.googleapis.com/{}/'.format(GS_STATIC_BUCKET_NAME)
MEDIA_URL = 'https://storage.googleapis.com/{}/'.format(GS_MEDIA_BUCKET_NAME)
storage_backends.py
"""
GoogleCloudStorage extensions suitable for handing Django's
Static and Media files.
Requires following settings:
MEDIA_URL, GS_MEDIA_BUCKET_NAME
STATIC_URL, GS_STATIC_BUCKET_NAME
In addition to
https://django-storages.readthedocs.io/en/latest/backends/gcloud.html
"""
from django.conf import settings
from storages.backends.gcloud import GoogleCloudStorage
from storages.utils import setting
from urllib.parse import urljoin
class GoogleCloudMediaStorage(GoogleCloudStorage):
"""GoogleCloudStorage suitable for Django's Media files."""
def __init__(self, *args, **kwargs):
if not settings.MEDIA_URL:
raise Exception('MEDIA_URL has not been configured')
kwargs['bucket_name'] = setting('GS_MEDIA_BUCKET_NAME', strict=True)
super(GoogleCloudMediaStorage, self).__init__(*args, **kwargs)
def url(self, name):
""".url that doesn't call Google."""
return urljoin(settings.MEDIA_URL, name)
class GoogleCloudStaticStorage(GoogleCloudStorage):
"""GoogleCloudStorage suitable for Django's Static files"""
def __init__(self, *args, **kwargs):
if not settings.STATIC_URL:
raise Exception('STATIC_URL has not been configured')
kwargs['bucket_name'] = setting('GS_STATIC_BUCKET_NAME', strict=True)
super(GoogleCloudStaticStorage, self).__init__(*args, **kwargs)
def url(self, name):
""".url that doesn't call Google."""
return urljoin(settings.STATIC_URL, name)
Note: authentication is handled by default via the GOOGLE_APPLICATION_CREDENTIALS environment variable.
https://cloud.google.com/docs/authentication/production#setting_the_environment_variable
May, 2022 Update:
With this instruction, you can connect your Django app to your bucket on GCS(Google Cloud Storage) and you can serve your static files and serve, upload and delete your media files.
For example, you have the bucket "my-django-bucket" on GCS:
And you have the service account "my-django-bucket-sa" then you need to copy(Ctrl+C) the email "my-django-bucket-sa#myproject-347313.iam.gserviceaccount.com":
Next, in Bucket details of the bucket "my-django-bucket", click on "PERMISSIONS" then "ADD":
Then, to enable the service account "my-django-bucket-sa" to have the full control of GCS resources, paste(Ctrl+V) the email "my-django-bucket-sa#myproject-347313.iam.gserviceaccount.com" to "New principals" then choose the role "Storage Admin" then click on "SAVE". *Choose other role by checking IAM roles for Cloud Storage if you don't want the role "Storage Admin" which can have the full control of GCS resources:
Next, to enable all users to view(read) files, type "allUsers" to “New principals” then choose the role "Storage Legacy Object Reader" then click on "SAVE":
Then, you should be asked as shown below so click on "ALLOW PUBLIC ACCESS":
Finally, you could add the role "Storage Admin" to the service account "my-django-bucket-sa" and the role "Storage Legacy Object Reader" to "allUsers":
Next, you need to download the private key of the service account "my-django-bucket-sa" in JSON so click on "Manage keys" from the 3 dots "⋮":
Then, click on "Create new key" from "ADD KEY":
Then, choose "JSON" then click on "CREATE"
Finally, you could download the private key of the service account "my-django-bucket-sa" in JSON "myproject-347313-020754294843.json":
Now, you have a django project and there are one settings folder "core" which has "static/core/core.js" and "settings.py" and one application folder "myapp" which has "static/myapp/myapp.css" as shown below:
Then next, you need to put "myproject-347313-020754294843.json" to the root django project directory where "db.sqlite3" and "manage.py" are:
Then, you better rename "myproject-347313-020754294843.json" to a shorter and reasonable name such as "gcpCredentials.json":
Next, you need to install "django-storages[google]" to connect to and communicate with "my-django-bucket" on GCS(Google Cloud Storage):
pip install django-storages[google]
By installing "django-storages[google]", you can get "django-storages" and other necessary packages as shown below:
"requirements.txt"
django-storages==1.12.3
cachetools==4.2.4
google-api-core==2.7.2
google-auth==2.6.5
google-cloud-core==2.3.0
google-cloud-storage==2.0.0
google-crc32c==1.3.0
google-resumable-media==2.3.2
googleapis-common-protos==1.56.0
protobuf==3.19.4
pyasn1==0.4.8
pyasn1-modules==0.2.8
Be careful, if you install "django-storages" without "[google]" as shown below:
pip install django-storages
You can only get "django-storages" as shown below.
"requirements.txt"
django-storages==1.12.3
Next, create "gcsUtils.py" in "core" folder where "settings.py" is:
Then, put this code below to "gcsUtils.py" to define "Static" and "Media" variables which each have a "GoogleCloudStorage" class object:
# "core/gcsUtils.py"
from storages.backends.gcloud import GoogleCloudStorage
Static = lambda: GoogleCloudStorage(location='static')
Media = lambda: GoogleCloudStorage(location='media')
Next, add this code below to "settings.py". *"STATICFILES_STORAGE" is like the conbination of "STATIC_ROOT" and "STATIC_URL" and "DEFAULT_FILE_STORAGE" is like the conbination of "MEDIA_ROOT" and "MEDIA_URL":
# "core/settings.py"
from google.oauth2 import service_account
# Set "static" folder
STATICFILES_STORAGE = 'core.gcsUtils.Static'
# Set "media" folder
DEFAULT_FILE_STORAGE = 'core.gcsUtils.Media'
GS_BUCKET_NAME = 'my-django-bucket'
# Add an unique ID to a file name if same file name exists
GS_FILE_OVERWRITE = False
GS_CREDENTIALS = service_account.Credentials.from_service_account_file(
os.path.join(BASE_DIR, 'gcpCredentials.json'),
)
Then, run this command below:
python manage.py collectstatic
Now, "static" folder is created in "my-django-bucket":
And static files are collected from "admin" and "application" folders to "static" folder in "my-django-bucket":
And this is "myapp.css" in "myapp" folder:
But as you can see, static files are not collected from the settings folder "core" to "static" folder in "my-django-bucket":
Because "STATICFILES_STORAGE" can only collect static files from "admin" and "application" folders but not from other folders like the settings folder "core":
# "core/settings.py"
STATICFILES_STORAGE = 'core.gcsUtils.Static'
So, to collect static files from the settings folder "core" to "static" folder in "my-django-bucket":
You need to add "STATICFILES_DIRS" to "settings.py" as shown below:
# "core/settings.py"
# Collect static files from the settings folder
# "core" which is not "admin" and "application" folder
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'core/static'),
]
Then, this is the full code of "settings.py":
# "core/settings.py"
from google.oauth2 import service_account
# Collect static files from the settings folder
# "core" which is not "admin" and "application" folder
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'core/static'),
]
# Set "static" folder
STATICFILES_STORAGE = 'core.gcsUtils.Static'
# Set "media" folder
DEFAULT_FILE_STORAGE = 'core.gcsUtils.Media'
GS_BUCKET_NAME = 'my-django-bucket'
# Add an unique ID to a file name if same file name exists
GS_FILE_OVERWRITE = False
GS_CREDENTIALS = service_account.Credentials.from_service_account_file(
os.path.join(BASE_DIR, 'gcpCredentials.json'),
)
Then again, run this command below:
python manage.py collectstatic
Then, static files is collected from the settings folder "core" to "static" folder in "my-django-bucket":
And this is "core.js" in "core" folder:
Next, this is the code for "myapp/models.py":
# "myapp/models.py"
from django.db import models
class Image(models.Model):
image = models.ImageField(upload_to='images/fruits')
def __str__(self):
return str(self.image)
And this is the code for "myapp/admin.py":
# "myapp/admin.py"
from django.contrib import admin
from .models import Image
admin.site.register(Image)
Then, upload "orange.jpg":
Now, "media" folder is created in "my-django-bucket":
And "orange.jpg" is uploaded in "media/images/fruits":
And because "GS_FILE_OVERWRITE = False" is set in "settings.py":
# "core/settings.py"
# Add an unique ID to a file name if same file name exists
GS_FILE_OVERWRITE = False
If uploading the same name file "orange.jpg" again:
Then, the unique ID "_VPJxGBW" is added to "orange.jpg" to prevent file overwrite then, "orange_VPJxGBW.jpg" is uploaded as shown below:
Next, if there is "orange.jpg" in "media/images/fruits":
Then, update(change) "orange.jpg" to "apple.jpg" being uploaded:
Then, "apple.jpg" is uploaded in "media/images/fruits" but "orange.jpg" is still in "media/images/fruits" without deleted:
And if there is "orange.jpg" in "media/images/fruits":
Then, delete "orange.jpg":
But "orange.jpg" is still in "media/images/fruits" without deleted:
So, to delete uploaded files when they are updated(changed) and deleted, you need to install "django-cleanup":
pip install django-cleanup
Then, add it to the bottom of "INSTALLED_APPS" in "settings.py":
# "core/settings.py"
INSTALLED_APPS = (
...,
'django_cleanup.apps.CleanupConfig', # Here
)
Then, if there is "orange.jpg" in "media/images/fruits":
Then, update(change) "orange.jpg" to "apple.jpg" being uploaded:
Then, "apple.jpg" is uploaded in "media/images/fruits" and "orange.jpg" is deleted from "media/images/fruits":
And if there is "orange.jpg" in "media/images/fruits":
Then, delete "orange.jpg":
Then, "orange.jpg" is deleted from "media/images/fruits":
Lastly, the GCS Bucket Settings which you have just set in "settings.py" as shown below work in both "DEBUG = True" and "DEBUG = False":
# "core/settings.py"
from google.oauth2 import service_account
# Collect static files from the settings folder
# "core" which is not "admin" and "application" folder
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'core/static'),
]
# Set "static" folder
STATICFILES_STORAGE = 'core.gcsUtils.Static'
# Set "media" folder
DEFAULT_FILE_STORAGE = 'core.gcsUtils.Media'
GS_BUCKET_NAME = 'my-django-bucket'
# Add an unique ID to a file name if same file name exists
GS_FILE_OVERWRITE = False
GS_CREDENTIALS = service_account.Credentials.from_service_account_file(
os.path.join(BASE_DIR, 'gcpCredentials.json'),
)
And, there will be "STATIC_ROOT", "STATIC_URL", "MEDIA_ROOT", "MEDIA_URL" with the GCS Bucket Settings in "settings.py" as shown below. So, in this case, "STATIC_ROOT", "STATIC_URL", "MEDIA_ROOT" and "MEDIA_URL" don't work while the GCS Bucket Settings work communicating with "my-django-bucket" on GCS:
# "core/settings.py"
from google.oauth2 import service_account
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
'''GCS Bucket Settings Start'''
# Collect static files from the settings folder
# "core" which is not "admin" and "application" folder
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'core/static'),
]
# Set "static" folder
STATICFILES_STORAGE = 'core.gcsUtils.Static'
# Set "media" folder
DEFAULT_FILE_STORAGE = 'core.gcsUtils.Media'
GS_BUCKET_NAME = 'my-django-bucket'
# Add an unique ID to a file name if same file name exists
GS_FILE_OVERWRITE = False
GS_CREDENTIALS = service_account.Credentials.from_service_account_file(
os.path.join(BASE_DIR, 'gcpCredentials.json'),
)
'''GCS Bucket Settings End'''
So, if you want "STATIC_ROOT", "STATIC_URL", "MEDIA_ROOT" and "MEDIA_URL" to work, just comment the GCS Bucket Settings then set "STATICFILES_DIRS" as shown below:
# "core/settings.py"
from google.oauth2 import service_account
# Collect static files from the settings folder
# "core" which is not "admin" and "application" folder
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'core/static'),
]
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
"""
'''GCS Bucket Settings Start'''
# Collect static files from the settings folder
# "core" which is not "admin" and "application" folder
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'core/static'),
]
# Set "static" folder
STATICFILES_STORAGE = 'core.gcsUtils.Static'
# Set "media" folder
DEFAULT_FILE_STORAGE = 'core.gcsUtils.Media'
GS_BUCKET_NAME = 'my-django-bucket'
# Add an unique ID to a file name if same file name exists
GS_FILE_OVERWRITE = False
GS_CREDENTIALS = service_account.Credentials.from_service_account_file(
os.path.join(BASE_DIR, 'gcpCredentials.json'),
)
'''GCS Bucket Settings End'''
"""
So, this basically will work. (With this library and settings).
The trick to making it work, is knowing where to get the 'user' and 'key' parameters for libcloud.
On Google Cloud Console > Storage, click Settings. Then click on the right-hand tab called Interoperability. On that panel, is a lone button, which says something like Enable Interoperability. Click it.
Voila! You now have a username and key.
Note: Do not use django-storages from pypi. It has not been updated, and doesn't work with recent releases of Django.
Use this version:
pip install -e 'git+https://github.com/jschneier/django-storages.git#egg=django-storages'
Edit: If you want to use a reverse proxy, then you may consider my slightly modified version.
https://github.com/jschneier/django-storages/compare/master...halfnibble:master
Description:
Under certain circumstances, it may be necessary to load files using a reverse proxy. This could be used to alleviate cross-origin request errors.
This small PR allows the developer to set an optional LIBCLOUD_PROXY_URL in settings.py.
Example Usage
# Apache VirtualHost conf
ProxyPass /foo http://storage.googleapis.com
ProxyPassReverse /foo http://storage.googleapis.com
# settings.py
LIBCLOUD_PROXY_URL = '/foo/'
As the latest version, access key and key ID changed to service account file. And we want to use a bucket with 2 folders static and media like a local server. Below low the update configs:
Create a file like gcloud_storages.py:
"""
Modify django-storages for GCloud to set static, media folder in a bucket
"""
from django.conf import settings
from storages.backends.gcloud import GoogleCloudStorage
class GoogleCloudMediaStorage(GoogleCloudStorage):
"""
GoogleCloudStorage suitable for Django's Media files.
"""
def __init__(self, *args, **kwargs):
kwargs['location'] = 'media'
super(GoogleCloudMediaStorage, self).__init__(*args, **kwargs)
class GoogleCloudStaticStorage(GoogleCloudStorage):
"""
GoogleCloudStorage suitable for Django's Static files
"""
def __init__(self, *args, **kwargs):
kwargs['location'] = 'static'
super(GoogleCloudStaticStorage, self).__init__(*args, **kwargs)
Use location argument to set the location of static, media files in bucket.
In settings.py
from google.oauth2 import service_account
...
GOOGLE_APPLICATION_CREDENTIALS = '/path/service-account.json'
DEFAULT_FILE_STORAGE = 'app.gcloud_storages.GoogleCloudMediaStorage'
STATICFILES_STORAGE = 'app.gcloud_storages.GoogleCloudStaticStorage'
GS_BUCKET_NAME = 'name-of-bucket'
GS_PROJECT_ID = 'project-id'
GS_DEFAULT_ACL = 'publicRead'
GS_CREDENTIALS = service_account.Credentials.from_service_account_file(
GOOGLE_APPLICATION_CREDENTIALS
)
Since I cannot comment on Alan Wagner's answer, here is an addition.
If you are using python3, you may get this error,
...
ImportError: No module named 'google_compute_engine'
If so, you will need to install google-compute-engine. The /etc/boto.cfg file tells python to use the 2.7 version of the library. You will have to run this next line to regenerate /etc/boto.cfg.
python3 -c "from google_compute_engine.boto.boto_config import BotoConfig; BotoConfig()"
Another error you may hit,
...
File "/app/venv/lib/python3.4/site-packages/boto/gs/connection.py", line 95, in create_bucket
data=get_utf8_value(data))
File "/app/venv/lib/python3.4/site-packages/boto/s3/connection.py", line 656, in make_request
auth_path = self.calling_format.build_auth_path(bucket, key)
File "/app/venv/lib/python3.4/site-packages/boto/s3/connection.py", line 94, in build_auth_path
path = '/' + bucket
TypeError: Can't convert 'bytes' object to str implicitly
I made a pull request to fix this. You may use my repo as a pip dependency if you wish until it gets merged.
I will try to keep this repo up to date. I have set the default develop branch as protected. I am the only one who can commit/approve merge requests. I have also only made one commit.
You will have to install google-compute-engine and run that line above before you can instalkl/build my boto repo.
I have detailed my step by step process on another thread
Serve Static files from Google Cloud Storage Bucket (for Django App hosted on GCE)
Here are my main references:
https://django-storages.readthedocs.io/en/latest/backends/gcloud.html
https://medium.com/#umeshsaruk/upload-to-google-cloud-storage-using-django-storages-72ddec2f0d05
I used the following packages:
pip3 install django-storages # https://pypi.org/project/django-storages/
pip3 install google-cloud-storage # https://pypi.org/project/google-cloud-storage/

my django project static files can not be load with option debug=false

It is very strange that my django website (setup on a linux server with django 1.3) can be visit correctly with DEBUG = True. But when I changed the option to DEBUG = False the static content won't load (css files and images can not be found)
Here's related options i got in my setting.py:
DEBUG = False
STATIC_ROOT = ''
ADMIN_MEDIA_PREFIX = '/static/admin/'
STATICFILES_DIRS = ("/home/ubuntu/ls_website/static/",)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
Anybody have any idea? If the version is too low, I would wait a while for 1.5 release.
I found when debug=False, django won't load static files automatically. Options are set static path in urls.py or serve static files with apache.
People said set static path in urls.py is slower than serve static files with apache. Don't know why though...
Staticfiles doesn't do anything when DEBUG=False. You need to serve those files with apache. Staticfiles has the ability to collect the files to one spot for you to make it easy, then you use some apache magic (assuming here since you didn't specify) to have apache intercept those requests and serve the static files for you.
Alias /robots.txt /home/username/Python/project/site_media/static/robots.txt
Alias /favicon.ico /home/username/Python/project/site_media/static/favicon.ico
Alias /static/ /home/username/Python/project/site_media/static/
I don't remember if it is buildstatic, build_static, collectstatic or collect_static to copy those files from your development stop to your deployment spot, but these variables control how staticfiles does its magic
# Absolute path to the directory that holds static files like app media.
# Example: "/home/media/media.lawrence.com/apps/"
STATIC_ROOT = os.path.join(PROJECT_ROOT, "site_media", "static")
# URL that handles the static files like app media.
# Example: "http://media.lawrence.com"
STATIC_URL = "/static/"
# Additional directories which hold static files
STATICFILES_DIRS = [
os.path.join(PROJECT_ROOT, "static"),
os.path.join(PROJECT_ROOT, "media"),
]
This assumes your static files are in the static folder of your project, and you want to serve them from the site_media folder.
I also move between Windows and Linux for development. To get around the problem of absolute paths in settings.py, I use this function:
def map_path(directory_name):
return os.path.join(os.path.dirname(__file__),
'../' + directory_name).replace('\\', '/')
Which you can implement in this fashion:
STATICFILES_DIRS = (
map_path('static'),
)
This function is tailored for Django 1.4.x. You'll need to modify it slightly for Django 1.3.x. Hope that helps you out.

django ImageField not uploading the file

So i've been googling this issue for the past hour and can't come up with a solution. Basically this is it: in my model.py i have a class that has this
class Case(models.Model):
zoomOutImage = models.ImageField('Label', upload_to="zoomOutImage")
and in my settings.py i have my media URL/ROOT set up like this
MEDIA_ROOT = os.path.join(os.path.abspath(''),'app/static/ds/')
MEDIA_URL = '/static/ds/'
which from the webserver should serve out like this:
http://127.0.0.1:8000/static/ds/zoomOutImage/actinic_granuloma_3.jpg
I've installed PIL (inside virtualENV) and there are no errors in uploading, the only issue is when i try uploading the file via the admin panel nothing happens. No errors nothing. The file just simply doesn't get uploaded to the zoomOutImage folder by the development server. Can anyone point me towards why?
I guess your file is in a subdir of your root, subdir named 'zoomOutImage'. Or even a file called like that in the root. I remember putting a function call in the upload to string. That function creates a path and filename, using os.join and the filename from the instance. Doing this by head, no example code available right now. But must be able to google this.
Look here https://stackoverflow.com/questions/1190697/django-filefield-with-upload-to-determined-at-runtime
And by the way, I totally disagree with your answer, you should NEVER use absolute paths in your settings! See this answer use css in django 1.4 development for how to use the correct settings and refer to your Project PATH
EDIT (after reading your own answer)
Guess you are missing this first step:
this is the path to your settings.py file:
SETTINGS_DIR = os.path.dirname(os.path.realpath(__file__))
and than this is the path to your project dir: (I Am using buildout, so call it buildout, but it's the root of your project):
BUILDOUT_DIR = os.path.abspath(os.path.join(SETTINGS_DIR, '..'))
and from there on you can define everything you want:
STATIC_ROOT = os.path.join(BUILDOUT_DIR, 'var', 'static')
STATIC_URL = '/static_media/'
MEDIA_ROOT = os.path.join(BUILDOUT_DIR, 'var', 'media')
MEDIA_URL = '/media/'
and in your template file refer to the image like:
<img src="{{MEDIA_URL}}{{ case.zoomOutImage }}" width="100%">
when your object given to the template is called case
about your question of the urls.
you should add this:
if settings.DEBUG:
urlpatterns += patterns('',
(r'', include('staticfiles.urls')),
)
and see the link above to the question about using css, it's the same problem, but there for finding the css files during development. It's all about the static file places.
import os
# get abspath
def rel(*x):
return os.path.join(os.path.abspath(os.path.dirname(__file__)), *x)
MEDIA_ROOT = rel('media')
MEDIA_URL = '/media/'
STATIC_URL = '/static/'
STATIC_ROOT = '' #if only your static files are in project folder
STATICFILES_DIRS = ( rel('static'),) #if only your static files are in project folder
use this settings, and everything will work
so i finally solved my problem. For anyone having this issue in the future do the following:
if you're trying to serve static media files locally on the development server use absolute paths for MEDIA_ROOT and MEDIA_URL.

What is the difference between static files and media files in Django?

I'm moving to Django 1.3 and find this separation of media and static files a bit confusing. Here is how default settings.py looks like:
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = ''
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = ''
# Absolute path to the directory that holds static files.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = ''
# URL that handles the static files served from STATIC_ROOT.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'
What should I put into MEDIA_ROOT and a STATIC_ROOT? Should those be separate directories? What is the difference?
Static files are meant for javascript/images etc, but media files are for user-uploaded content.
As Uku Loskit said, static files are for things like your applications' css files, javascript files, images, etc. Media files are typically user or admin uploadable files.
Normally you will want MEDIA_ROOT and STATIC_ROOT to be separate directories. Keep in mind that STATIC_ROOT is where the management command collectstatic will place all the static files it finds. In production, you then configure your webserver to serve the files out of STATIC_ROOT when given a request that starts with STATIC_URL. If you are using the Django devserver for development, it will automatically serve static files.
The staticfiles application thus disentangles user uploaded media from application media, thus making deployment, backups, and version control easier. Prior to the staticfiles app, it was common for developers to have the media files mixed in with static application assets.
The 1.3 docs for staticfiles have been steadily improving; for more details, look at the how-to.

Categories

Resources