Static URL in JavaScript - django

I have a CSS file which is being used in my template file
<link href="{% static "assets/style/reset.css" %}" rel="stylesheet" type="text/css"/>
I want to access the 'static' in my JavaScript. Is it possible? How can I do it?

Your javascript has to pass through django's template redering. You could do this by rendering your javacript inside of your template like Django Template Variables and Javascript suggests.
Or you could create a view that just renders your javascript dynamically:
(r'^dynamic.js$', dynamic_js)
def dynamic_js(request):
"""
Create a js file dynamically
"""
return render(request, 'dynamic.js',
content_type='application/javascript')
# dynamic.js
# can use template tags now!
Having django serve your static assests is extremely inneffiecient, and is one of the first things to migrate away from if you want a speedy site. If your js file is rarely changing it might be better to create some sort of build process where you can generate your dynamic js with django (so you can use the template variables) and save it to you static folder, so that your webserver can serve the content for you!

Related

Static files being referenced via different path in same Django view

I recently updated one of my views and URLs to take an additional parameter and now that I have done this the page which is rendered displays with no css or javascript because the static path is wrong.
I am obviously not understanding correctly how static is served however I didn't think that changing the URL confs would change the path that Django would look for static. All my static for the whole site is in the one place.
urls.py
url(r'^fill/(.*)/(.*)/$', views.fill_survey, name='unique_getfile'),
url(r'^fill/(.*)', views.fill_survey, name='unique_getfile'),
and here is my view ... first block executes for the first url match and the second block executes for the bottom url
def fill_survey(request, unique_url, new_name="blank"):
"""
get file or redirect to error page
"""
if len(unique_url) < 50:
if unique_url == "new":
firstlast = new_name.split(" ")
c = Client.objects.get(firstname=firstlast[0], lastname=firstlast[1])
survey_url_number = generate_survey(request, c.email)
response = Survey.objects.get(number=survey_url_number['number'])
return render(request, 'survey/survey.html', {'survey': response})
else:
response = Survey.objects.get(number=unique_url)
return render(request, 'survey/survey.html', {'survey': response})
The rendered page then has the following static paths for the first and second url match respectively:
wwww.mysite.com/static/etc...
www.mysite.com/module_name/static/etc...
Paths in my template like:
<link rel="stylesheet" href="../../../static/classic/global/css/bootstrap.min.css">
Why are these different URLs leading to different static paths?
Thanks in advance!
Here's the relevant docs but by default Django only looks for static resources in /static/ folder or its subfolders. You can define a list of static file directories in your settings file if you want though.
https://docs.djangoproject.com/en/2.0/howto/static-files/
EDIT: Response to comment.
Can I see your template? Also, I'd try changing all your urls to end in a /$.
EDIT: Response to posted template.
I use the static tag rather than the absolute. I.E.
<link rel="stylesheet" href="{% static "/css/bootstrap-3.3.7.min.css" %}">
This way if we mess with the location of our templates we don't ned to go back and change all the templates
.
A couple thought about your html:
Since it doesn't start with / it's pointing to the a folder within the current folder.
With a / it points to the path at the root of your current web.
See https://www.w3schools.com/html/html_filepaths.asp
Regarding why I end my addresses in /$. Here's a good answer.
Why django urls end with a slash?
I wish I had a clearer answer for you but try the trailing / in the url and the leading / or {% static %} in your template.

How to use images loaded with webpack in django templates?

I am using Webpack 2 and use url-loader to load all of my images. before using webpack, I used the static template tag like this:
<img src="{% static "img.png" %}" ... />
and now webpack renames all of the images to some hash and ext like this:
img.png becomes img-[somehash].png. (I use this for cache invalidation).
the problem is how to load the new image (with the hash) in django templates ?!
thanks in advance.
How about passing correct path in context data? In Django view you are passing context data to the template. You can use regular expressions to find the name of file with hash. Let say that your images are in the directory which variable called STATIC_ROOT links to (place where all static files are). First, you need to find files:
from yourproject.SETTINGS import STATIC_ROOT
all_files = os.listdir(STATIC_ROOT)
Let say that name of the file you want is picture.png, and it was changed to picture-asd12edaq.png Then, find correct file name using regex or simple in operator:
for file in all_files:
if 'picture' in file and '.png' in file:
context['src'] = file
break
Then in template use simple <img src="{% static {{src}} %}" ... />

Using Django urls in javascript files

I am trying to use url-names in my javascript/jquery files for AJAX requests and I have found several solutions that can solve this problem. The one that I am currently using is the following.
I define a url to serve javascript files:
urls.py
url(r'^js/([\w\.\-]+)/([\w\.\-]+)/$', 'views.get_javascript_file', name='get_javascript_file')
url(r'^getmoredicus/$', 'load_discussions', name="load-discus"),
Then I define the view that renders the javascript files.
views.py:
def get_javascript_file(request, app_name, js_file):
'''
Used to request and serve rendered javascript/jquery files.
'''
return render_to_response("%s/%s.js" % (app_name, js_file),
context_instance=RequestContext(request))
Now in the html files, we can use the get_javascript_file url to get the rendered javascript files.
html files:
<script type="text/javascript" src="{% url get_javascript_file 'myapp' 'jsfile' %}"></script>
Now in any javascript file, I can access the url-names through {% url url-name %}.
Questions:
1) Is there a better/faster way to use url-names in javascript files? I know that there are some apps already created to accomplish this but I want to get everyone's(django experts) opinion on the best way to accomplish this.
2) Can we cache the rendered javascript files after they have been rendered the first time so that in each subsequent request, we don't have to render them again? If yes, then how can we go about doing that.
3) In this method, we are rendering the script files from their apps folders. Is there a way to access the static files located in STATIC_ROOT from the get_javascript_file view? I am just thinking about how this would work in a production environment. Is it a good practice to access static files from their apps folders rather than putting them in STATIC_URL and accessing them from there?
NOTE
I know that there are already some questions on SO that answer some parts of this question, but I just wanted to get to the bottom of this once and for all for future django learners. What is the best way to use url-names in javascript or any script for that matter?
I'm not a fan of running external js through the view rendering. Especially if you're using something like django-compressor to compress and cache your js files.
I prefer to just include the variables in a script tag prior to including the external files.
<script>
my_var = "{{ MY_PROPERTY }}"
</script>
<script type="text/javascript" src="{{ STATIC_URL }}js/external_script.js"></script>
That solution is also not always ideal, but I'm open to other solutions.

Is it possible to use django's custom template tags to insert code in other blocks in the template?

I'm writing a custom template tag that wraps an HTML element with some code to make it editable. This is backed up by some CSS, and JS that takes care of sending the data to the server to save it.
This component requires the inclusion of
<script type="text/javascript" src="../myscript.js"></script>
at the bottom of the page and
<link rel="stylesheet" type="text/css" href="../mystyle.css">
at the top.
I already have two "js" and "css" template blocks in the page template.
My question - is there a way for for the custom template tag to include these scripts once in the relevant page blocks, if my tag is present?
IE I put in:
{ % mytag %} <div>editable element</div> { % endmytag %}
and the "js" and "css" template blocks gets populated with the relevant script\link tags?
(I don't want to preinclude those in every page, as only some of my pages will use this tag)
You might try using Django-Sekizai from within the template your custom tag renders to add CSS and JS files to another block, which is what Sekizai is designed to do. I use it extensively with Django-CMS based projects, but I haven't tried your use case.

How do I use multiple style sheets in Django, where the style sheet is determined by a GET variable, without violating DRY?

I an writing a website that will have multiple skins. Each skin has its own style sheet. I would like the skin used to be determined by a GET variable, so that this URL:
whatever?skin=foo
will cause the page to be rendered containing this HTML in the header:
<link rel="stylesheet" type="text/css" href="/site_media/foo.css"/>
(Normally I want the skin to be determined by a user's preference, but I want this way of doing it as well, so a user can preview what a new skin will look like, as well as for making it easy for me while developing it.)
This is fairly easy to do in Django, for example you could use a template with this line:
<link rel="stylesheet" type="text/css" href="/site_media/{{skin}}.css"/>
And a view like this:
def whateverView(request):
""" called by URL /whatever """
skin = request.GET.get('skin', "default")
c = RequestContext(request, {'skin': skin})
html = whateverTemplate.render(c)
return HttpResponse(html)
But I don't want to have to do it like that, as I would have to add the same code to every single view, which would violate DRY.
So is there some way I can do it, such that it works on all my pages, while only writing the code once?
You can do this using Django's Context Processors: http://docs.djangoproject.com/en/dev/ref/templates/api/?#writing-your-own-context-processors. Or, you could enable django.core.conext_processors.request and access the request object in your template.