Trouble setting-up directories to compile from in Django-Assets / Webassets - python

This is my current assets.py file:
from django_assets import Bundle, register
sass = Bundle(
'build/main.sass',
filters='sass',
output='css/main.css'
)
register('sass', sass)
Now I run into an issue with it saying Another bundle is already registered as "sass", but not seeing how to unregister it.
At any rate, I change register('sass', sass) to register('sass_all', sass) to get past the error. When I go to compile it is looking in my scripts directory where I keep manage.py. In settings.py I add:
ASSETS_ROOT = [
'static',
]
Which just has look in scripts/static which doesn't exist.
Tried:
# This is already in settings.py
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
# Added new line
ASSETS_ROOT = [
STATICFILES_DIRS,
]
It generates a couple errors: KeyError: 'directory', OSError: The environment has no "directory" configured, and AttributeError: 'list' object has no attribute 'startswith'. Really it is just one error that directory isn't defined, I think.
Read through environment documentation which is vague given my skill level. In assets.py adding Environment to import just says Could not import in Environment. Adding Environment.directory('static') results in Environment is not defined. Just directory('static') also results in directory is not defined. env = Environment() same thing. Tried adding directory='/static' to sass = Bundle(...) which just says TypeError: got unexpected keyword argument 'directory'.
Anyway, spent a few hours on it and stuck again. Documentation seems to indicate directory settings should go in assets.py and not settings.py, whereas ASSETS_ROOT should be going in settings.py.
Thanks again in advance!
~/portal-client
project_dir
apps
account
templates
account
login.html
forms.py
urls.py
views.py
home
templates
home
home.html
urls.py
views.py
results
assets.py
settings.py
urls.py
scripts
manage.py
static
build
main.js
main.sass
css
app.css
main.css
js
app.js
main.js
media
templates
base.html
footer.html
title.html
Continuation from this question: Trouble adding Django-Assets / Webassets directory to look for assets.py files

A quick point to note:
# This is already in settings.py
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
# After this line STATICFILES_DIRS is `[ 'BASE_DIR/static' ]`
# Added new line
ASSETS_ROOT = [
STATICFILES_DIRS,
]
# After this line, ASSETS_ROOT is `[ [ 'BASE_DIR/static' ] ]`
# i.e., an array of arrays
# I think you actually wanted:
ASSETS_ROOT = STATICFILES_DIRS[0]
# - or more explicitly -
ASSETS_ROOT = os.path.normpath(os.path.join(BASE_DIR, 'static'))
That said many of these issues look like they are being caused by a fairly non-standard django structure (i.e., that your manage.py is in the scripts directory rather than in BASE_DIR).

Related

Django: Static Image won't load

I have been following the official documentation to the letter, trying some of the advice for related questions on here, and just searching the web in general and I am still having no luck getting one little image to load.
I have an image called 'logo.png' and my project hierarchy looks like this:
project/
mysite/
app/
__init__.py
admin.py
models.py
urls.py
view.py
mysite/
__init__.py
settings.py
urls.py
views.py
wsgi.py
static/
logo.png
templates/
index.html
calling_image.html
Inside settings.py I have STATIC_URL = '/static/'
Inside calling_image.html I have <img src="/static/logo.png">
My template calling_image.html is called by project/mysite/app/views.py which is of course then called on by project/mysite/app/urls.py and I even tried including the following two lines (as I saw suggested a few times) at the end of my urls.py:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()
Nothing works, so what have I done wrong?
Edit: Sorry I made a type, I have STATIC_URL = '/static/' with the closing slash in my settings.py and for clarification, I am running this on my dev build with python manage.py runserver
Solved: So I ended up solving this myself. I created a directory resources within project/mysite/ and placed logo.png in there. I then set STATICFILES_DIRS = (os.path.join(BASE_DIR, "resources"),) and ran collecstatic and everything worked! Didn't need to use urlpatterns += staticfiles_urlpatterns() and whatnot.
It looks like you probably need the variable STATICFILES_DIRS defined in your settings.py and that should include the location of that static directory holding logo.png.
Django only looks for static files inside a static directory inside each app by default. If you have a static file outside of any app, it won't be picked up by collectstatic automatically.
See https://docs.djangoproject.com/en/1.8/ref/settings/#std:setting-STATICFILES_DIRS
Confusion Surrounding Staticfiles
There's always a lot of confusion around Django and Static files. I believe this confusion comes from the fact that it doesn't make any sense for Django to handle static files in production, but it seems natural to use it when learning to use Django and thus when initially developing.
The reason it doesn't make any sense for Django to serve static files is that Django is a framework for rendering dynamic responses. "Static" files are not dynamic: they don't change. Thus, it's a huge waste of resources to spin up a Python application, which calls all of the Django machinery, just to find and return a file that has no dynamic content.
Staticfiles: the job of the webserver
There is something that is really good at serving static files: webservers themselves (such as a Apache, nginx, etc.). That's what they were designed to do. The webserver can run a Python/Django application or it can just locate a file and send it back, so you typically configure a webserver by telling it something like the following (in pseudo-server-speak):
When someone accesses the path /static/ let them access the files in
the following directory: /var/www/static/.
When someone accesses the
path /, spin up this Python application that lives over here:
/var/www/django-app.
Django Static Files Tools
As a result, Django comes with some helper tools that manage static files, so that your actual server can serve them.
These tools are the following(defined in settings.py):
STATIC_URL: the URL path where your server will be serving your
static files. This is just so that when you use the static templatetag, that Django knows how to urlreverse it. In other words, it's merely a convenient way of turning {% static "..." %} into /static/....
STATIC_ROOT: the place on your server (or in the
cloud somewhere), to which Django will copy your static files, so
that your server can serve them. This copying happens when you run
collectstatic.
STATICFILES_DIRS: any extra directories Django
should look for static files whenever you run collectstatic. By
default Django only looks in each app's directory for a static
directory (just like with templates).
Static Files In Development
Okay, but that's not so helpful in development where you are probably using Django's runserver command. You don't have a server running that will server static files.
Thus, you can ask Django to please also server static files for you in just this one case, because you are developing your application and don't want to run a separate server.
There is a view that automatically should pick up and serve static files when DEBUG=True. Alternately, this is also why someone might use the following:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()
Make sure that django.contrib.staticfiles is included in your INSTALLED_APPS.
In your settings file, define STATIC_URL, for example:
STATIC_URL = 'static/'
Hopes you stored images in folder projectname/static/appname/images/image.png
Finally in your html simply add the following
<img src="appname/images/image.png" alt="My image"/>
please refer django dcumentation
I tried everything, nothing worked. In the end it turn out that image was corrupt because I opened it as bytes in Visual Code editor.
Uploaded new image and everything worked.
If I recall, you need to specify STATIC_ROOT = 'static' in settings.py and you need to have a URL to direct /static to your static files. like so.
urlpatterns += patterns('',
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.STATIC_ROOT, 'show_indexes': True
}),
)
This could be a bit outdated but still works for me.
Also, are you trying to get this to work on your dev site with python manage.py runserver or on a production site?
Update
Here is an example for you main urls.py file.
from django.conf.urls import patterns, include, url
urlpatterns = (
url(r'^admin/', include(admin.site.urls)),
# more urls...
)
#The following enable structural 'static' files while in development mode.
if settings.DEBUG:
urlpatterns += patterns('',
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.STATIC_ROOT, 'show_indexes': True
}),
)
patterns is imported near the top of your urls.py file.
This is where STATIC_ROOT comes in to play.
You may also need to run python manage.py collectstatic in order for your static files to be collected from your various apps and copied into the folder that is STATIC_ROOT.
See this answer for a much more in depth explanation :)

Get the path of "static" folder in django automatically

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.

How to override template in django-allauth?

Answers in other questions leave impression that this is in fact very easy:
django-allauth configuration doubts
overriding default templates of django-allauth
However, I can't get it to work at all.
From example app settings I can see that django-allauth supposedly expects it's templates to be in account, openid and socialaccount directories. But when I put template at TEMPLATE_DIR/account/signup.html it doesn't get loaded, signup view displays template bundled with django-allauth. What do I miss?
I eventually resorted to loading my app before django-allauth. In settings.py:
INSTALLED_APPS = (
...
'myapp',
'allauth',
'allauth.account'
)
This solution goes against what's presented in example app, but I was not able to solve it in other way.
To this day--- we're now on Django-1.10.5--- the django-allauth docs remain most unhelpful on this score. It does seem to be that Django looks in the templates directory of the first app listed, the setting of DIRS in TEMPLATES in settings.py notwithstanding. I'm providing an answer only to help you implement Adam Starrh's answer, to help with the reverse urls (I got errors until I took care of those).
In your urls.py file put:
from allauth.account.views import SignupView, LoginView, PasswordResetView
class MySignupView(SignupView):
template_name = 'signup.html'
class MyLoginView(LoginView):
template_name = 'login.html'
class MyPasswordResetView(PasswordResetView):
template_name = 'password_reset.html'
urlpatterns = [
url(r'^accounts/login', MyLoginView.as_view(), name='account_login'),
url(r'^accounts/signup', MySignupView.as_view(), name='account_signup'),
url(r'^accounts/password_reset', MyPasswordResetView.as_view(), name='account_reset_password'),
]
Presently the views.py file is here, so you can extend the above to other templates.
I must add that you still need in TEMPLATES, something like:
'DIRS': [
os.path.join(PROJECT_ROOT, 'templates', 'bootstrap', 'allauth', 'account'),
],
And in this example that would be if your templates are in /templates/bootstrap/allauth/account, which they are in my case. And:
PROJECT_ROOT = os.path.normpath(os.path.dirname(os.path.abspath(__file__)))
EDIT... THE PROPER WAY:
OK, the above works, to a point, and it's good that it directly sets the template to what you want. But as soon as you include social apps you'll start to get reverse url errors such as for dropbox_login, for which you have not provided a named view.
After reading Burhan Khalid's comment on this other stackoverflow thread that the questioner found, I eventually found that the following works:
'DIRS': [
os.path.join(PROJECT_ROOT, 'templates', 'example'),
]
And this yields /home/mike/example/example/templates/example on the development server in my case, as I am running the example app from git clone git://github.com/pennersr/django-allauth.git.
Into that dir of DIRS I copied the entire subdirectories account and socialaccount from the provided sample bootstrap templates. This is utterly contrary to the directory structure of example as it comes from github and to notes in the settings.py file of example.
And you leave urls.py just as in the example app, with simply:
url(r'^accounts/', include('allauth.urls')),
Adding a template directory for allauth in template dirs will do the trick. In Django 1.8 his can be done by editing template dir settingsTEMPLATES as follows.
TEMPLATES = [
...
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
os.path.join(BASE_DIR, 'templates', 'allauth'),
],
]
I think below code will work on other versions of django
TEMPLATE_DIRS = [
os.path.join(BASE_DIR, 'templates'),
os.path.join(BASE_DIR, 'templates', 'allauth'),
]
In your views:
from allauth.account.views import SignupView, LoginView
class MySignupView(SignupView):
template_name = 'my_signup.html'
class MyLoginView(LoginView):
template_name = 'my_login.html'
For me only one solution works:
first make TEMPLATE_LOADERS to load filesystem.Loader
TEMPLATE_LOADERS = [
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
# 'django.template.loaders.eggs.Loader',
]
second - make TEMPLATE_DIRS with path where you copied templates from allauth. Make sure you copied full folder hierarchy from templates folder of allauth app.
TEMPLATE_DIRS = [
os.path.join(BASE_DIR, 'cms', 'templates', 'allauth'),
]
in this example a made path to my app, named cms because this is the main app of my project
after you could start to edit base.html template
I found a better way to do this but forgot. All Auth allows you to do this very easy but and low on documentation. Here is my next easiest solution, until I rediscover the vaster way. #lol
The code creates a custom login page but the pattern is simple and easy to replicate. You can put all this code in urls.py, or not:
from allauth.account.views import LoginView
class Lvx(LoginView):
# Login View eXtended
# beware ordering and collisions on paths
template_name = "components/login.html"
# don't forget to create the login page, see All Auth docs
# for use. /components is in your app templates path
login = Lvx.as_view()
urlpatterns = [
url(r'^accounts/login/$', login), # usually up top
...
]
There is also a setting you can use to point to a custom page, will edit this at some point. Feedback welcome.
As per the documentation provided here, it is possible to override the templates by replicating the directory structure inside the template base location of your project. For instance, by just creating the account/logout.html , I was able to override the logout.html file provided by allauth. The settings.py in my case is stated here
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
}
]
In django v2.0. I use this method and its works. By following the django book, [https://djangobook.com/mdj2-django-templates/] .
The important way is to use [os.path.join(BASE_DIR, 'name_of_your_file/templates/allauth')] instead of using 'DIRS': [os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'templates', 'allauth')],
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'name_of_your_file/templates/allauth')],
'APP_DIRS': True,
This is my first time post at stackoverflow yah,i find this solution long time and finally its work so i share it, hope can help someone.
It's quite easy once you know Django's template look up order and you configure the TEMPLATE =[] properly as per your need. There's no need to play with views or Python code if it's just about overriding allauth's templates.
Let's understand the Django's template look up order at first, just a little. Django's template lookup order is as follows, all of these are configured inside TEMPLATE =[]in project's settings.py.
I. 'Loader': Give you the option to use Template Loaders which are responsible for locating templates, loading them, and returning Template objects. General implementations don't use it much. If you haven't configured a template loader then one of the following two option would decide which template is used by your view.
II. 'DIRS': Here you get the option to explicitly tell Django where to search for templates, in order, up to down.
III. 'APP_DIRS': If this field is set to true then Django looks for your template in your apps' dir. To correctly use this option you need to organize your templates as follows:
root_dir
app1_dir
templates
your_template.html
app2_dir
templates
your_template.html
You must name your templates dir as "templates" and you must put your templates in that dir only for this to work
Third option is little weird though, if a template in your app's view isn't found in corresponding app's template dir Django will go through template dir of other apps to find it.
It works well if templates are organized properly and naming convention of templates is standardized, so that when a template isn't found in local app's dir, that template shouldn't be erroneously found in other app's dir. Well, you may have some scenarios where you would want it to work that way.
Now, to the point answer to your question:
Allauth by default uses the templates from:
Python installed directory or virtual env --> *Lib --> site-packages --> allauth --> templates*
You would usually want to override all the allauth's templates as they are very basic and you would want to beautify/modify them all, following are the steps which would enable you to override them all, if you don't wish to override all of them do as follows, but just don't change the HTML for that template, simple!
Suppose your project structure is as follows:
projectdir
app1_dir
app2_dir
projectname_dir
Copy the templates dir from Python installed directory or virtual env --> Lib --> site-packages --> allauth --> templates to a dir of your choice, suppose you chose to keep it in app1_dir (you may chose any dir, makes no difference, but you should choose an appropriate one as per your requirements), then create a dir in app1_dir named 'allauth' (you could name it anything you like), then paste the copied allauth's templates dir in this dir, so now your project structure would look as follows:
projectdir
app1_dir
allauth
templates
account
openid
socialaccount
base.html
app2_dir
projectname_dir
Change your TEMPLATES = [] in project settings as follows:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'allauth', 'templates'),
],
'APP_DIRS': True,
},
]
Here BASE_DIR is projectdir (root dir)
Basically you may keep the copied template dir from allauth dir in any project's dir of your choice, but you must enusre that you provided the correct path here:
'DIRS': [os.path.join(BASE_DIR, 'allauth', 'templates')
If it doesn't work then, set 'APP_DIRS': False, then you would see a debug message from Django and it wouldn't use app dir (allauth dir in site-packages). And then looking at that error you may figure out what's wrong with your config.

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.

Django can't find template

I know many people have asked, this question, but despite hardcoding the path to my template directory I can't seem to get Django to find my template.
Here is settings.py
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
#django.template.loaders.eggs.Loader',
)
TEMPLATE_DIRS = (
"/Users/full/path/to/marketing_site/templates",
)
This is the views.py file:
def static (request, feature_page):
# this will get the appropriate feature page template.
template = loader.get_template('features/pricing.html')
c = RequestContext(request,{
})
return HttpResponse(template.render(c))
Inside the main folder is the templates folder and the app folder. I use to put the apps in the same folder as settings.py but it appears django 1.4 has changed the default file structure.
My error is:
TemplateDoesNotExist at /features/pricing
Django tried loading these templates, in this order:
Using loader django.template.loaders.filesystem.Loader:
Using loader django.template.loaders.app_directories.Loader:
/Library/Python/2.7/site-packages/django/contrib/auth/templates/feature_pricing.html (File does not exist)
Update:
My logs for the webpage list the TEMPLATE_DIRS as ().
If I put a print statement on the settings.py page for the TEMPLATE_DIRS I get a printout of the TEMPLATE_DIRS appropriately... so somehow the TEMPLATE_DIRS isn't being used (from what it looks like)
I had added in an extra TEMPLATE_DIR in the settings.py
:(
it's better to set up relative paths for your path variables. You can set it up like so:
import os
PATH_PROJECT = os.path.realpath(os.path.dirname(__file__))
...
...
TEMPLATE_DIRS = (
PATH_PROJECT + '/templates/'
)
Also assuming you are using windows you may want to try:
TEMPLATE_DIRS = (
"C:/Users/full/path/to/marketing_site/templates",
)
I'm betting /Users/full/path/to/marketing_site/templates does not contain a features directory, or /Users/full/path/to/marketing_site/templates/features does not contain a pricing.html file.
Based on your comment, it looks like you're calling loader.get_template('feature_pricing.‌​html'), instead of using 'feature/pricing.html'.
EDIT: I didn't notice this before:
Inside the main folder is the templates folder and the app folder. I use to put the apps in the same folder as settings.py but it appears django 1.4 has changed the default file structure.
That could be causing the issue. Change the directory structure to match the 1.4 Django conventions. You might just recreate the project, copy the relevant settings over into the newly create settings.py, and copy all the files.
Try adding project paths to django.wsgi
import os
import sys
paths = ('path/to/project/',
'path/to/more /included/directories/',
)
for path in paths:
if path not in sys.path:
sys.path.append(path)
os.environ['DJANGO_SETTINGS_MODULE'] = 'project.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

Categories

Resources