How to load a custom JS file in Django admin home? - javascript

I have a heavily customized Django admin where it's very simple to load a custom JS file for each of my ModelAdmins:
class MyModelAdmin(admin.ModelAdmin):
class Media:
js = ('js/admin/mymodel.js',)
But how do I do this for the admin "homepage," where all my admin models are listed?
Update #1: amending my question, since the solutions below aren't that useful if I cannot efficiently include Django's jQuery. So, how do I include Django's jQuery in the JS file? If I wrap my code with (as I do in my other ModelAdmin JS files):
(function ($) {
// my code here...
})(django.jQuery);
I get the following error:
ReferenceError: django is not defined.
Thanks.
Update #2: I was able to include Django's jQuery successfully by following this answer: https://stackoverflow.com/a/10584539/585783

You can override templates/admin/index.html and add the JavaScript in the block extrahead:
{% extends "admin/index.html" %}
{% block extrahead %}
{{ block.super }}
# add a <script> tag here with your JavaScript
{% endblock %}

Related

About using jinja templating in JS file

I have been using a template in which there's images of previous and next button is in JavaScript file. The Framework I'm using is Django, is there any solution to use jinja templating/rendering for these images in JS file.
JS code:
$(".active-banner-slider").owlCarousel({
items:1,
autoplay:false,
autoplayTimeout: 5000,
loop:true,
nav:true,
navText:["<img src={% static 'img/banner/prev.png' >","<img src={% static 'img/banner/next.png' %}>"],
dots:false
});
I used same static method with html files and it worked, I don't know if this method does even work with JS file or not? if it does what would be the correct way?
Yes, you can generate a JS component of a web page using the Django template processor, or Jinja if you prefer. You do, however, need to make sure that the JS is generated in the correct context (surrounded by appropriate tags, in the right place in your rendered output). You also have to be careful to code your JS using { { and } } (significant spaces!) never {{.
If you use "view page source" and your browser's debugging tools, you will probably spot what you are doing wrong.
My site base template has a block onready_js like this:
<script type="text/javascript"> $(document).ready( function() {
{% block onready_js %}{% endblock onready_js %}
});
</script>
into which you can inject bits of JS to be executed when the page becomes ready, like this (ignore the irrelevant details, apart from the use of {{...}} and {% if ... %} etc. Absent any block definition, the base template generates a null $(document).ready( function() { });
{% block onready_js %}
{% if form or POST_name %}
// activate the button column to POST to this target with this name
var buttons = $('button.MyFilterSelectButton');
buttons.attr('type','submit').attr('name','{{POST_name}}')
buttons.click( function(event){
$('#id_{{POST_name}}').val( $(this).attr('value') );
/* stuff deleted */
$('.MyFilterSelectCol').show();
{% else %}
// hide the button column which doesn't do anything useful
$('.MyFilterSelectCol').hide();
{% endif %}
{% endblock onready_js %}

Flask - Component templates structure?

I've been experimenting with a Flask template structure to resemble a component workflow. This is inspired by Vue.
Some key ideas :
Each page is treated as a component
A component is just a folder containing all necessary files inside it (except ones that are common)
Each component is encourageg to have several HTML files to avoid large files, we will be using Jinja's include to "bundle" them
togheter
Avoid javascript, or at least, loading unnecessary javascript, each page will include only what's necessary
Here's an example :
The route for PageExample would be the following :
app.route('/example'):
return render_template('PageExample/html.html')
And PageExample/html.html :
{% extends 'base.html' %}
{% block content %}
<div class="tab" id="tab1">
{% include 'PageExample/tab1.html' %}
</div>
<div class="tab" id="tab2">
{% include 'PageExample/tab2.html' %}
</div>
{% endblock %}
PageExample/tab1.html (tab2 follows the same logic)
<!-- block header is in base.html -->
{% block header %}
{{ super() }}
<script src="{{url_for('components', 'PageExample/tab1.js')}}">
{% endblock %}
<div class="tab-content">
Some content here that uses the tab1.js javascript
</div>
So, what's the question ?
I have limited experience with Flask, so I'm not sure if this idea is sound, it seems hacky but it makes developing pages easier, especially with multiple people (the little javascript a page might need can be done in any way). Also increased loading speed by a ton.
Dos this work? Is this structure reccomended? Are there any flaws to it? What sort of problems could I run into? Any recommendation to do it better? Is this already done nowadays in Flask? I couldn't find any examples of a Flask app done this way (specially the Jinja stuff using lots of includes)
I'm currently not at my main computer, so I'll update this later if need be, but if your included html files referenced any data that is stored in the backend then you'd also need to make sure you reference the exact location there as well.
For example:
If you need the first name property from a User class it would be
{{ User.firstName }}
Not only that, but the tab template will also need to be supplied this User.firstName variable, which isn't done implicitly.
You will need to create what is called a Blueprint then a View and tell the view to make the User.firstName variable available to PageExample/tab1.html
tabs.py
import User
from flask import Blueprint, render_template
import """other flask dependencies needed"""
bp = Blueprint('index', __name__, url_prefix='/')
def tabData():
"""data to process"""
render_template("PageExample/tab1.html", User=User)
In that same tabs.py file, you can also write a view for tab2.html as well as html.html. Should be noted that I'm assuming that the contents of PageExample are for the index of the website and that they will all be rendered on that same page.
Also, It seems like your tabs will be in the content/body of the html but it will also render the blocks of base.html and add the defined scripts inline with the body of html.html. Instead, it should be referenced in the html.html file itself
html.html
{% extends 'base.html' %}
{% block header %}
{{ super() }}
<script src="{{url_for('components', 'PageExample/tab1.js')}}">
{% endblock %}
{% block content %}
<div class="tab" id="tab1">
{% include 'PageExample/tab1.html' %}
</div>
<div class="tab" id="tab2">
{% include 'PageExample/tab2.html' %}
</div>
{% endblock %}
with tab1.html being
<div class="tab-content">
Some content here that uses the tab1.js javascript
</div>
Obviously, this is just the surface of what you will need to know about flask. Think the bottom line is that it can work. Although I would suggest that your put all resources such as JS and CSS in a separate folder and reference those resources from those locations.
For more information on Flask and how you can utilise it, check out the Flask Tutorial here:
http://flask.pocoo.org/docs/1.0/tutorial/

Shopify - using if statements within js.liquid and scss.liquid files

I am trying to merge JS files together in 1 file, however I need to set conditions using the if statements within the js file.
I have created file.js.liquid but it does not seem to working; I added a test for example:
{% if template contains 'index' %}
console.log('homepage loaded');
{% endif %}
Example of what i am trying to do, of course have plenty i need to do.
{% if settings.the_simpsons_enabled and settings.simpsons_video_enable %}
// video popup
$(".video-popup").videoPopup();
{% endif %}
The conditional statements are also not working within scss.liquid files either:
{% if template contains 'index' or template contains 'collection' or template contains 'product' %}
#import url("{{ 'owl.carousel.scss' | asset_url }}");
{% endif %}
Any ideas why if would not be working or if its even possible? I assume it is being a liquid file.
The Liquid extension on such files like CSS or JS allows use of Liquid variables but not statements.
So {{ write_my_liquid_var_here }} will work. {% if liquid_statement %}do something{% endif %} won't.
Regarding Shopify and SASS
The following won't work as you can't use #import in Shopify's SASS files.
#import url("{{ 'owl.carousel.scss' | asset_url }}"); //This will not work
Regarding using conditional liquid statements in .js.liquid files
I don't know everything about this subject, but I do know the following two things.
1) Check out this thread and you'll see that this type of statement won't work because js files are parsed independent of normal liquid templates, so it would have no idea which template you're viewing.
{% if template contains 'index' %} //This will not work
A better place to put the above logic would be at the bottom of your theme.liquid file above the </body> tag. However this won't help you with what seems to be your goal of reducing HTTP requests by using one JavaScript fie.
2) However, you can access values in your settings_data.json file
{% if settings.the_simpsons_enabled and settings.simpsons_video_enable %} //This will work
I hope this helps

How to include properly Javascript using a Javascript Twig Template

I know how to access my assets, but i wanted to create a template working with Javascript and Twig, which would allow me to use Twig variables in my script.
For example, I have a template called 'details.html.twig', which extends a 'layout.html.twig':
{% extends '#AcmeBundle/Front/layout.html.twig %}
{# SOME CODE AND CONTENT #}
{% block page_script %}
{{ parent() }}
<script>
{# Part of my script #}
</script>
{% endblock page_script %}
All of this worked perfectly, but to be able to reuse some js code (using twig variables), I cut some part of my script and put I in an external template, called 'viewer.html.twig'. To be able to use it in my 'details.html.twig', I used:
{% include '#AcmeBundle/Front/Model/viewer.html.twig' %}
I put this line right after the {{ parent() }} one and before the <script> tag.
However, my script which used to work when directly written in 'details' template seems to be quite ignored right now.
If any of you could have a clue of what makes my template being included but skipped, or a way to include the template easier or properly, I'm open to all kind of observations.
G'day,
Jérémy
If you code a file containing only javascript you should name your file:
{% include '#AcmeBundle/Front/Model/viewer.js.twig' %}
Then Twig (as of 1.17) automatically defines its escaping strategy based on the extension.
See the twig docs and an example of js twig file in symfony.

Symfony2 - Sonata Admin - add javascript before field

In admin class:
protected function configureFormFields(FormMapper $formMapper) {
$formMapper
->add('name', 'text')
->add('description', 'text')
;
}
I don't know how I can before "name" add javascript, can you help me?
Working for me:
In admin class src\PP\TestBundle\TestAdmin.php
public function configure() {
$this->setTemplate('edit', 'PPTestBundle:CRUD:edit_javascript.html.twig');
}
In src\PP\TestBundle\Resources\views\edit_javascript.html.twig
{% extends 'SonataAdminBundle:CRUD:base_edit.html.twig' %}
{% block javascripts %}
{{ parent() }}
<script src="{{ asset('bundles/pptest/admin/js/myscripts.js') }}" type="text/javascript"></script>
{% endblock %}
When you do all this stuff and you have upload myscripts.js you should send this in command line:
app/console assets:install web
(possible that I forgot something)
Sorry for my bad English :<>
EDITED
1º You need to create a custom TWIG template for it (where you could place your javascript code just before the widget code).
2º Then you write inside ap/config/config.yml where your custom template is to allow Symfony and SonataAdmin to recognize it.
1º You have some info here Sonata Admin - Custom template
2º More info here customize field types
An example could be something like this:
Admin class
protected function configureFormFields(FormMapper $formMapper) {
$formMapper
->add('name', 'ajax_autocomplete')
->add('description', 'text')
;
}
And, in the TWIG template you need to extend from the Sonata Admin field template that better fits your necessities. In this case maybe base_edit.html.twig or edit_text.html.twig
You have a list of templates to extend from, inside this Sonata Admin dir: vendor\sonata-project\admin-bundle\Sonata\AdminBundle\Resources\views\CRUD
Customization
Imagine you have placed your custom template inside XXXBundle:YYY:ajax_autocomplete.html.twig
I think it should work if you write a line here:
sonata_doctrine_orm_admin:
templates:
types:
list:
ajax_autocomplete: XXXBundle:YYY:ajax_autocomplete.html.twig
Starting from sonata admin 3.x you can add/remove js/css to/from the page without extending it.
sonata_admin:
....
assets:
# javascript paths to add to the page in addition to the list above
extra_javascripts:
- 'your js file path'
# javascript paths to remove from the page
remove_javascripts:
- 'your js file path'
you can find more information here https://github.com/sonata-project/SonataAdminBundle/pull/4836/files?short_path=e252be0#diff-e252be027e26148c11d971dc969f4be0

Categories

Resources