Django's APPEND_SLASH setting does not work with static, why? - django

Django's 4.1.1 APPEND_SLASH setting automatically appends a slash / until I add static roots, i.e. urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT).
For example, this works with http://127.0.0.1:8000/admin and http://127.0.0.1:8000/admin/
urlpatterns = [
path('', home),
path('admin/', admin.site.urls),
]
However, adding my static roots and the setting no longer takes effect:
urlpatterns = [
path('', home),
path('admin/', admin.site.urls),
]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Why? Is this a bug? How is urlpatterns += static etc impacting Django's setting?

When you append static to your URLconf, it takes all URLs that do not match existing URL patterns and attempts to serve them through the view django.views.static.serve, which does not respect settings.APPEND_SLASH.
This should only be a problem in development, as you'll be serving static files through nginx/apache/whatever in production, but this is a good opportunity for you to sanitize all of your URLs in templates, etc. to include trailing slashes (hint: use the {% url %} template tag). You won't be able to do much about users typing URLs directly without the trailing slash, but again, this is only in development.
You can also use Whitenoise in development to get around this (http://whitenoise.evans.io/en/stable/django.html).

Related

Image url not displaying my uploaded images when django project loaded onto heroku site

My uploaded images are not loading when uploaded to heroku and I think its not related to static file issue. When i set debug = False they come fine and i know that when it is false django uses itself to host the static assests. So setting that and my images loads fine but that's not the case if i set Debug = True on heroku or on my local env. Can somebody help me solve this issue.
template
<img class="img-fluid" style="height:auto;" src="{{post.work_img.url}}" alt="Generic placeholder image">
model
class WorkExp(models.Model):
work_img = models.ImageField(upload_to="work_images/")
app/urls.py
urlpatterns = [
path("carrer/", WorkExpView, name="carrer_page"),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
project/urls.py
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("blog.urls", namespace="blog")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
In project/urls.py try this
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
instead of
+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
and set the debug = True
Check if you have static_root and are using python manage.py collectstatic.

Static url goes after the regular page url

My static files only load on index page, but when navigating to another page like: examle_url/page, it returns a 404 error since it loads it like that: http://127.0.0.1:8000/categories/default/static/js/main.js, see the static loads after page
settings.py
STATIC_URL = 'static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static_root/')
STATICFILES_DIRS = (
os.path.join(BASE_DIR, '/static/base'),
)
urls.py "all my urls are in main directory and then i import views from apps"
urlpatterns = [
path('admin/', admin.site.urls),
path('profile/', profile, name="profile"),
path('', index, name="index"),
path('category/', category, name="category"),
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
If it matters my load static files are all in theme.html file and is then extended in all other html files.
Any help will be greatly appreciated, thanks in advance!
You should prepend the STATIC_URL setting [Django-doc] with a slash:
# settings.py
# …
# with a leading slash
STATIC_URL = '/static/'
# …
If you do not do that, then the url will look like static/js/main.js. If the path does not start with a slash, then that is relative to path the current URL, and thus if the page is /categories/default, it will look at /categories/default/static/js/main.js.

django static files with a different path

I'm trying to make the local development work with everything under a /abc.
For example, instead of http://localhost:8080 I want everything to be at something like http://localhost:8080/abcd
I was able to achieve this by updating the url.py with the following:
urlpatterns = patterns('',
url(r'^abcd/admin/', include(admin.site.urls), name='admin'),
url(r'^abcd/search/?$', views.search, name='search'),
url(r'^abcd/$', views.index, name='root')
)
# Force Django to serve static assets, if this is not the production
if settings.PRODUCTION is False:
urlpatterns += patterns('', (
r'^abcd/static/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.STATIC_ROOT
}
))
Now I can view the pages with http://localhost:8080/abcd but the rendering does not show up correctly because of the static files. I need the static files to be served at http://localhost:8080/abcd/static/ and for it to work with all the pages.
Is there a simple way to make it work? I tried doing the above and it doesn't seem to work. I'm super new to django so I don't fully understand how I can achieve what I'm trying to do. Any help from experts would be much appreciated.
It should work.
urlpatterns = patterns('',
url(r'^abcd/', views.index, name='root')
url(r'^abcd/admin/', include(admin.site.urls), name='admin'),
url(r'^abcd/search/?$', views.search, name='search')
)
# Force Django to serve static assets, if this is not the production
if settings.PRODUCTION is False:
urlpatterns += patterns('', (
r'^abcd/static/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.STATIC_ROOT
}
))
change settings.py
STATIC_URL = '/abcd/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]

Django not serving media files if I check for settings.DEBUG

This serves the media files correctly:
urlpatterns = [
...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
This doesn't serve the media files:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [ ... ]
if settings.DEBUG:
urlpatterns + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
The documentation writes "This is not suitable for production use!", so that is why I need a way to check for DEBUG before serving media files. How can I do that. Why does this approach doesn't work?
Use
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
(notice '=' after '+' - in your version you are adding static() patterns but not assigning the result to the urlpatterns variable)

Url rewrite for django ajax site in dev server

I'm developing an Ajax site where routing is controlled with JavaScript.
I want every request to be sent to the IndexView except those declared in the urls.py file.
Here is my urls.py configuration:
urlpatterns = patterns('',
url(r'^api/', include('api.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^$', IndexView.as_view()),
)
If I change the regex to url(r'^', IndexView.as_view()) it works but files in MEDIA_ROOT won't be displayed.
I know in production I can config the server to serve the static files the way I want but I want it to work with the dev server.
Silly solution. Adding url(r'^', IndexView.as_view()) after,
if settings.DEBUG:
urlpatterns += patterns('',
(r'%s(?P<path>.*)' % settings.MEDIA_URL[1:], 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
)
did the job.
But I'm open to better ways for managing routing with this kind of ajax applications.