How to add custom JS to Django model admin - django

I have a Django model that requires an OAuth token as one of its properties. The easiest way to generate the token is using the supplied client-side JS from the API provider. I'd like to add a simple link to the add/edit template in the Django admin site to invoke this JS and put the resulting token into the appropriate field - see attached as an example of where I'm trying to get to.
I've read the Overriding admin templates documentation, but that doesn't cover this use case.

You can rewrite django/contrib/templates/admin/change_form.html
{% extends "/admin/change_form.html" %}
{% block extrahead %}{{ block.super }}
<script type="text/javascript" src="..."></script>
{% endblock %}

Related

Ajax: SyntaxError: Unexpected token < in JSON at position 2 [duplicate]

Can I use Django's template tags inside Javascript? Like using {% form.as_p %} in jQuery to dynamically add forms to the page.
Yes, I do it frequently. Your javascript has to be served through django, but if you just have it in the html header as inline javascript you'll be fine.
E.g: I use this to put prefix on a dynamic formset I use.
{% extends "base.html" %}
{% block extrahead %}
<script type="text/javascript">
$(document).ready(function() {
{# Append fields for dynamic formset to work#}
{% for fset, cap, _, tid in study_formsets.fset_cap_tid %}
$(function() {
$('.form_container_{{ tid }}').formset({
prefix: '{{ fset.prefix }}',
formCssClass: '{{ tid }}',
extraClasses: ['myrow1', 'myrow2']
});
});
{% endfor %}
});
</script>
{% endblock %}
Note in "base.html" I have a html head where the jquery libraries are loaded, that contains {% block extrahead %}{% endblock %}.
You can't use Django's template tags from your Javascript code if that's what you mean. All the Django variables and logic stop existing after the template has been rendered and the HttpResponse has been sent to the client. At that moment when Javascript executes, the client (browser) has no notion the variables you rendered the template with (such as "form").
What you can do is have Javascript modify your HTML page using chunks of HTML that were rendered by your Django template.
If you want to generate HTML on client side, I'd recommend to look at client side tempalte libraries (eg. JQuery Templates - use those with the {% verbatim %} templatetag).
If you want to use variables inside your rendered javascript I (that's my opnion), think it's a bad idea. But if all you want is to generate URL for your views, media and static files, I do this a lot.
Take a look to this github: jscssmin
Yes, you can use`
Example : `{{ user.username }}`
Be sure this is not single quotes but '(back tick / back quote)

Django asset manager for Views or template tags?

I come to Django having used the Yii2 PHP framework. One of the good features about that is it allows you to create asset files for CSS and JS which are then loaded into the base layout file at runtime. This allows you to keep the base template clean of CSS and JS markup within the head and at the bottom of the HTML document. The CSS and JS files you specify in the asset file are automatically placed in the correct position in the document and you can also specify dependencies if needed.
At the moment, with Django I am having to edit the base.html file manually which is not ideal.
I know you can use the Media class for forms, and in admin.py, which does a similar job. However, what I would like to do is to something like this (for example) in inclusion template tags or in a class based view perhaps.
Is this possible?
Many thanks!
UPDATE
Here is a similar question Is it possible to use django's custom template tags to insert code in other blocks in the template?
do you find block tag?
base.html
<head>
{% block extra_css %}{% endblock %}
<head>
view.html
{% extends 'base.html' %}
{% block extra_css %}
<link rel="stylesheet" href="YOUR URL">
{% endblock %}

include static files from django template

I'm trying to include a static html page from a django template.
I tried using {% include the_static.html %} but this doesn't work for some unknown reason.
the_static.html page is a data page that will be modified often with an html editor.
and my_model has a url to this html and include it. But django refuses to find it although I'm sure I've setup the path correctly.
You can write your custom template tag to do this.
Create a file named includestatic.py under appname/templatetags/. Also, remember to create appname/templatetags/__init__.py, to include the app in settings and to restart the server.
includestatic.py should have this code:
from django import template
from django.contrib.staticfiles import finders
from django.utils.html import escape
register = template.Library()
#register.simple_tag
def includestatic(path, encoding='UTF-8'):
file_path = finders.find(path)
with open(file_path, "r", encoding=encoding) as f:
string = f.read()
return escape(string)
To use it in your template, put {% load includestatic %} at the top of your template, and then use the tag like {% includestatic "app/file.txt" %}.
I am not sure I understand everything yet...
You've an HTML page served by Django on a given url, let's suppose it to be http://mydjangodomain/get_the_static/. This URL is set in the urls.py of your model. Ok, that's normal.
You have a django template for this model. Let's suppose it's defined in a template directory mytemplates/mymodeltemplates/ and it's called myfrontpage.html (since in Django templates are html files).
I guess you've an URL defined in your urls.py to server that front page ? Let's suppose it's http://mydjangodomain/get_the_front_page/
Now I don't understand how your front page use your static html. Do your final front page html need the static's URL for a "src" attribute or something like it, or do you need to include the static's html into the front page's html ?
In the 1st case, you already have the URL, it's http://mydjangodomain/get_the_static/ so just use it as if.
In the 2nd case, you don't need the previous URL, get ride of it. Furthermore, put the_static.html in mytemplates/mymodeltemplates/. Then you need the {% include "/mymodeltemplates/the_static.html" %} tag. If this doesn't work, make sure you've the following in your settings:
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
APPLI_ROOT_PATH = "<absolute_path_to_the_application_root_on_your_server>"
TEMPLATE_DIRS = (
'%s/mytemplates' % APPLI_ROOT_PATH,
)
Sort of resurrecting the dead, but at least with django 1.10, there's a very clean answer here:
http://www.effectivedjango.com/tutorial/static.html
an excerpt from that page:
Simple Template Inclusion We want to add the Boostrap CSS to all of
our templates, but we’d like to avoid repeating ourself: if we add it
to each template individually, when we want to make changes (for
example, to add another stylesheet) we have to make them to all the
files. To solve this, we’ll create a base template that the others
will inherit from.
Let’s create base.html in the templates directory of our contacts app.
{% load staticfiles %}
<html>
<head>
<link href="{% static 'bootstrap/css/bootstrap.min.css' %}"
rel="stylesheet" media="screen">
</head>
<body>
{% block content %}
{% endblock %}
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</body>
</html>
base.html defines the common structure for our pages, and includes a
block tag, which other templates can fill in.
We’ll update contact_list.html to extend from base.html and fill in
the content block.
{% extends "base.html" %}
{% block content %}
<h1>Contacts</h1>
<ul>
{% for contact in object_list %}
<li class="contact">{{ contact }}</li>
{% endfor %}
</ul>
add contact
{% endblock %}
Having followed this exactly, I now have a base.html that includes all my style references and the navigation bars/etc, so the html in the block content is merely the central contents of each (varying) page.
Do you mean that you want to EXTENDS the parent template the_static.html?
If yes, you should add below code at the first line of your children template:
{% extends "the_static.html" %}
Details documentation can be found here

Adding views to the Django admin

Is there a way to add custom views to the Django admin app?
To be specific, I would like to be able to switch out the "content" div for custom static content, while preserving the "header" and "footer" divs. This is different than redirecting to a static HTML page, which would not preserve the header and footer.
You just configure your view as usual (urls.py -> myapp.views) and then extend the admin base template:
{% extends "admin/base_site.html" %}
{% block content %}
My content looking like the rest of the admin app.
{% endblock %}
Here is a small intro http://www.djangobook.com/en/1.0/chapter17/, I think where is new version, but I think where is nothing changed in concept of extending admin pages.

Edit Django admin logout template?

I want to make a very small change to the Django admin logout page.
I know how to use templates to override the Django admin templates, so I have tried to do the same thing with the logout file.
I have set up a new template at templates/registration/logged_out.html. The content of this file is as follows:
{% extends "registration/logged_out.html" %}
{% block content %}
<p>Thanks for using the site.</p>
<p>Log in again</p>
<p>Return to the home page</p>
{% endblock %}
However, something is definitely wrong, because when I try to log out of admin, the site stops running.
I've found the Django docs page recommending the use of AdminSite for changes to the base template and logout pages, but is this really necessary for such a tiny change?
If so, does anyone have an example of how I might set up the logout template? I'm rather intimidated by the instructions for AdminSite.
Thanks.
The reason of manage.py runserver termination is an inheritance loop.
Django loads "registration/logged_out.html" and that it tries to load it's parent: "registration/logged_out.html". Unfortunately parent is the same template and so we end up on the template inheritance loop.
Manage.py will terminate with some variant of stack overflow error...
You can easily escape the issue by extending the parent of original "registration/logged_out.html" -> "admin/base_site.html". I.e:
{% extends "admin/base_site.html" %}
{% load i18n %}
{% block breadcrumbs %}<div class="breadcrumbs">{% trans 'Home' %}</div>{% endblock %}
{% block content %}
<p>Thanks for using the site.</p>
<p>Log in again</p>
<p>Return to the home page</p>
{% endblock %}
You're getting a template import loop. The template loader won't load the base template form wherever you've got Django installed, because it sees that you have that template in your project's template folder.
I think you'll need to copy the log out template from where you have Django installed to your project's template folder. Unfortunately that's the only way that seems to work. This method also means that if updates are made to the Django admin templates, you'll have to manually apply them to your modified templates.