I having some real trouble getting django to play nice with my media setup. I am not using staticfiles since I am have no need for a CDN at this point of the project and I want to keep it simple.
My folder structure looks like this:
/static
/admin
/css
/js
/etc
/css
/js
/images
The admin folder is a copy of the admin contrib media folder... since I am using mod_wsgi I know that this can't live in the django project folder.
My settings file:
MEDIA_ROOT = os.path.join(PROJECT_DIR, 'static/')
MEDIA_URL = 'http://127.0.0.1:8000/static/'
ADMIN_MEDIA_PREFIX = 'admin/' (tried with leading slash too)
Urls:
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root':MEDIA_ROOT, 'show_indexes':True}),
No matter what I try, I can't get the admin media to serve. I know from reading the documentation that the ADMIN_MEDIA_PREFIX has to be very different from the normal media url, but I need to be able to serve the files outside of the system django folder because of mod_wsgi.
Can anyone help?
For your setup, ADMIN_MEDIA_PREFIX = MEDIA_URL + 'admin/' should work.
Related
I'm trying to bundle an Angular app and deploy it as static content in a Django Rest Framework DRF application.
I don't know Django or DRF at all however, I want to take control of the routing to express something like this:
For /admin/* - delegate to built-in Django admin.
For /api/* - delegate to Django Rest Framework
For / only, and /* - treat as static content loaded from "some specified project folder", so
/ maps to file ./static/index.html
/assets/pic.jpg maps to ./static/assets/pic.jpg
I've not been able to achieve the above. All I have is this:
A template view for index.html living at ./templates/index.html - This is the from the Angular project and is not a Django template.
Other webpack bundled content copied manually to ./static such as vendor.|hash|.bundle.js
Another problem is what to do with Assets. In the angular project, HTML views refer to assets via /assets which is at the same level as index.html
I've gotten some control over paths using this command line:
ng build --deploy-url=/static --output-path=../backend/tutorial/static
The deploy-url arg results in bundled assets references in index.html being prefixed by /static which means that Django can serve them (but not favicon.ico for some reason).
The output-path arg dumps all the assets somewhere other than the default "dist" folder.
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^api/', include(router.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^', TemplateView.as_view(template_name="index.html")),
]
Url patterns looks like the above.
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static")
]
STATIC_URL = '/static/'
These are the static settings. What I need is to be able to say "/static" and "/assets" are both static asset folders.
I'm not sure what TemplateView is (urlPatterns). Maybe there's a StaticFilesView or something that maps a URL to a path on disk?
Blockquote
These are the static settings. What I need is to be able to say "/static" and "/assets" are both static asset folders.
Blockquote
You can achieve that with the following steps:
Add /assets static directory in NGINX site configuration file:
server {
....
....
# your Django project's static files - required
location /static {
alias /path/to.../static;
}
# your Angular project's static files
location /assets {
alias /path/to.../assets;
}
....
....
}
In your Django urls.py add:
from django.views.static import serve as static_serve
urlpatterns = [
....
url(r'^assets/(?P<path>.*)$', static_serve,
{'document_root':'/path/to.../assets'}),
....
....
]
That's it. You don't have to touch the static configuration in Django settings.
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(DATA_DIR, 'media')
STATIC_ROOT = os.path.join(DATA_DIR, 'static')
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'reservation_exchange', 'static'),
)
I am working on a multi-app website. And I have bunch of noob questions.
My dir structure looks like as below:
/var/www/html/portal
src/
manage.py
portal/
static/
admin/
css/
img/
js/
fonts/
templates/
base.html
homepage.html
venv/
Is my dir structure as per as Django standards?
Are my STATIC files settings correct?
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
Or should it be
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(PROJECT_DIR, 'static')
Should I collectstatic after copying all my static files such as css,js etc or I can do it before copying files in those dirs?
If I do collectstatic without mentioning STATIC_ROOT I get an exception
django.core.exceptions.ImproperlyConfigured: You're using the staticfiles app without having set the STATIC_ROOT setting to a filesystem path.
But when I replace STATICFILES_DIRS with the following, my .css files stop serving. What am I doing wrong?
STATIC_ROOT = os.path.join(PROJECT_DIR, 'static')
You don't need to run staticfiles when you're running a development server and DEBUG is set to True.
Static and media files can be then served directly via the web process (Docs) with adding these lines to your main urls.py:
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
As to the whole STATIC_URL, STATIC_ROOT, MEDIA_URL and MEDIA_ROOT, they're all related to how you'll serve your app in production, with a proper webserver.
What usually happens then is that the webserver (i.e. Nginx) handles serving files, not the Django app. But the Django app needs to know where are they. So:
STATIC_URL and MEDIA_URL need to be the same in your Django app settings and in your webserver config, for example with Nginx:
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
...
location /static {
alias /home/myusername/myproject/static/;
}
location /media {
alias /home/myusername/myproject/media/;
}
STATIC_ROOT MEDIA_ROOT are 100% about how you want to structure your project on the server. Assuming the above, you need to work out how to point it to /home/myusername/myproject/static/.
Example of my settings:
BASE_DIR = Path(__file__).parent.parent.parent
MEDIA_URL = '/media/'
MEDIA_ROOT = str(BASE_DIR.joinpath('media'))
STATIC_URL = '/static/'
STATIC_ROOT = str(BASE_DIR.joinpath('staticfiles'))
Media files will be directly uploaded to the MEDIA_ROOT, but notice that you need to somehow get the static files from your applications (which could be in a number of folders, a library you use can have some extra static files, Django Admin has then, etc.) to the folder that Nginx is pointed to (which should be the same as STATIC_ROOT). That's where collectstaticfiles comes in and copies all your static files to that directory.
In regards to directory structure, there are differences of opinion on how it should be set up. A quick google search can bring up some websites and discussions on Django project structures. I recommend reading some of the information to determine what is best for your and your project.
The Django documentation has a best practices page as well that is a good resource/reminder. Django Best Practices.
I mainly followed the Two Scoops of Django directory structure. The Two Scoops has helped me a lot in understanding this. My own twist looks something like this.
src/
app/
templates/
app_name/
base.html
other_pages.html
tests/
tests.py
app_files.py
static/
images/
css/
etc..
templates/
global_includes/
include_file.html
base.html
The collectstatic should not effect the serving of your static files during development. From what I have learned, collectstatic is more for when you are serving your static files during deployment from a separate server, or aws, heroku, etc. More info can be found here in the docs: Managing Static Files, staticfiles app, Deploying static files
I have learned that if my CSS files are not serving, it usually has something to do with my path. Chrome developer tools inspect element/console helps me with any path errors.
Have you added
+ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
to your your main urlpattern/urls.py?
Here is more information on serving files during development: Serving static files during development.
Lastly check that your BASE_DIR is following the correct path for your project. You may have to change it.
I hope this helps.
Remember that if you have DEBUG set to 'False' it will ignore the staticfiles setting because it is expected that your webserver will be serving this directly. This caught me out a few times until I realized I hadn't updated the staticfiles folder (which I keep in a separate repository for reasons I can't remember now).
This seems to work in current django (2.2) :
from django.conf.urls.static import serve
urlpatterns += [
path(settings.STATIC_URL[1:], serve, {'document_root': settings.STATIC_ROOT })
]
I'm trying to configure Django to serve static files when using runserver (production works fine). Everything works fine for all of the static files that are under an apps directory. The problem comes with static files that are not under a specific app, but are in the final static directory. For instance, I have this project structure:
/myproject/
/myproject/static/
/myproject/static/css/foo.css
/myproject/app1
/myproject/app1/static/css/bar.css
urls.py
if settings.SERVE_STATIC:
urlpatterns += patterns('',
url(r'^static/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.STATIC_ROOT}),
)
urlpatterns += staticfiles_urlpatterns() # one of these may be redundant.
settings.py
SERVE_STATIC = True
PROJECT_ROOT = '/myproject'
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')
STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(PROJECT_ROOT, 'static'),)
INSTALLED_APPS = ('app1',)
With these settings, I get the error:
ImproperlyConfigured: The STATICFILES_DIRS setting should not contain
the STATIC_ROOT setting
Which makes sense. I'm telling Django to collect static files, and put them in the same place - which could cause a loop.
If I comment out the STATICFILES_DIRS variable, django will find the static file 'bar.css'. But it does not find 'foo.css'.
If I comment out the STATIC_ROOT variable and put back the STATICFILES_DIRS, then it finds the file 'foo.css' - but of course, the 'collectstatic' command will no longer work.
Note - I realize that the '/static' directory is supposed to be empty, but the project I'm on, has files there anyway. :) As long as they're not overwritten by 'collectstatic', it looks like Django runserver should serve them - but it doesn't.
How do I serve the static files under STATIC_ROOT (such as foo.css) when running Django runserver?
Move the files that are in /static/ right now to a different directory -- call it /project-static/, for instance.
Then only include this line in urls.py:
urlpatterns += staticfiles_urlpatterns()
(remove the django.views.static.serve view)
And in settings.py, use this:
STATICFILES_DIRS = (os.path.join(PROJECT_ROOT, 'project-static'),)
Then you can put files in /project-static/ directory on your filesystem, the development server will serve them out of the /static/ URL prefix, and in production, collectstatic will find them and put them into the /static/ directory where the web server can find them.
When I use MEDIA_URL or STATIC_URL to point to /static/ currently set MEDIA_URL to /static/
and using it in a path to CSS file like:
<link rel="stylesheet" type="text/css" href="{{MEDIA_URL}}css/css.css" />
It points to /static/css.css, but trying http://localhost/static/css.css gives 404 error.
I have in settings:
.....
MEDIA_ROOT = ''
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = '/static/'
# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = 'D:/programming/django_projects/ecomstore/'
.....
In urls.py I have point to static like this:
url(r'^static/(?P<path>.*)$', 'django.views.static.serve',
{'document_root':'D:/programming/django_projects/ecomstore/'}
So where problem is? Why it is showing 404, do I need to create some view for static files? Or is there some thing else wrong in my settings or urls.py ? Any response will be appreciated, as I am newbie in django.
thanks in advance
You need to re-read the docs more closely: https://docs.djangoproject.com/en/dev/howto/static-files/
Here's some things to note:
MEDIA_URL and MEDIA_ROOT are for user uploads (FileFields and ImageFields on your models). It should be its own folder; "media" is common.
STATIC_URL and STATIC_ROOT are for your static resources. It should also be its own folder; "static" is common.
Do not actually put anything in STATIC_ROOT. This directory is only for the output of the collectstatic management command in production.
Your static resources should go in your apps' "static" folder or a completely new and different directory (i.e. not MEDIA_ROOT or STATIC_ROOT). You then add the path to that directory to STATICFILES_DIRS.
Don't add anything to urls.py. In development, Django will automatically serve anything in your apps "static" directories or any directory in STATICFILES_DIRS. In production, your webserver will be responsible for serving these files.
I'd like to love Django, but this business of static and media files in development environments is driving me nuts. Please rescue me from my stupidity.
I'm on my development machine. I have folder media in the root of my project directory.
In settings.py I have: MEDIA_ROOT = '' and MEDIA_URL = '/media/'.
In urls.py I have:
if settings.DEBUG:
urlpatterns += patterns('',
url(r'^media/(?P<path>.*)$',
'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT, }),
)
But the only way I can get media files is by referencing /media/media/ e.g.
<img src="/media/media/image.png" />.
I expect (and want)
<img src="/media/image.png" />
Can anyone tell me what is happening here, and give me a simple recipe for setting up media file handling?
Thank you very much.
#Timmy O'Mahony - thanks! epic post, and very clear. But it leaves a couple of questions:
(1) I have to use /media/ and /static/, not media/ and static/ as MEDIA_URL and and STATIC_URL - am I missing something?
(2) If collectstatic hoses /static/, where do you put site level CSS e.g. the site's CSS files? Not in /static/, evidently.
(3) I put them in a directory '_' off the project root and set STATICFILES_DIRS to point to it - and that seems to be where the development server gets its static files, despite the urlpatterns directive. If THAT is wrong, where do you put site level CSS during development, and what is the workflow around collectstatic when you modify them - do you have to edit them one place, and collect them someplace else after every edit?
Folder Setup:
Your project root should be something like:
/app1
/app2
/media
/static
/templates
urls.py
settings.py
manage.py
The media folder is supposed to hold things like images, downloads and other material that might be uploaded during normal use of the website (i.e. after development is finished)
The static folder is supposed to hold all the CSS/JS and other material that is a part of the development of the site
Settings.py:
MEDIA_ROOT is the absolute server path to the static folder mentioned above. That means it should be something like:
MEDIA_ROOT = "/User/Bob/Sites/MySite/Project_root/media/"
MEDIA_URL is the relative browser URL you should access your media files from when you are looking at the site. It should be (usually)
MEDIA_URL = "media/"
which means all material can be viewed at http://example.com/media/
Similarly, STATIC_ROOT should be something like
STATIC_ROOT = "/User/Bob/Sites/MySite/Project_root/static/"
and STATIC_URL be
STATIC_URL = "static/"
Serving the files:
Now that you have told django where these folders should be, and the correct URLs to access them, you need to serve all requests to the folders correctly.
Usually when you are in production, you want the webserver to take care of serving your static files and media files.
If you are developing though, you can just get the django development server to serve them for you.
To do this, you tell it to route all request that come in to http://example.com/media to your MEDIA_ROOT and all requests that come in to http://example.com/static to your STATIC_ROOT.
To do this, you add some URLS to URLS.py like you have:
from django.conf import settings
if settings.DEBUG:
urlpatterns += patterns('',
url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT,
}),
url(r'^static/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.STATIC_ROOT,
}),
)
Extra:
If you have multiple apps, each with their own CSS and JS files, you mightn't want to throw them into one single /static/ folder. It might be useful to put them in subfolders of the apps they belong to:
/app1/static/ # Specific static folder
/app2/static/
/media/
/static/ # Root static folder
Now, your webserver/development server is only looking for static files where you told it to look (i.e. the root static folder) so you need to collect all the files in the subfolders and copy them to the root static folder. You could do this by hand, but django provides a command to do this for you (this is the whole point of the static app)
./manage collectstatic
Why have you made the MEDIA_ROOT setting blank? It needs to be the path to your media directory. Since, as you say, your media is in a subdirectory called media, you should put that in MEDIA_ROOT.
I followed timmy procedure but I got an error that No module name django.views. When I use import django.views in my virtualenv everything works fine i.e It's not an issue with the import of library.
However, I was able to solve this problem by following this procedure in my main urls file
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
https://docs.djangoproject.com/en/dev/howto/static-files/
I had the same problem so I added these lines
from django.conf.urls import url, include
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'', include('blog.urls')),
url(r'^admin/', admin.site.urls),
url(r'^cadmin/', include('cadmin.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
in urls.py in the Django project configuration directory. more information :https://overiq.com/django/1.10/handling-media-files-in-django/
In your settings.py, make sure you add
django.core.context_processors.media
in your TEMPLATE_CONTEXT_PROCESSORS.Otherwise the MEDIA_ROOT won't work when you use it in the templates.
I am using Django 1.10. And my media folder is 'uploads'
This is the configuration in my settings.py:
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
MEDIA_URL = '/uploads/'
And in the template I put the name o my MEDIA_URL before de object.name instead object.url like this:
<img src="uploads/{{ imagen_identificativa.name }} " alt="{{imagen_identificativa}}">
And it works for me.
I hope this helps.
For Django version 3 I used the following:
from django.conf import settings
from django.urls import re_path
from django.views.static import serve
# ... the rest of your URLconf goes here ...
if settings.DEBUG:
urlpatterns += [
re_path(r'^media/(?P<path>.*)$', serve, {
'document_root': settings.MEDIA_ROOT,
}),
]
my settings.py
BASE_DIR = Path(__file__).resolve().parent.parent
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
STATIC_URL = '/static/'
here is a documentation link https://docs.djangoproject.com/en/3.1/ref/views/
In case you are using Django REST with some dev server don't forget to update your dev proxy settings to redirect /media to Django backend
Here is another alternative:
Set your media configs something like this inside 'settings.py':
#Set media path
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
MEDIA_URL = '/media/'
Lets say I have a modal called person with image filed like below:
class Person(models.Model):
name = models.CharField(max_length = 30)
photo = models.ImageField(upload_to = 'photos')
Now here upload_to path we are taking about is inside the MEDIA_ROOT folder. In my case a media folder will be created inside which photos folder will be created and our media here will be dumped.
So now in my template I do something like this:
<img src="{{ person.photo.url}} />
So in short, you got a field, use it like this:
src ={{ object.field.url}}
Hope that helps! Happy Coding!