Django ManifestStaticFilesStorage and urls in javascript, angular, css - javascript

I am working with Django 1.8 + AngularJS 1.4.5.
Django has an amazing feature to prevent modified files are cached: ManifestStaticFilesStorage.
Once a file is modified the collectstatic command recalculate and add to the filename the hash of the file.Then look for all the appearances of the url with that file and and replace the original filename with the hashed filename.
Eg:
styles.css -> styles.b8a501ed930c.css
And:
<link href="{% static 'css/styles.css' %}" rel="stylesheet">
Is compiled as:
<link href="/static/css/styles.b8a501ed930c.css" rel="stylesheet">
That is very helpful, but only rename the filenames inside the {% static %} tag.
Is there any way to add this feautre to the urls inside css/js files? For example to add a hash name to the partials html templates of angularjs.
$routeProvider.when('/mypage', {
templateUrl: "mypage.html", -> ("mypage.hashdigest.html")
controller: "MyPageController"
});

Related

Django3: dynamically generating js which I can use in HTML page

As we know in Django framework we can generate the HTML page based on some predefined template files.
Inside those templates we can use and some specific django keywords/operators/functions.
Like:
{% block stylesheets %}
<link href="{% static 'js/jquery/jquery-ui.css' %}" rel="stylesheet">
<link href="{% static 'vendor/chosen/chosen.css' %}" rel="stylesheet">
{% endblock stylesheets %}
But most important things which I want to touch in this question are related to tag 'translate'
"{% trans 'List of all available masters' %}"
So I can be sure that the final content of my page will use some predefined language.
And the places where I am using such tags are different: "simple" html content with / and etc tags AND inline javascripts blocks. Like:
<script type="text/javascript">
$('#datepicker_value').on('change', function(){
....
var dialog = BootstrapModalWrapperFactory.createModal({
title: '{% trans 'Extended information about the event' %}',
message: '<pre>'+JSON.stringify(info.event.extendedProps.description, null, 4)+'</pre>',
buttons: [
{
label: '{% trans 'Close' %}',
cssClass: "btn btn-secondary",
action: function (button, buttonData, originalEvent) {
return this.hide();
}
}
]
});
....
</script>
So my main question here is such:
HOW correctly I can move ALL <script>...</script> blocks from html template into the external JS file?
To keep all the functionality of the django framework working! And my 1 variant was - I should use the same technique which I use for generating HTMLs with Django framework abilities. But maybe in a little shorten variant: Right inside the views.py file - CAN I somehow correctly generate on the fly full content of GLOBAL.js file which will contains ALL ... blocks from html template - where they all were previously stored.
And in a such manner - that standard django template engine can convert all {% ..... %} placeholders in a correct real content BEFORE the full content of GLOBAL.js will be generated and given out. And especially the content of translatable placeholders!!! Well, then in the HTML page template I can insert a call to a special command that can display the contents of this script at the moment the page is rendered by the browser on the client side. Something like:
<script type="text/javascript" src="{% url 'GLOBAL.js' %}"></script>
Am i right? If yes - how I can do that step-by-step? Or maybe there is something new and more logical way?
Django version is the latest one!!! 3.*
P.S. Also I've faced with a problem of transferring script block with content like document.addEventListener('DOMContentLoaded', function(){...}); Looks like such event handlers can't be moved out to the separate JS file from HTML page((
There is no reason you couldn't use Django template tags inside Javascript files (or any other filetype for that matter). As an example, here's is a view that returns rendered Javascript:
from django.shortcuts import render
def render_javascript(request):
return render(request, 'myapp/global.js', {})
If you hook this view into your urlpatterns like this:
urlpatterns = [
path("js/global.js", render_javascript, name="globaljs"),
]
You can then use the {% url %} template tag to refer to it from your HTML templates like this:
<script type="text/javascript" src="{% url 'globaljs' %}"></script>
Now when your browser requests js/global.js, the Django view will take the template myapp/global.js, process it with the templating system, and return the rendered template.

How to have relative paths in eleventy?

I am currently working on a 11ty project and really like it. But I have a problem with the links when I deploy the output. I'd like to deploy it to 2 different locations on separate servers. One of the locations is in the root directory, the other one in a sub-folder.
Is it possible to have relative links in the output?
I already tried pathPrefix, but either I don't use it properly or it just doesn't give me the result I am looking for.
.eleventy.js:
module.exports = eleventyConfig => {
...
// Include our static assets
eleventyConfig.addPassthroughCopy("images")
return {
pathPrefix: "/subfolder/",
templateFormats: ["md", "njk"],
markdownTemplateEngine: 'njk',
htmlTemplateEngine: 'njk',
passthroughFileCopy: true,
dir: {
input: 'site',
output: 'dist',
includes: 'includes',
data: 'globals',
}
}
}
When I run eleventy --config=eleventy.config.js --serve, an additional folder gets generated with the name _eleventy_redirect, including an index.html file with:
<!doctype html>
<meta http-equiv="refresh" content="0; url=/subfolder/">
<title>Browsersync pathPrefix Redirect</title>
Go to /subfolder/
When I run eleventy --config=eleventy.config.js (without the --serve), that folder isn't there.
However, either way all the links are absolute (e.g. Home is href="/"), and the site doesn't work on the server.
Is there a way to have either relative links (e.g. Home is href="./" on the root index.html and href="../" on sub pages) or at least include the subfolder in the urls (e.g. Home is href="./subfolder/")?
Not quite what I was looking for, but it helps with some parts of my issue.
The url filter normalizes absolute paths, e.g.
href="{{ "/" | url }}"
See the eleventy github for more details.
I came across the same problem and found a solution: use Liquid Template variables (which already come in Eleventy) to insert the relative part of the path.
Suppose you have:
The index.html page at the root of the directory.
The contact.html page, whose index ends up being created inside the /contact directory.
The _head.html file that imports some css's and is included in both pages.
You could do it as follows:
_head.html :
<link rel="stylesheet" href="{{ relative_prefix }}/scss/styles.min.css">
<link rel="shorstcut icon" href="{{ relative_prefix }}/favicon.ico">
index.html :
{% assign relative_prefix = '.' %}
{% include _head.html %}
<body>
...
contact.html (that turns into /contact/index.html) :
{% assign relative_prefix = '..' %}
{% include _head.html %}
<body>
...
This way, you can choose to always use relative paths, and never use absolute paths. Consequently, you can simply copy the files generated by Eleventy to several different directories and it will work for all of them. The cool thing is that the site also works on your local machine without a running server, that is, you can open the site in the browser as follows: file:///C:/myProjectDir/_site/index.html

Assetic and generating new filename every change

Hi i am using assetic in symfony 3. But i have problem my assets are defined like this:
{% stylesheets filter='cssrewrite' filter='?uglifycss'
'assets/font-awesome-4.6.3/css/font-awesome.min.css'
'assets/bootstrap-3.3.7/css/bootstrap.min.css'
...
%}
In console run php bin/console assetic:watch
After change in css or js it will generate new file but with same name for example ce9c2ef.css.
But it is problem because after deploy, css file has changes content but no filename so all people see old css...
Q: How i can change generated file name every change in css?
There is options 'output='path/filename.js' in {% stylesheets %} but there i can't add <?php echo $var; ?> or {{ var }}...
UPDATE:
assetic config:
assetic:
debug: '%kernel.debug%'
use_controller: '%kernel.debug%'
filters:
cssrewrite: ~
uglifyjs2:
bin: "%kernel.root_dir%/Resources/node_modules/uglify-js/bin/uglifyjs"
uglifycss:
bin: "%kernel.root_dir%/Resources/node_modules/uglifycss/uglifycss"
templating config:
templating:
engines: ['twig']
EDIT:
So i found solution PARTIAL solution:
To config add:
assetic:
workers:
cache_busting: ~
and after that, your file will looks like ce9c2ef-d1e35a0_filename.css in develop and ce9c2ef-d1e35a0.css in prod...
but in deploy you must clear cache first so you have 2 hashes first ce9c2ef still the same (I do not understand the point of existence) and second d1e35a0 is changing so it finally resolving problem with browser cache....
But if you make changes in css, assetic:watch compile it, but page loads old files...!
Worst bundle ever i mean that changing filename is basic thing and on the internet is so many ways how resolve it and i was tryed one after another 1 day until i finally succeed...
When you're using assetic, one way to solve your issue is by giving your assets a version in your framework:templating section of app/config.yml:
assets:
version: "%application_version%"
Then you can specify your version in your parameters.yml/parameters.yml.dist file:
parameters:
application_version: 1.0.1
Then you can load your stylesheets or javascript like so:
{% stylesheets output='css/sites.css' filter='cssrewrite'
'assets/font-awesome-4.6.3/css/font-awesome.min.css'
'assets/bootstrap-3.3.7/css/bootstrap.min.css'
...
%}
<link href="{{ asset_url }}" type="text/css" rel="stylesheet" media="all" />
{% endstylesheets %}
Now when you dump your assets, it will automatically append ?1.0.1 (or whatever version you are on" to the end of them. For example, in production you would see the following:
<link href="/css/site.css?1.0.1" type="text/css" rel="stylesheet" media="all" />
Note that there are different ways of doing naming strategies, and this can get tricky if you forget to update your assets version every time you make changes to your assets, but there are ways to improve upon that strategy. This should get you up and running though.
If you notice I didn't manually specify the uglify* filters - you can have these automatically applied by putting this in your app/config_prod.yml:
assetic:
filters:
uglifycss:
apply_to: "\.css$"
uglifyjs2:
apply_to: "\.js$"

loading CSS and JS files on specific views in Laravel 5.2

I have CSS and JS files that must only load on certain very specific views in Laravel 5.2.
My boss decided to drop RequireJS which we used to load JS files on our blade templates. Now, we are trying to load dependencies on a native manner.
This is my code:
#extends('layouts.app')
<link href="{{ URL::asset('assets/css/slick.grid.css') }}" rel="stylesheet">
<link href="{{ URL::asset('assets/css/examples.css') }}" rel="stylesheet">
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
loadscript('assets/js/jquery.event.drag-2.3.0.js');
loadscript('assets/js/slick.rowselectionmodel.js');
loadscript('assets/js/slick.core.js');
loadscript('assets/js/slick.grid.js');
});
</script>
#section('page')
//the rest of page
And my "loadscript" function does this:
function loadscript(url, callback)
{
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
head.appendChild(script);
};
This does work, but it feels quite slow, I believe there must be a much better way to have specific css and js file load with laravel on whichever view we want.
It's really important to have the css and js files load only on certain views.
Laravel 5 - Add a stylesheet only if on a certain page/controller (page specific asset)
#extends('layouts.master')
#section('styles')
<link href="{{asset('assets/css/custom-style.css')}}" />
#stop
If you don't like the #section() idea and just want the dynamic scripts in one place, check out my detailed answer here:
Laravel 5 - Add a stylesheet only if on a certain page/controller (page specific asset)
In summary, using named routes:
<!-- In layout template -->
#if (in_array(Route::currentRouteName(), ['profile', 'register']))
<script src="example.js"></script>
#endif

Execute Javascript and css in Django template

I am exporting HTML to PDF via Weasyprint in my Django app. I have noticed that if I send the template html to front end and return that html to backend to export it to pdf, it prints perfectly. But if I directly send template html to Weasyprint, it messes up everything! No css, no javascript.
This is how I'm using the template to generate html:
template = loader.get_template('Reporting/reportTemplate.html')
context = {
"reportObj" : result[0]
}
htmlContent = (template.render(context, request))
response['message'] = htmlContent
return JsonResponse(response)
In my JS controller I assign the htmlContent to my div:
$('#htmlContent').html(response.message);
Then I return the generated html back to my Django function to print pdf
HTML(string=htmlContent).write_pdf(target=response, stylesheets=[CSS(string=getCSS())])
This way it maintains the design and everything.
But when I send htmlContent directly to Weayprint without sending it to front end, the design and coloring is gone!
In my template, I even have included CSS and Javascript files like this:
{% load static %}
{% block content %}
<link href="{% static "css/ion.rangeSlider.css" %}" rel="stylesheet">
<link href="{% static "css/ion.rangeSlider.skinHTML5.css" %}" rel="stylesheet">
<script type='text/javascript' src='{% static "scripts/ion.rangeSlider.js" %}'></script>
<script type='text/javascript'>
$(document).ready(function(){
var creditScore = $("#creditScore").html();
$("#rangeCS").ionRangeSlider({
type: "double",
min: 0,
max: 1000,
step: 100,
from: 0,
to: creditScore,
from_fixed: true,
to_fixed: true,
grid: true,
grid_snap: true
});
});
</script>
{% endblock %}
How can I execute Javascript and CSS in Django template and export to PDF without having to send it to front end?
Are you meaning you've JS in the template that you render as source for Weasyprint ? Because JS used that way runs only on a client side (like browsers) and Weasyprint won't run it, it cannot. You must provided the final document (HTML) to Weasyprint.
If you've CSS issues in your PDF, so maybe you're using unsupported CSS features for Weasyprint.
Like mille_a said, you can't execute javascript code into a pdf.
So to resolve your problem you need to do it into your view :
# do some python stuff to get somes datas
datas = ...
# assign it into your html
htmlContent = my_html_template.render(datas)
# call the pdf generation
HTML(string=htmlContent).write_pdf(target=response)
You can see this example for more details : http://www.supinfo.com/articles/single/379-generate-pdf-files-out-of-html-templates-with-django
Hope it helps.

Categories

Resources