I have read other topics on stackoverflow and on the django website, but I am still confused.
These are my configurations:
STATIC_ROOT = os.path.join(BASE_DIR, 'assets')
STATIC_URL = '/static/'
When I run manage.py collectstatic , my static files will be collected at myproject/assests/
I will store a default profile photo (for using with my models) here: myporject/static/images/default_profile_photo.png, so when I run collect static, it will be coppied in myproject/assets/images/default_profile_photo.png
Everything fine so far.
On my models.py I have a field:
class UserProfile(models.Model):
photo = models.ImageField(upload_to = get_upload_file_name,
storage = OverwriteStorage(),
default = 'path/to/my/default/image.jpg'))
My main question is: what path should I set to this default atribute? should I benefit from the STATIC_URL somehow?
Other questions: How can I user here the STATIC_URL from settings.py? and what is the usage of STATIC_URL? where and how can I see the effect between using STATIC_URL='/static/' and STATIC_URL='/wtf/'
os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))), 'static', 'templates'),
for each "os.path.dirname( )" I have one more within the following, which corresponds to a parent directory, so in my example I have four of them, it clarifies the root folder as being 4 folders above the current directory.
Files that are uploaded always go in a subdirectory of MEDIA_ROOT and are referenced from MEDIA_URL.
For any FileField (like ImageField), you simply give the subdirectory that will be used to store the files that are uploaded to this model.
If you have MEDIA_ROOT as '/foo/bar/uploads/', then in your models you have this:
class Foo(models.Model):
photo = models.ImageField(upload_to='photos')
Then all photos uploaded will be stored in /foo/bar/uploads/photos/.
Unlike collectstatic, there is no command to manage media files. You have to deal with them on your own.
Now on setting a default value; in addition to a path, you can add the name of a callable (a function), that is called whenever an instance of the object is saved. You can exploit this:
import os
from django.contrib.staticfiles import finders
from django.config import settings
def get_default_photo_path():
results = finders.find('/default/image.jpg')
if results:
return os.path.join(settings.STATICFILES_DIRS[0], results[0])
class Foo(models.Model):
photo = models.ImageField(upload_to='photos',
default=get_default_photo_path, null=True)
Now, whenever a new object is created, the default value is the static file path to /default/image.jpg. If for some reason this file doesn't exist (for example, you forgot to add it), None will be returned. In other to store that, you have to set null=True.
Related
I am trying to use django-storages with s3boto in my app and trying to serve media and static files from s3.
I have the following settings in my settings file:
AWS_STORAGE_BUCKET_NAME = '<bucket_name>'
AWS_S3_ACCESS_KEY_ID = '<access_key>'
AWS_S3_SECRET_ACCESS_KEY = '<secret>'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
STATICFILES_LOCATION = 'static'
STATICFILES_STORAGE = '<custom_storage_satic>'
MEDIAFILES_LOCATION = 'media'
DEFAULT_FILE_STORAGE = '<custom_storage_media>'
And my custom_storages.py is
from django.conf import settings
from storages.backends.s3boto import S3BotoStorage
class StaticStorage(S3BotoStorage):
location = settings.STATICFILES_LOCATION
class MediaStorage(S3BotoStorage):
location = settings.MEDIAFILES_LOCATION
When I create an image in django, instead of getting the relative path to my image starting with
image.url
'/media/image/<rest_of_the_path>.jpg'
I am getting the absolute url, which is something like
image.url
'https://<s3_bucket_name>.s3.amazonaws.com/media/image/original/'
When I use local storage instead of s3boto, it works as expected and gives me the relative path. Am I missing something here?
I struck the same issue when attempting to use the Imgix CDN for my S3 media (I suspect we're both using the same tutorial based on your use of the custom_storages.py override).
Here is an abridged version of the S3BotoStorage class in the django-storages framework. This excerpt highlights the important properties and methods for this issue, namely the custom-domain property.
class S3BotoStorage(Storage):
location = setting('AWS_LOCATION', '')
custom_domain = setting('AWS_S3_CUSTOM_DOMAIN')
def url(self, name, headers=None, response_headers=None, expire=None):
# Preserve the trailing slash after normalizing the path.
name = self._normalize_name(self._clean_name(name))
if self.custom_domain:
return "%s//%s/%s" % (self.url_protocol, self.custom_domain, filepath_to_uri(name))
As you can see in the url method, a URL is generated to override the STATIC_URL and MEDIA_URL Django settings. Currently the domain of the URL is created with the AWS_S3_CUSTOM_DOMAIN setting, which is why you continue to see the static S3 URL for media files.
So first, in your Django settings file, add a setting describing your CDN's domain.
IMGIX_DOMAIN = 'example.imgix.net'
Then, similar to the override of the location property, add an override to the custom_domain property in your MediaStorage class.
class MediaStorage(S3BotoStorage):
location = settings.MEDIAFILES_LOCATION
custom_domain = settings.IMGIX_DOMAIN
Now the final URL to your media files should begin with your CDN's domain, followed by the relative path to your file on the S3 bucket.
If you are serving static media from an S3 bucket, you must use an absolute URL, since the media is being served from a wholly different server.
I'm working on a Django application, which permits to manage music files (upload, read, delete, ...).
I'm using MEDIA_ROOT system for the music uploads, which works perfectly !
But, to read or delete a file in MEDIA_ROOT, I don't know ... (except with variable in script..).
For example, if I need to read a music with Mplayer, my actual solution in views.py :
media_root = "/home/music/"
command = ("sudo /usr/bin/mplayer "+media_root)
path = music.path
p = subprocess.Popen(command+str(music.path), shell=True)
Is there any (secure) way to access to the MEDIA_ROOT from views.py / models.py ??
Thanks
You can access the settings by simply doing
from django.conf import settings
settings.MEDIA_URL
https://docs.djangoproject.com/en/dev/topics/settings/#using-settings-in-python-code
I am developing Django (1.6) app. In my app I have to use the static images to be displayed on the HTML pages (like magnifying glass for search box,logo,etc). After little bit of research I came to know that we have to create a folder (say "static") which holds the static images and then I have mention the path in my settings.py like shown below :
`STATIC_URL = '/static/'
STATICFILES_DIRS = (
"C:/Users/Welcome/Desktop/business/static/polls",
"C:/Users/Welcome/Desktop/business/static",
)`
I also added the code shown below in urls.py too after which I could get the images on my HTML pages.
urlpatterns = patterns(''......... ...........) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
My question now is every time I change the directory (current working directory or if I transfer the project to another pc ) I have to update the path in settings.py.
How to not do that ? how to get path of "static" folder automatically when I run my project. Please do help. What I'm missing ?
Normally the static files finder of django will expect that your app itself has a static sub-directory, and you can store everything there.
+ myproj
- manage.py
+ app
- __init__.py
- settings.py
- urls.py
+ static <-- notice the static directory.
+ templates
This is good of course for development where the Django server is the one serving these static files. In production you'll need to collect everything to the location declared in your STATIC_ROOT setting with the collectstatic management command.
This way you won't need to change the location each time you copy your project to a new location or a new computer.
Of course, that once you do that you can drop the STATICFILES_DIRS definition from your settings.py. This setting is used to tell Django that there are other static assets that reside outside of a certain app. If you want to use it anyway then you can define those directories relative to the project itself, i.e.:
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static")
)
Your urls.py should then use the staticfiles_urlpatterns like this:
if settings.DEBUG:
urlpatterns += staticfiles_urlpatterns()
For more information see the Django documentation on static files:
https://docs.djangoproject.com/en/1.7/howto/static-files/
I just figured out the solution for my question. First you need to get the current working directory and then for looking out for the folder in that current working directory(where your project is being installed) assign this to variable say path_for_images and then pass it to the STATICFILES_DIR as shown below:
path_for_images = os.getcwd()+"\static"
STATICFILES_DIRS = ( path_for images,) <-- note ,(comma) after `path_for_images`
No need to do any changes for the urls.py and images get loaded. This isn't exact pythonic way but it's surely one of the way.
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.
I'm writing a view that displays a set of images on a page.
This is the model
#models.py
class Movie(models.Model):
title = models.CharField(max_length = 500)
poster = models.ImageField(upload_to = 'qanda/static/movie_posters')
#index.html
<img src = "{{ STATIC_URL }}movie_posters/{{ movie.poster }}"></a>
When I runserver, the image doesn't appear. The URL the image is trying to load is
http://127.0.0.1:8000/static/movie_posters/qanda/static/movie_posters/image.jpg
When the URL it should be trying to load is
http://127.0.0.1:8000/static/movie_posters/image.jpg
My assumption is that since movie.poster is located at 'qanda/static/movie_posters', when I render it on HTML, it is loading the Static URL (127.0.0:8000/static) and then the location 'qanda/static/movie_posters' at the end. How do I make the image render correctly?
There are two pieces of how image url is calculated.
First in your settings.py you define MEDIA_ROOT. MEDIA_ROOT specifies an absolute folder on your computer where media will be stored. So for example for these settings:
MEDIA_ROOT = '/abs/path/to/media/'
and if you have a field
models.ImageField(upload_to='movie_posters')
then images will be stored at:
/abs/path/to/media/movie_posters/
/abs/path/to/media/movie_posters/poster.jpg <- example
This deals with where media is stored on your hard drive.
Second piece is how to calculate urls for these media files. For that you define MEDIA_URL in your settings.py. That essentially maps a URL to your MEDIA_ROOT location. So then if your MEDIA_URL is:
MEDIA_URL = 'http://localhost/media/'
Then if you want to access an image stored at movie_posters/poster.jpg which has an absolute path of /abs/path/to/media/movie_posters/poster.jpg, its URL should be http://localhost/media/movie_posters/poster.jpg. You can compute the URL by doing:
{{ MEDIA_URL }}{{ movie.poster }}
Please note that I am using MEDIA_URL instead of STATIC_URL. Those are not the same thing. Computing urls like that however is not very neat. Thats why Django's ImageField and FileField have an url attribute:
{{ movie.poster.url }}
Django will then compute the proper url depending on your MEDIA_URL setting.
Note:
For all of this to work, you have to have a separate media server running. Django does not serve any media files. In development it is only capable of serving static file (not same as media files). So in development one nice trick to serve media files is to use Python's simple web server. For that, open a new terminal (on Linux and Mac) or Command Prompt (on Windows) window/tab and navigate to your media folder. Then just execute the following command there:
python -m SimpleHTTPServer 8090
and make sure your setting is:
MEDIA_URL = 'http://localhost:8090/'
and then Python will serve your media files. That works nice for development.
If you want to serve your media just using the development server you can add this for the time being to your urls.py
urlpatterns = patterns( ...all your awesome urls...) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
you can define a custom template tag which returns the basename of the URL like this:
from django import template
import os
register = template.Library()
#register.filter
def getBasename(myURL):
return os.path.basename(myURL)
this should go in your custom template tags (eg. customTemplateTags.py) file within your templatetags directory of your app.
Then you can use the filter in order to get only the image filename, not the entire URL.
{% load customTemplateTags %}
<img src = "{{ STATIC_URL }}movie_posters/{{ movie.poster.url|getBasename }}"></a>