how to add change language dropdown to Django(1.10) admin? - python

I'm planning to add change language dropdown in my admin page.
according to this code and How to extend admin page.
I copy base_site.html and copy it to myapp/templates/admin, the i create a html file named change_language.html and write this code in it:
{% load i18n %}
/ {% trans 'Change language' %}
<form action="/i18n/setlang/" method="post" style="display: inline;">
<div style="display: inline;">
<select name="language" onchange="javascript:form.submit()">
{% for lang in LANGUAGES %}
<option value="{{ lang.0 }}"{% ifequal LANGUAGE_CODE lang.0 %} selected="selected"{% endifequal %}>{{ lang.1 }}</option>
{% endfor %}
</select>
</div>
</form>
I add {% extends 'admin/base_site.html' %} at the top of this file, noting happens.
I add {% extends 'admin/base.html' %} , again noting happens.
All hints and answers says that we should change something name <div id="user-tools"> at line 25 of base.html, But in Django 1.10 it goes to line 31 with a different staff. im kinnda lost because i read many different staff every where and non of them works for me. Dose any know where im doing wrong ?
here is my middlewares :
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
And template settings :
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR,'templates'),
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

In your templates/admin folder, make sure the file is named base_site.html (otherwise the default base_site will not be overwritten).
Make sure to copy the latest version of the file from the django-repo.
Most important: verify you extend the admins base.html (your base_site.html should start with {% extends "admin/base.html" %})
You may now add your form (for example to the footer):
{% extends "admin/base.html" %}
{% load i18n %}
{% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}
{% block branding %}
<h1 id="site-name">{{ site_header|default:_('Django administration') }}</h1>
{% endblock %}
{% block nav-global %}{% endblock %}
{% block footer %}
<div id="footer">
<form action="/i18n/setlang/" method="post">
{% csrf_token %}
<select name="language">
{% for lang in LANGUAGES %}
<option value="{{ lang.0 }}"
{% ifequal lang.0 request.LANGUAGE_CODE %}
selected="yes"
{% endifequal %}
>{{ lang.1 }}</option>
{% endfor %}
</select>
<input type="submit" value="{% trans 'Change language' %}" />
</form>
</div>
{% endblock %}
Refer to the base.html to find a block that seems suitable for your form.
You will also need to add the i18n urls to your url-settings
url(r'^i18n/', include('django.conf.urls.i18n')),
And if you really want to submit your form using javascript you will also need to get and submit the csrf token for the form. The django docs cover this topic quite comprehensive.

In addition to Kim's answer, you should add i18n context processor in your django settings django.template.context_processors.i18n to be able to access LANGUAGES variable in the template.

I guess you are mixing both answers that you've found on the internet. One of them copies and changes a couple of files from the admin template, effectively overriding them in your program's references. The second one extends admin's templates. You should completely implement just one of them.

Related

Django HoneyPot Change Password Issue

I would appreciate if you could give me any clue! As I don't have experience in this, probably I've misunderstood smth.
I'm using honeypot, more specifically honeypot.middleware.HoneypotMiddleware with HONEYPOT_FIELD_NAME in my API (settings.py).
As for the moment it's enough, I'm using the basic implementation for login, password change, reset from django.contrib.auth. In login I did a small customization so I added it in the url (authentication_form=CustomAuthenticationForm).
So I don't konw what I'm missing because the login page works (it is also a form), but the password change, reset ones are returning 400 Bad Request. Honey Pot Error (honey_pot_fieldname). Request aborted.
django: 2.1.2
django-honeypot: 0.7.0
[Updating with code]
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
....
'honeypot',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'honeypot.middleware.HoneypotMiddleware',
]
HONEYPOT_FIELD_NAME = config('HONEYPOT_FIELD_NAME')
forms.py
from django.contrib.auth.forms import AuthenticationForm
class CustomAuthenticationForm(AuthenticationForm):
error_messages = {
'invalid_login': _(
"Please enter a correct %(username)s and password. Note that both "
"fields may be case-sensitive."
),
'inactive': _("This account is inactive."),
'suspended': _("Your account has been temporarily suspended. For more information,\
please contact us."),
}
def clean(self)
def confirm_login_allowed(self, user)
urls.py
from django.contrib.auth import views as auth_view
urlpatterns = [
....
# ---- BASIC USER AUTHENTICATION (DJANGO)
path('api/login/', auth_view.LoginView.as_view(authentication_form=CustomAuthenticationForm), name='login'),
path('api/logout/', auth_view.LogoutView.as_view(), name='logout'),
# ---- PASSWORD CHANGE, RESET
path('api/password_change/', auth_view.PasswordChangeView.as_view(), name='password_change'),
path('api/password_change_done/', auth_view.PasswordChangeDoneView.as_view(),
name='password_change_done'),
....
]
[Templates]
templates/resgistration/login.html
{% extends 'base.html' %}
{% load i18n widget_tweaks %}
{% block head %}
{% load bootstrap3 %}
{{ form.media }}
{% endblock %}
{% block content %}
<div class="col-sm-4 col-sm-offset-4" style="margin-top:20px;">
<h1 class="display-4 text-center" >User login</h1>
<legend></legend>
<form method="post">
{% csrf_token %}
{% bootstrap_form form layout='inline' %}
{% buttons %}
<button type="submit" class="btn btn-primary center-block" style="margin-top: 20px">Log in</button>
{% endbuttons %}
</form>
</div>
{% endblock %}
templates/resgistration/password_change_form.html
{% extends 'base.html' %}
{% load i18n widget_tweaks %}
{% block head %}
{% load bootstrap3 %}
{{ form.media }}
{% endblock %}
{% block content %}
<div class="col-sm-4 col-sm-offset-4" style="margin-top:20px;">
<h1 class="display-4 text-center" >{{ title }}</h1>
<legend></legend>
<form method="post">
{% csrf_token %}
{% bootstrap_form form layout='inline' %}
{% buttons %}
<button type="submit" class="btn btn-primary center-block" style="margin-top: 20px">Change password</button>
{% endbuttons %}
</form>
</div>
{% endblock %}
Thanks in advance!
[Updating with solution]
Finally I achieved it!
I only had to add at the top of the template change_password_form.html the line
{% load honeypot %}
and within the form including the tag:
{% render_honeypot_field "field_name" %}
For achieve this helped me this article
django-honeypot
Hope that will be helpful for others.

Locale from django app not change

I newbie into Django, and I need make a I18N system. I have this url.py:
from django.contrib import admin
from django.urls import path, include
from . import views
urlpatterns = [
path('', views.index, name='home'),
path(r'^i18n/', include('django.conf.urls.i18n')),
]
And I made this html to change the language:
{% load i18n %}
<form action="/i18n/setlang/" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="{{request.path}}" />
<select name="language">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected="selected"{% endif %}>
{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>
<input type="submit" value="Go" />
</form>
But when I click in "Go" button, the server response is: Page not found (404), The current path, i18n/setlang/, didn't match any of these. I stay using python 3.6 and Django 2.0.4.
And I no have idea how can I solve it.
The problem was here:
path(r'^i18n/', include('django.conf.urls.i18n')),
I cut off r'^':
path('i18n/', include('django.conf.urls.i18n')),
and works!

Django page no found

views.py
def search_author(request):
if 'q' in request.GET and request.GET['q']:
q = request.GET['q']
authors =User.objects.filter(username=q)
return render_to_response('search_results.html',
{'authors': author, 'query': q})
else:
return HttpResponse('Please submit a search term.')
def search_form(request):
return render_to_response('search_form.html')
urls.py
url(r'^search_author$',app.views.search_author),
url(r'^search_form$', app.views.search_form)
search_form.html
{% extends "app/layout.html" %}
{% block content %}
<form action="/search_author/" method="get">
<input type="text" name="q">
<input type="submit" value="Search">
</form>
search_results.html
{% extends "app/layout.html" %}
{% block content %}
<p>You searched for: <strong>{{ query }}</strong></p>
{% if authors%}
<p>Found {{ authors|length }} author{{ authors|pluralize }}.</p>
<ul>
{% for author in authors %}
<li>{{ author.username }}</li>
{% endfor %}
</ul>
{% else %}
<p>No authors matched your search criteria.</p>
{% endif %}
loginparitial.html
{% if user.is_authenticated %}
<form id="logoutForm" action="/logout" method="post" class="navbar-right">
{% csrf_token %}
<ul class="nav navbar-nav navbar-right">
<li><span class="navbar-brand">您好 {{ user.username }}!</span></li>
<li>查询作者</li>
<li> 发布旧书</li>
<li><a href="user_book_detail" >查看我的书籍</a></li>
<li> 登出</li>
</ul>
when l click the '查询作者' in the home page,the error says
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/search_form/
Can anyone help me with my problem ? Thanks in advance
It's because of your regex pattern.
/search_form/ is different from your specified ^search_form$. That maps to /search_form (No trailing slash). To make it /search_form/, just use ^search_form/$.
I think you giving wrong routing to templates.
In settings.py you giving templates directory route like this
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
then your templates loaded from main app folder --> templates folder.
You can call templates directly in views.
If you save your templates in another folder in templates folder,then you need to give the template route upto that folder.
For example:
you saved your templates in main app folder -->templates --> app folder.
then you have to give the route upto to app folder.
like this:
def search_form(request):
return render_to_response('app/search_form.html').
Try once..!

How can I change Django admin language?

I have a django 1.6 site with i18n working. I can change the frontend language with a select box in the top of the template, but I don't know if there is a django app or trick to change the admin language, because it seems to store somewhere in session variable, and it keeps the first language I have used in the frontend.
In your settings.py just add 'django.middleware.locale.LocaleMiddleware' to your MIDDLEWARE_CLASSES setting, making sure it appears after 'django.contrib.sessions.middleware.SessionMiddleware'.
You can create /en/admin, /fr/admin/ and so on using i18n_patterns:
urlpatterns += i18n_patterns(
url(r'^admin/', include(admin.site.urls)),
)
(For Django <= 1.7, you must specify a prefix, use i18n_patterns('', ... ))
Here is a slightly modified version of a code snippet from the Django docs for admin/base.html that adds a language selection dropdown:
{% extends "admin/base.html" %}
{% load i18n %}
{% block userlinks %}
{{ block.super }}
/ <form action="{% url 'set_language' %}" method="post" style="display:inline">{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}">
<select name="language" onchange="this.form.submit()">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected{% endif %}>
{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>
</form>
{% endblock %}
For this to work you also need to add the following to your urlpatterns:
path('i18n/', include('django.conf.urls.i18n')),

Django doesn't seem to detect my login.html, block problem?

I'm creating a web app with django 1.2.4.
I am using contrib.auth.views.login, I have followed every step but it seems I have forgotten something cause I don't see the login form. 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...
Any solution??
Thnak you
Instead of inserting of a block I used the include tag in base.html, just like this:
{% include "registration/login.html" %}
If you’d prefer not to call default (django provided) template registration/login.html, you can pass the template_name parameter via the extra arguments to the view in your URLconf.
For example, this URLconf line would use myapp/login.html instead:
(r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'myapp/login.html'}),
Reference : Django official documentation
It solves my problem. Hope this works for others.

Categories