Extending Django admin delete confirmation page - python

I am wondering if it is possible to extend Django Admin's delete confirmation page for specific app and model. I want the functionality that enable user to delete all records like that of django admin interface. it is possible to extends delete confirmation.html in my app

You can extend the Django admin delete confirmation page. To extend it, in your templates directory, create a directory named admin and create an html file named delete_selected_confirmation.html with the below content (the default admin delete confirmation page source)
{% extends "admin/base_site.html" %}
{% load i18n l10n admin_urls static %}
{% block extrahead %}
{{ block.super }}
{{ media }}
<script src="{% static 'admin/js/cancel.js' %}" async></script>
{% endblock %}
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} delete-confirmation delete-selected-confirmation{% endblock %}
{% block breadcrumbs %}
<div class="breadcrumbs">
{% translate 'Home' %}
› {{ opts.app_config.verbose_name }}
› {{ opts.verbose_name_plural|capfirst }}
› {% translate 'Delete multiple objects' %}
</div>
{% endblock %}
{% block content %}
{% if perms_lacking %}
<p>{% blocktranslate %}Deleting the selected {{ objects_name }} would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktranslate %}</p>
<ul>
{% for obj in perms_lacking %}
<li>{{ obj }}</li>
{% endfor %}
</ul>
{% elif protected %}
<p>{% blocktranslate %}Deleting the selected {{ objects_name }} would require deleting the following protected related objects:{% endblocktranslate %}</p>
<ul>
{% for obj in protected %}
<li>{{ obj }}</li>
{% endfor %}
</ul>
{% else %}
<p>{% blocktranslate %}Are you sure you want to delete the selected {{ objects_name }}? All of the following objects and their related items will be deleted:{% endblocktranslate %}</p>
{% include "admin/includes/object_delete_summary.html" %}
<h2>{% translate "Objects" %}</h2>
{% for deletable_object in deletable_objects %}
<ul>{{ deletable_object|unordered_list }}</ul>
{% endfor %}
<form method="post">{% csrf_token %}
<div>
{% for obj in queryset %}
<input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}">
{% endfor %}
<input type="hidden" name="action" value="delete_selected">
<input type="hidden" name="post" value="yes">
<input type="submit" value="{% translate 'Yes, I’m sure' %}">
{% translate "No, take me back" %}
</div>
</form>
{% endif %}
{% endblock %}
now the directory and file structure should look like this. Now you can extend the above template as per your need.
├── templates
   └── admin
      └── delete_selected_confirmation.html

Related

Invalid block tag on line 10: 'endblock', expected 'empty' or 'endfor'. Did you forget to register or load this tag? django (python)

I want registration and log in form in same page and in same html file. when i render form1 i have problem. i search in google but can't fix. can i render two form same html?
this is code --->
{% extends 'base.html' %}
<link rel="stylesheet" type="text/css" href="/static/css/style.css?{% now "U" %}" />
{% block content %}
<form action = '' method="post" novalidate="novalidate" id="reg" >
{% csrf_token %}
<div class="continer">
{% for field in form %}
{{ field.label_tag }}
{{ field }}
{{ field.errors }}
{% endfor %}
<button type="submit" name="register" id="btn" >registraton</button>
<button type="button" name="log" id="lgn">login</button>
</div>
</form>
<form action="" method="post" novalidate="novalidate" id="log">
{% csrf_token %}
<div class="continer2">
{% for field in form1 %}
{{ field }}
</div>
</form>
{% endblock %}
You're missing an endfor for the last for loop:
{% for field in form1 %}
{{ field }}
{% endfor %}
The error message indicated that you might be missing an endwith or endfor which is a hint to look for a with or for that hasn't been closed.

how to import a block of a template in jinja2

I want to use jinja2 to design a template that will be rendered as an article whose chapters and sections should be combined freely. So I create a base.html as a skeleton. The problem is that the chapters and sections contain some reusable table and image elements, and if I use these elements as 'macro', then it will be difficult to use chapters and sections as 'macro' too. But if I use chapters and sections as 'block', how can I import 'block' into the skeleton? And some local variables must be passed into chapters and sections.
Here is an example of my script. The script reads config.json and turns it into a dict to pass to the base.html for rendering. The actual number of chapters and sections are much more than that I represent in the example, with multiple paragraphs, and the number of type of components too.
#config.json
{"templates":[
{"title":"chapter1",
"children":[
{"title":"chapter1_1","template":"template1.html","block":"block1"},
{"title":"chapter1_2","template":"template2.html","block":"block1","parameter":{"note":"hello world"}},
]},
{"title":"chapter2","template":"template1.html","block":"block2","parameter":{"note":"blabla"}}
]}
#base.html
{% from "component.html" import common_table as common_table with context %}
{% from "component.html" import common_img as common_img with context %}
{%- for chapter in chapter_list %}
{%- set ch_loop = loop %}
<h2>{{ ch_loop.index }} {{ chapter.title }}</h2>
{%- if chapter.children %}
{%- for section in chapter.children %}
<h3>{{ ch_loop.index }}.{{ loop.index }} {{ section.title }}</h3>
{% import section.template as template with context %}
{% set parameter=section.parameter %}
{{ template.blocks[section.block] }}
{%- endfor %}
{%- else %}
{% import chapter.template as template with context %}
{% set parameter=chapter.parameter %}
{{ template.blocks[chapter.block] }}
{%- endif %}
{%- endfor %}
#template1.html
{% block block1 %}
I am block 1
{{ common_table(id="table1",head="nohead") }}
{{ common_img(src="css/icon/icon1.png") }}
{% endblock %}
{% block block2 %}
I am block 2
{{ common_img(src="css/icon/icon2.png") }}
{% if parameter.note=="blabla" %}
{{ "blabla~blabla~" }}
{% endif %}
{% endblock %}
#component.html
{% macro common_table(id, name,note, head="onehead") %}
{% if name %}
<b class="tablename">{{ name }}</b>
{% endif %}
<table id="{{ id }}" class=" {{ head }}"></table>
{% if note %}
<p class="tablenote">{{ note }}</p>
{% endif %}
{% endmacro %}
{% macro common_img(src, alt, name) %}
<img src="{{ src }}" alt="{{ alt }}">
{% if name %}
<b class="imgname">{{ name }}</b>
{% endif %}
{% endmacro %}
I searched and found that the template object in script seems to have 'blocks' attribute, so I tried to import template files as an object and use '.blocks' to get the block attribute of template object, but it gave me an error as following:
jinja2.exceptions.UndefinedError: 'jinja2.environment.TemplateModule object' has no attribute 'blocks'
I checked the code of jinja2 and found that the imported template object is 'TemplateModule' class, different from the 'Template' class in script, and the 'TemplateModule' class doesn't seem to have 'blocks' attribute, even doesn't export blocks .
So how can I import a block of a template ? Or should I change my jinja2 statements?

Access model properties in Django Admin templates?

I have Django 2.0.3 on Python 3.5.3. I search for simple way to small improve my standard Django Admin dashboard (main page of Django Admin).
Here is my template for Admin main page ./templates/admin/index.html:
{% extends "admin/base_site.html" %}
{% load i18n static %}
{% block extrastyle %}{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static "admin/css/dashboard.css" %}"/>{% endblock %}
{% block coltype %}colMS{% endblock %}
{% block bodyclass %}{{ block.super }} dashboard{% endblock %}
{% block breadcrumbs %}{% endblock %}
{% block content %}
<div id="content-main">
{% if app_list %}
{% for app in app_list %}
<div class="app-{{ app.app_label }} module">
<table>
<caption>
<a href="{{ app.app_url }}" class="section"
title="{% blocktrans with name=app.name %}Models in the {{ name }} application{% endblocktrans %}">{{ app.name }}</a>
</caption>
{% for model in app.models %}
<tr class="model-{{ model.object_name|lower }}">
{% if model.admin_url %}
<th scope="row">{{ model.name }}</th>
{% else %}
<th scope="row">{{ model.name }}</th>
{% endif %}
{% if model.add_url and request.user.is_superuser %}
<td>{% trans 'Add' %}</td>
{% else %}
<td> </td>
{% endif %}
{% if model.admin_url and request.user.is_superuser %}
<td>{% trans 'Change' %}</td>
{% else %}
<td> </td>
{% endif %}
</tr>
{% endfor %}
</table>
</div>
{% endfor %}
{% else %}
<p>{% trans "You don't have permission to edit anything." %}</p>
{% endif %}
</div>
{% endblock %}
I delete sidebar block, because I never use it. And it looks like:
I want to add to each model link count of objects. For example, Cities (23), Citizenships (102) and similar for all models in list. I try to add function with #property decorator in ./app/models.py, but it's not working:
class APIConfig(models.Model):
...
#property
def with_active_status(self):
return self.objects.filter(is_active=True).count()
...
I call this property in Admin template, like {{ model.with_active_status }} and it shows nothing.
This can't be a property. You don't have an instance of the model to call it on. In any case, if you did have an instance it still wouldn't work, as model managers - objects - can only be accessed from the class, not the instance.
You should make it a classmethod:
#classmethod
def with_active_status(cls):
return cls.objects.filter(is_active=True).count()

flask-admin: revise the button text

I haven't found similar questions on stackoverflow, I'd like to change the save button to submit or confirm on the edit form. I know this might not be easily changed. Thanks for any advise in advance.
After search in the code of flask-admin, I found the button is rendered with macro render_form, render_form_buttons, extra. The value of these buttons is hard code with {{ _gettext("blabla") }}.
As these buttons are not fields of data model, we can't use rendering rules to custom the value. I think there are two work arounds to get this done:
change the macro which render these buttons in the source of flask-admin(render_form_buttons, extra)
flask-admin use flask-babelex to do localization({{ _gettext("blabla") }}), you can 'translate' Save to submit or confirm with flask-babelex
UPDATE:
You can custom edit.html in your own template directory.
{% extends 'admin/model/edit.html' %}
{% from 'admin/lib.html' import extra with context %}
{% from 'admin/lib.html' import form_tag with context %}
{% from 'admin/lib.html' import render_form_fields with context %}
{% macro my_render_form_buttons(cancel_url, extra=None, is_modal=False) %}
<hr>
<div class="form-group">
<div class="col-md-offset-2 col-md-10 submit-row">
<input type="submit" class="btn btn-primary" value="{{ _gettext('Submit') }}" />
{% if extra %}
{{ extra }}
{% endif %}
{% if cancel_url %}
<a href="{{ cancel_url }}" class="btn btn-danger" role="button" {% if is_modal %}data-dismiss="modal"{% endif %}>{{ _gettext('Cancel') }}</a>
{% endif %}
</div>
</div>
{% endmacro %}
{% macro my_render_from(form, cancel_url, extra=None, form_opts=None, action=None, is_modal=False) -%}
{% call form_tag(action=action) %}
{{ render_form_fields(form, form_opts=form_opts) }}
{{ my_render_form_buttons(cancel_url, extra, is_modal) }}
{% endcall %}
{% endmacro %}
{% block edit_form %}
{{ my_render_form(form, return_url, extra(), form_opts) }}
{% endblock %}

How can i override django contrib comments template?

The django contrib comments form i'm using:
{% get_comment_form for post as form %}
<form action="{% comment_form_target %}" method="post">{% csrf_token %}
{% if next %}
<div><input type="hidden" name="next" value="{{ next }}" /></div>
{% endif %}
{% for field in form %}
{% if field.is_hidden %}
<div>{{ field }}</div>
{% else %}
{% if field.name == 'comment' %}
{% if field.errors %}{{ field.errors }}{% endif %}
<p
{% if field.errors %} class="error"{% endif %}
{% ifequal field.name "honeypot" %} style="display:none;"{% endifequal %}>
{{ field.label_tag }} {{ field }}
</p>
{% endif %}
{% endif %}
{% endfor %}
<p class="submit">
<input type="submit" name="post" class="submit-post" value="{% trans "Post" %}" />
</p>
</form>
After submitting the form, it redirects to http://127.0.0.1:8000/comments/posted/?c=..
That means it calls the template django/contrib/comments/templates/comments/posted.html
The content of django/contrib/comments/templates/comments/posted.html:
{% extends "comments/base.html" %}
{% load i18n %}
{% block title %}{% trans "Thanks for commenting" %}.{% endblock %}
{% block content %}
<h1>{% trans "Thank you for your comment" %}.</h1>
{% endblock %}
That doesn't extends my project's base.html.
I need to customize/override that template so that it extends my project's base.html. How can i do that?
If i can't do that, then if i upload my django web project on server, then how would i edit the content of django/contrib/comments/templates/comments/posted.html so that it looks like that:
{% extends "path/to/myproject/templates/base.html" %}
{% load i18n %}
{% block title %}{% trans "Thanks for commenting" %}.{% endblock %}
{% block content %}
<h1>{% trans "Thank you for your comment" %}.</h1>
{% endblock %}
On local pc, for this time i changed/edited the content of django/contrib/comments/templates/comments/posted.html hard-coded to extends my project base.html.
Can anyone give some idea to solve this? I have searched a lot to solve this.
Just override it in your project's "templates" directory:
<project_root>/templates/comments/posted.html
It doesn't seem to be well documented in either the comments app or Django's general template documentation, but it works the same as overriding admin templates (which is documented).

Categories