Why does altering STATIC_URL in Django disrupt ADMIN_MEDIA_PREFIX - python

Trying to gain some high level clarity on how Django serves (admin) static files.
When altering the STATIC_URL setting in Django's settings.py to a new location (I'm serving images from a 3rd party server) it seems to disrupt ADMIN_MEDIA_PREFIX and thus stop the Admin media (css, images, js) from being served.
Why does this happen? I though STATIC_URL and ADMIN_MEDIA_PREFIX should pertain to different parts of the application and not influence eachother.

Which version of Django do you use? Before Django 1.4, the STATIC_URL and ADMIN_MEDIA_PREFIX are indeed different parts. In Django 1.4, ADMIN_MEDIA_PREFIX is deprecated and STATIC_URL is used solely.
The way you're using to serve corresponding files is important also. You could check the URLs of media files in the admin page: if they are generated correctly but cannot get loaded, it might be caused by mis-configured web server instead of Django itself.

Related

Django on Heroku - missing staticfiles manifest.json file

I am trying to start Django on Heroku. I looked around Stack Overflow, I tried different things, but I cannot figure it out. It looks similar to all the questions related to staticfiles problem on Django, unfortunately I don't know where the problem is. My project runs just fine with DEBUG = True, but when I change it to False, I get following traceback:
2020-11-09T13:13:42.801384+00:00 app[web.1]: Missing staticfiles manifest entry for 'order/css/open-iconic-bootstrap.min.css'
It happens on all of my apps that require staticfiles. I tried to find manifest.json, but it does not exist. So I think this is the issue.
Here are my relevant settings:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
#more ...
]
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedStaticFilesStorage'
django_heroku.settings(locals())
Thanks for looking into this!
#keome in the comments already gave you the first steps in debugging this issue so I won't repeat that here.
Notwithstanding the issues they raised (which should be looked at first), I think the key issue is that your whitenoise configuration isn't set up to generate a manifest. You probably want:
# Serve compressed and manifested static files
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
The reason your current configuration would work with DEBUG=1 is that in debug mode, django will fall back to serve static files itself (neither secure nor efficient).
Second, make sure that you run collectstatic with the same storage configuration as you're running the server - I cant see what settings files you have, but it seems like you've collected static without a manifesting strategy, but you're trying to serve it with a manifesting strategy (and hence django is confused by why there isn't a manifest).
Incidentally, whitenoise by default creates a staticfiles.json file, not a manifest.json file, and it's served as a static file. So if your STATIC_URL = "/static/" then you can find the manifest at <your-domain>/static/staticfiles.json.
Edit - clarification
The reason the manifest of staticfiles isn't actually called manifest.json is because that'd conflict with the usual name of the manifest.json served as part of a Progressive Web App (spec here), which is kind of similar (in that it can serve as an instruction to the browser of where to find certain files) but not the same.

The real difference between MEDIA_ROOT (media files) and STATIC_ROOT (static files) in python django and how to use them correctly

The real difference between MEDIA_ROOT and STATIC_ROOT in python django and how to use them correctly?
I just was looking for the answer and i'm still confused about it, in the end of the day i got two different answers:
- First is that the MEDIA_ROOT is for storing images and mp3 files maybe and the STATIC_ROOT for the css, js... and so on.
-Second answer is that they were only using MEDIA_ROOT in the past for static files, and it caused some errors so eventually we are only using STATIC_ROOT.
is one of them right if not be direct and simple please so everybody can understand and by how to use them correctly i mean what kind of files to put in them exactly
Understanding the real difference between MEDIA_ROOT and STATIC_ROOT can be confusing sometimes as both of them are related to serving files.
To be clear about their differences, I could point out their uses and types of files they serve.
STATIC_ROOT, STATIC_URL and STATICFILES_DIRS are all used to serve the static files required for the website or application. Whereas, MEDIA_URL and MEDIA_ROOT are used to serve the media files uploaded by a user.
As you can see that the main difference lies between media and static files. So, let's differentiate them.
Static files are files like CSS, JS, JQuery, scss, and other images(PNG, JPG, SVG, etc. )etc. which are used in development, creation and rendering of your website or application. Whereas, media files are those files that are uploaded by the user while using the website.
So, if there is a JavaScript file named main.js which is used to give some functionalities like show popup on button click then it is a STATIC file. Similarly, images like website logo, or some static images displayed in the website that the user can't change by any action are also STATIC files.
Hence, files(as mentioned above) that are used during the development and rendering of the website are known as STATIC files and are served by STATIC_ROOT, STATIC_URL or STATICFILES_DIRS(during deployment) in Django.
Now for the MEDIA files: any file that the user uploads, for example; a video, or image or excel file, etc. during the normal usage of the website or application are called MEDIA files in Django.
MEDIA_ROOT and MEDIA_URL are used to point out the location of MEDIA files stored in your application.
Hope this makes you clear.

STATICFILES_DIRS setting makes my admin widget override disappear

I'm having trouble understanding how static files are handled in Django. I've read through the official Django documentation as well as multiple threads, including this wonderful one here:
Differences between STATICFILES_DIR, STATIC_ROOT and MEDIA_ROOT
Most people define the STATICFILES_DIRS list as a list of paths where django will search for additional static files aside from the app's static folder.
I understand that, but what does this have to do with the formfields I'm overriding in my admin.py?
I have overridden the default ManyToMany form to the FilteredSelectMultiple widget in a few of my admin models like so:
from django.contrib.admin.widgets import FilteredSelectMultiple
formfield_overrides = {
models.ManyToManyField: {'widget': FilteredSelectMultiple("User Names", is_stacked=False)}
}
This works fine and produces the widget override I wanted: Functional Widget Screenshot
However, when I define STATICFILES_DIRS in settings.py to include my root static folder like so:
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static/'),
)
It breaks my override and defaults back to the original ManyToMany field form:
Broken Widget Screenshot
We do not have STATIC_ROOT defined in our settings.py as we don't plan on using the collect static feature. We plan on keeping/referencing our static files at the root static folder. Also in our settings.py we have:
STATIC_URL = '/static/'
I don't understand how these settings for dealing with static files are interfering with the formfield_override above. I would appreciate some insight on this, so that I could find a way to approach this issue.
Thank you!
I figured out the cause of my issue. I missed this portion in the Django documentation that explains STATICFILES_FINDERS: STATICFILES_STORAGE Documentation
It turns out that my production server was finding the static files in my outer root folder first, which were not up to date. This explains why I wasn't seeing my changes. I'm going to reconfigure the way I handle static files to ensure that the outer root static folder that my production server looks always has the latest static files via the collectstatic feature

Static files namespaces in django

I can't get my static files in Django to work with "namespaced" urls - I wonder if I'm missing something here?
my project structure
Basically I have one app called "foo" in my project "static_test". Inside that app I have a "static" folder which contains "test.txt".
I haven't changed anything in settings.py, so it contains all the default settings: staticfiles is included in INSTALLED_APPS, and STATIC_URL is set to '/static/'.
All of this is in full accordance with official Django tutorial: https://docs.djangoproject.com/en/1.9/howto/static-files/
I'm using Django 1.9.2.
When I start the Django development server, this is what I get:
localhost:8000/static/test.txt - 200 OK
localhost:8000/static/foo/test.txt - 404 Page not found
This is despite the official tutorial claiming
In your templates, either hardcode the url like /static/my_app/myexample.jpg or, preferably, use the static template tag to build the URL for the given relative path by using the configured STATICFILES_STORAGE storage (this makes it much easier when you want to switch to a content delivery network (CDN) for serving static files).
Why is the second url (/static/foo/test.txt) not working for me? And why is the first url working? I do not have a project-wide static folder.
Thanks
from the docs
You should use 'django.contrib.staticfiles.finders.AppDirectoriesFinder' in your STATICIFILES_FINDERS variable in your settings.
First one is searching under static.
Second one under foo under static.
Your link should look like this.
href="{% static "test.txt" %}"
And settings.py like this
STATIC_URL = '/static/'

Using relative vs absolute URL for STATIC_URL in Django

I'm attempting to setup appropriate STATIC_URL and STATIC_ROOT values for a new Django project, and I'm running into a problem with using an absolute URL for STATIC_URL.
My project is structured like:
<project root>
static
media
src
<apps>
static
js
css
custom.css
i
settings.py
In my settings.py, I have
STATIC_ROOT = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../static/'))
If I set STATIC_URL = '/static/', then I can access http://localhost:8000/static/css/custom.css perfectly.
However, if I use an absolute URL like STATIC_URL = 'http://localhost:8000/static/', as though I were using a CDN, then http://localhost:8000/static/css/custom.css returns a 404 error.
Shouldn't these settings be effectively identical? The docs state STATIC_URL can be absolute. Why does the later setting fail to load static media?
I just tested the same thing, using http://localhost:8000/static/ doesn't work for me either.
In my settings I keep a development variable, so on localhost the url is '/static/' and when I'm deployed (and I set DEVELOPMENT = False), its a full url.
if DEVELOPMENT == True:
STATIC_URL = '/static/'
else:
STATIC_URL = 'https://www.mywebsite.com/static/'
I assume that you are using the static function from the django.conf.urls.static to serve your static files in the development environment (that means DEBUG=True). Now as you can read in the documentation this function is not working with the absolute urls with DEBUG enabled.
So from the docs:
https://docs.djangoproject.com/en/dev/howto/static-files/#serving-static-files-during-development
"This helper function works only in debug mode and only if the given prefix is local (e.g. /static/) and not a URL (e.g. http://static.example.com/)."
The cause and solution was simple, but discovering it was unintuitive based on how I described the problem. I failed to mention that my absolute STATIC_URL actually had a different domain (http://localmedia:8000/static/ not http://localhost:8000/static/).
I was doing this as part of a hack to simplify media hosting among several external development Windows machines I was using to test various versions of IE.
However, when there's a mismatch between the domain in STATIC_URL and runserver's local domain, Django only serves content from STATIC_ROOT and doesn't attempt to retrieve media from app folders. Not sure why, but that's the way it is.
If I ran manage.py collectstatic, it would effectively fix the 404 error by copying all app folder media into my STATIC_ROOT. Alternatively, I could just use the same domain in my STATIC_URL, and Django would automatically find any uncollected media in the app folders.

Categories