Override template in django admin - python

I'm using Django 1.11
I was able to extend/override one template called change_form.html
I placed this file under /templates/admin/my_app/my_model/
For this one I extended and changed one block, like in the example in django docs
I was not able to override one template called submit_line.html
I tried placing it under /templates/admin/, /templates/admin/my_app/, and /templates/admin/my_app/my_model/. None worked.
I edited the file under django/contrib and it worked, but I don't want to change that file. It was just to see if the content was showing.
I just want to add one button to the template, so the user can download one XML file.

After some tests and research here is the solution.
First, underneath /templates/admin/my_app/my_model/ copy-paste the submit_line.html from django/contrib/admin/templates/admin/.
Change submit_line.html and add any urls you like. Say:
<!-- submit_line.html -->
{% load i18n admin_urls %}
<div class="submit-row">
{% if show_save %}<input type="submit" value="{% trans 'Save' %}" class="default" name="_save" />{% endif %}
{% if show_delete_link %}
{% url opts|admin_urlname:'delete' original.pk|admin_urlquote as delete_url %}
<p class="deletelink-box">{% trans "Delete" %}</p>
{% endif %}
<!-- NEW SUBMIT INPUTS -->
<input type="submit" value="TEST" name="_saveasnewss" />
<input type="submit" value="TEST 2" name="_saveasnews" />
<!-- END NEW SUBMIT INPUTS -->
{% if show_save_as_new %}<input type="submit" value="{% trans 'Save as new' %}" name="_saveasnew" />{% endif %}
{% if show_save_and_add_another %}<input type="submit" value="{% trans 'Save and add another' %}" name="_addanother" />{% endif %}
{% if show_save_and_continue %}<input type="submit" value="{% trans 'Save and continue editing' %}" name="_continue" />{% endif %}
</div>
We're copy-pasting it because there aren't any {% block %} tags inside the change_form.html to override.
Further on, inside the change_form.html, add these:
<!-- change_form.html -->
{% extends "admin/change_form.html" %}
{% load my_app_tags %} /* Change "my_app" to your app name that will contain the 'submit_row' template tag */
OTHER OVERRIDES HERE
{% block submit_buttons_bottom %}{% submit_row %}{% endblock %}
Finally, in your app's templatetags, add this template tag:
# my_app/templatetags/my_app_tags.py
from django.contrib.admin.templatetags.admin_modify import submit_row
from django.template.loader import get_template
from django import template
# this would be the path to your "submit_line.html"
t = get_template('admin/my_app/my_model/submit_line.html')
register = template.Library()
register.inclusion_tag(t, takes_context=True)(submit_row)
That's it! Now you should see these extra <input type="submit" /> only under my_model add/change page. If you want them globally just move submit_line.html from where it is to templates/admin/. Don't forget to update the paths inside my_app/templatetags/my_app_tags.py too.

Related

Django form action attribute is not working propely

I am working on app in django 1.11, on search feature. I installed elasticsearch - here all things are working.
In base.html and under url 127.0.0.1:8000 - I have form to search and I would like to keep this form here. On another hand I have search app with view, url, template - under url 127.0.0.1:8000/search/ - search is working here.
To solve this problem - search on main page and redirect on site with results I was trying to use action attribute in django form.
form in base.html
<form action="{% url 'search:search' %}" method="post">
{% csrf_token %}
<div class="input-group">
<input type="text" class="form-control" id="q" {% if request.GET.q %}value="{{ request.GET.q }}"{% endif %} name="q" placeholder="Search">
<div class="input-group-append">
<button class="btn btn-outline-primary" type="button">GO</button>
</div>
</div>
</form>
view in search app
def search(request):
q = request.GET.get('q')
if q:
posts = PostDocument.search().query('match', title=q)
else:
posts = ''
return render(request, 'search/search.html', {'posts': posts})
template with results
{% extends 'base.html' %}
{% block content %}
{% for p in posts %}
{{ p.title }}
{% endfor %}
{% endblock content %}
{% block sidebar %}{% endblock sidebar %}
You here mix up GET and POST. If the method is method="post", then the data is passed in the request, and thus ends up in the request.POST query dictionary.
If on the other hand the method is method="get", then the data ends up in the querystring of the URL. In that case, you can indeed use request.GET.
Often (not always), search queries are done with querystrings, since then a person can copy the URL and send it to another person, and that person thus can see the search results.
You can thus change the form to:
<form action="{% url 'search:search' %}" method="get">
{% csrf_token %}
<div class="input-group">
<input type="text" class="form-control" id="q" {% if request.GET.q %}value="{{ request.GET.q }}"{% endif %} name="q" placeholder="Search">
<div class="input-group-append">
<button class="btn btn-outline-primary" type="button">GO</button>
</div>
</div>
</form>

Don't do something in Base on a Particular template page - Django

I have setup my nav bar in my base.html as follows
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
{% if user.is_authenticated %}
<li>Logout</li>
<li>My Profile</li>
{% else %}
<li>Login</li>
<li>Register</li>
{% endif %}
</ul>
Now the problem is that I Don't want to execute the {% if %} block when user is not authenticated and when I am rendering a particular template page i.e
create_thing.html
{% extends 'layouts/base.html' %}
{% block title %} Create a Thing
- {{ block.super }}{% endblock %}
{% block content %}
<div id="content">
<h1> Create a Thing </h1>
<form role="form" action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
</div>
{% endblock %}
Simply copying the contents from Base and pasting it after removing doesn't help. It still executes base.html and gets inside the if statement and shows an error because slug wont be defined until I have filled details in create_thing.html.
Try nesting the {% if %} clause in another {% if not aux_var %} clause. Whenever you don't want to execute the first if, pass "aux_var":1 to the renderer as context.

django 1.6: style django's built in forgot password template

I'm trying to style django's built in forgot password registration to remove the generic Django green theme and have my own customized them. But I'm unable to do that.
here is the registration/password_reset_form.html with my header and footer that has my bootstrap and custom css files. But they are not reflected in the template. I still see the default django styling.
{% include "meddy1/header.html" %}
{% load staticfiles %}
{% block title %}Reset Password{% endblock %}
<p>Please specify your email address to receive instructions for resetting it.</p>
<form action="" method="post">
<div style="display:none">
<input type="hidden" value="{{ csrf_token }}" name="csrfmiddlewaretoken">
</div>
{{ form.email.errors }}
<p><label for="id_email">E-mail address:</label> {{ form.email }} <input type="submit" value="Reset password" /></p>
</form>
{% include "meddy1/footer.html" %}

Handle enter button in change_form Django

I'm new with Django and python. I have a problem. Is there a way, after click enter button to be redirected to the same change_form page without being passed to change_list page by Django? This is the UI that I mean:
(enter button in under all fieldset)
Hope you can understand what i mean and give me some responses. Thank you :).
Change the submit_line.html template
I've changed:
{% if show_save %}<input name="_save" type="submit" value="{% trans 'Save' %}" class="default" {{ onclick_attrib }}/>{% endif %}
to:
{% if show_save %}<input name="_continue" type="submit" value="{% trans 'Save' %}" class="default" {{ onclick_attrib }}/>{% endif %}
which will cause the default save-button to act as the save-and-continue-button.
this stackoverflow-question or the django documentation may help you to change the submit_line-template correctly
complete "submit_line.html":
{% load i18n %}
<div class="submit-row">
{% if show_save %}<input type="submit" value="{% trans 'Save' %}" class="default" name="_continue" {{ onclick_attrib }}/>{% endif %}
{% if show_delete_link %}<p class="deletelink-box">{% trans "Delete" %}</p>{% endif %}
{% if show_save_as_new %}<input type="submit" value="{% trans 'Save as new' %}" name="_saveasnew" {{ onclick_attrib }}/>{%endif%}
{% if show_save_and_add_another %}<input type="submit" value="{% trans 'Save and add another' %}" name="_addanother" {{ onclick_attrib }} />{% endif %}
</div>
If you are talking about the django admin, there's three buttons:
Save and Add New
Save and Continue Editing ( you need to click this one )
Save
If you're talking about your own apps, add a next parameter to your forms catch it in form validation and redirect accordingly
Edit:
I see you created a custom button, you can override the save/enter method in your ModelAdmin and redirect to wherever you want. Just add a hidden next input to your form.
Example:
settings.py
TEMPLATE_CONTEXT_PROCESSORS = (
# other stuff
"django.core.context_processors.request",
)
your change form template:
<input type="hidden" name="next" value="{{request.path}}" />
the enter button, will cause the underlying html-form to be submitted.
this has nothing todo with django or python and is browser specific.
the django change_form has three submit-buttons, the last one will used.
there are multiple ways todo this:
override hange_form-template and add some jquery to react on the keypress event (enter) and fire the button of choice.
reorder those buttons

django - How can I render a template I use everywhere in my webpage?

I'm using django 1.2.4.
I have a template for login in registration/login.html (wich action is django.contrib.auth.views.login) and I want to include it on everypage. I created a block on my base.html as I do for every template. The thing is the browser doesn't recognize this login block and I think it is because I only render a template for each view, I am not rendering this login template.
Here is my folder structure:
/templates/
base.html
/myapp/
object_list.html
...
/registration/
login.html
...and here is my login.html:
{% extends "base.html" %}
{% block mylogin %}
<div class="horizontal">
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
<form action="{% url django.contrib.auth.views.login %}" method="post">
{% csrf_token %}
<div class="login_box">
<div class="login_text">{{ form.username.label_tag }}</div><div class="login_input">{{ form.username }}</div>
<div class="password_text">{{ form.password.label_tag }}</div><div class="password_input">{{ form.password }}</div>
<input id="button_login" type="submit" value="" />
</div>
</form>
</div>
{% endblock %}
...and in my base.html I have:
<div id="some_div">
{% block mylogin %} {% endblock %}
</div>
I have a basestyle.css included in base.html and the other templates inherit correctly too... it seems to be a block problem...
So.. how can I render this template for every view??
Thank you
I think you are looking for the include tag. This way you can include your login html snippet in your base.html :
{% include "/registration/login.html" %}
What I really need was to create a templatetag in templatetags/mytags.py, where I define a function called get_login wich looks like this:
#register.inclusion_tag('registration/login.html', takes_context=True)
def get_login(context):
...
return {'formLogin': mark_safe(AuthenticationForm())}
...and in base.html:
{% load mytags %}{% get_login %}
The problem now is that the template (registration/login.html) doesnt recognize '{{ formLogin.username }}','{{ formLogin.password }}' and so on.
What am I missing?
Update 1:
mark_safe returns an instance of django.utils.safestring.SafeString, not a form.
Use (AuthenticationForm() instead of mark_safe(AuthenticationForm()) and it works!

Categories

Resources