Evgenij LegotskojJune 1, 2022, 4:30 a.m.

Django - Lesson 059. Saving the selected language in user settings

In this article, I would like to show an example of how you can make a link on the site so that the user can switch between languages on the site.

But I will show a more advanced version of this functionality, namely saving the selected language in the user table, as well as redirecting the user to a page with the correct language that was selected by the user, if they are of course authorized. That is, if the user has set the German language for himself, then when going to the site via an English link, the site will automatically redirect the user to the page with the German language.

To do this, we need to add a language code field to the user model, I hope that everyone is already using their user model in Django instead of the default one.
Rewrite the standard Django language setup function, and also add a Middleware that will process the urls requested from the site.

Among other things, this functionality will be useful in order to generate letters with the correct language for registered users.

This article is based on Django 4 and may not be suitable for older versions of Django.

Set up the user model

Let's add the language field to the user model, in which the code of the selected language will be added, by default it will be the language that is the main language for your site.

Файл yourapp/yourauthapp/models.py

# -*- coding: utf-8 -*-

from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.db import models



class Group(DjangoGroup):
    class Meta:
        proxy = True


class User(AbstractUser):
    language = models.CharField(max_length=10,
                                choices=settings.LANGUAGES,
                                default=settings.LANGUAGE_CODE)

Accordingly, we will create a migration and execute it.

python manage.py makemigrations
python manage.py migrate

Add a view to set the language

Файл yourapp/yourauthapp/views.py

There are two important points here:

  • The original function is to use a form and send a POST message. I prefer the link with the language code.
  • In case the user is authorized,
# -*- coding: utf-8 -*-

from django.conf import settings
from django.http import HttpResponseRedirect, HttpResponse
from django.urls import translate_url
from django.utils.http import url_has_allowed_host_and_scheme
from django.utils.translation import check_for_language


def set_language(request, lang_code):

    next_url = request.POST.get('next', request.GET.get('next'))
    if (
        (next_url or request.accepts('text/html')) and
        not url_has_allowed_host_and_scheme(
            url=next_url,
            allowed_hosts={request.get_host()},
            require_https=request.is_secure(),
        )
    ):
        next_url = request.META.get('HTTP_REFERER')
        if not url_has_allowed_host_and_scheme(
            url=next_url,
            allowed_hosts={request.get_host()},
            require_https=request.is_secure(),
        ):
            next_url = '/'
    response = HttpResponseRedirect(next_url) if next_url else HttpResponse(status=204)

    if request.method == 'GET': # Change method from POST to GET, we want use url parameters for this funcionality

        if lang_code and check_for_language(lang_code):
            if next_url:
                next_trans = translate_url(next_url, lang_code)
                if next_trans != next_url:
                    response = HttpResponseRedirect(next_trans)
            response.set_cookie(
                settings.LANGUAGE_COOKIE_NAME, lang_code,
                max_age=settings.LANGUAGE_COOKIE_AGE,
                path=settings.LANGUAGE_COOKIE_PATH,
                domain=settings.LANGUAGE_COOKIE_DOMAIN,
                secure=settings.LANGUAGE_COOKIE_SECURE,
                httponly=settings.LANGUAGE_COOKIE_HTTPONLY,
                samesite=settings.LANGUAGE_COOKIE_SAMESITE,
            )

            # Important part of code, set language to user, if user is authenticated
            if request.user.is_authenticated:
                request.user.language = lang_code
                request.user.save(update_fields=['language'])

    return response

Include set_language in your main urls.py file

Now you need to connect the view so that you can generate links for switching the language in templates.

# -*- coding: utf-8 -*-

from django.urls import path

from yourauthapp import views


urlpatterns = [
    path('lang/<str:lang_code>/', views.set_language, name='lang'),
    ...
]

Generation of links in the template

Note that I add ?next={{ request.path }} to the link to get the correct redirect to the original page where the user chose to switch the language.

{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
    <a href="{% url 'lang' language.code %}?next={{ request.path }}">{{ language.name_local }}</a>
{% endfor %}

yourapp/yourauthapp/middleware.py

And now let's write a middleware that will automatically redirect the user to a page with the appropriate language.

# -*- coding: utf-8 -*-

from django.http import HttpResponseRedirect
from django.urls import translate_url
from django.utils import translation
from django.utils.deprecation import MiddlewareMixin


class LocaleMiddleware(MiddlewareMixin):

    def process_response(self, request, response):
        user = getattr(request, 'user', None)
        if not user:
            return response

        if not user.is_authenticated:
            return response

        user_language = getattr(user, 'language', None)
        if not user_language:
            return response

        next_trans = translate_url(request.path, user_language)
        if next_trans != request.path:
            translation.activate(user_language)
            response = HttpResponseRedirect(next_trans)

        return response

It remains only to enable middleware in the site settings and everything will work.

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',

    # add your middleware for redirect user
    'yourauthapp.middleware.LocaleMiddleware',
]

Conclusion

Now all authorized users will always be redirected to pages with the language they have chosen.

Of course, for unauthorized users this will not work, but at least they will always be able to choose the language they want from those available on your site.

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
- company blog

Добрый день.

Помимо прочего, данный функционал будет полезен для того, чтобы формировать письма с правильным языком для зарегистрированных пользователей.

Уведомление об этой статье на почту мне пришло почему-то на английском.

Добрый день!
Потому что на этом сайте это не сделано :)
Я сейчас работаю над вторым проектом и делаю работу над ошибками :)
Позже буду ремонтировать и здесь, нужно ещё на более новую версию Django мигрировать.

Будет интересно посмотреть ваш новый проект, Евгений. Уж как никак, но ваши статьи самые лучшие и подходят на уровень детального создания, ведь по вашим статьям я делал много для своего проекта. Надеюсь у вас будут перспективы создать инструкции с новыми вашими познаниями и новым кодом :)

Благодарю за отзыв. Да, я понемногу буду писать статьи с информацией из нового проекта.
А сам проект позже анонсирую, также повешаю в сайдбаре анонсовый виджет.

Буду ждать, Евгений! Потому что буду разрабатывать новый проект, как альманах программиста новичка.)

Можно пояснительную записку настроек. Что примерно указывается

                path=settings.LANGUAGE_COOKIE_PATH,
                domain=settings.LANGUAGE_COOKIE_DOMAIN,
                secure=settings.LANGUAGE_COOKIE_SECURE,
                httponly=settings.LANGUAGE_COOKIE_HTTPONLY,
                samesite=settings.LANGUAGE_COOKIE_SAMESITE,

Это всё настройки для языка в Django, по умолчанию ничего менять не нужно.
А сам этот кусок кода скопирован из оригинальной функции.

Подробнее написано в официальной документации Django settings .
Там написаны и значения по умолчанию.

Я как так сказать новичёк в Python и Django в целом. Читал документацию и вот по этому мне показалось сразу что это оттуда. Немного маштабируемо по своему усмотрению. Однако все настройки из settings возможно индивидуальны. Это как я понимаю те настройки что я делаю сам.

Да, вы можете в своём settings файле определить все эти переменные и значения по умолчанию будут переписаны.

Comments

Only authorized users can post comments.
Please, Log in or Sign up
Fornex

Let me recommend you a great European Fornex hosting.

Fornex has proven itself to be a stable host over the years.

For Django projects I recommend VPS hosting

Following the link you will receive a 5% discount on shared hosting services, dedicated servers, VPS and VPN

View Hosting
JS

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:50points,
  • Rating points-4
V

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:50points,
  • Rating points-4
DK

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:20points,
  • Rating points-10
Popular publications in the last 90 Days
Last comments

Qt/C++ - Lesson 005. QSqlRelationalTableModel - The work with relational tables

Хочу поделится, мы сделали свой вариант QSqlRelationalTableModel и заодно к нему новое развитие QTableView, и получилась готовая таблица PblTableDlg, у которой реализованы внешние связи, комбобо…
S

Qt WinAPI - Lesson 004. QtIFW - Automation WinDeployQt and build installers with Qt Installer Framework

Hello Evgenij, regarding the online installer, I've tried many times to use web host for the created repo after repogen step. I tried using github but I found people talking it is not …
  • juvf
  • Jan. 16, 2023, 10:18 p.m.

Qt/C++ - Lesson 051. QMediaPlayer – simple audio player

PS. Почти дописал плеер на QML. Уперся в ограничения QML. Переписываю плеер на с++/qt, а графика останится в qml. Нашел то, что мне надо, а именно индикатор звука. Qt может перехватывать аудиопо…

Qt/C++ - Lesson 039. How to paint stroke in QSqlTableModel by value in the column?

В этом случае вижу только какой-нибудь костыль в стиле перебора по всем индексам в заголовке с помощью методу headerData . То есть пройтись в for цикле пока не будет совпадения н…
a
  • avt
  • Dec. 12, 2022, 9:06 a.m.

Qt/C++ - Lesson 039. How to paint stroke in QSqlTableModel by value in the column?

Спасибо за ответ. Нет, дело не в читаемости кода, в разных таблицах у меня есть столбцы с одинаковым именем, но с разными индексами. Хотел сделать решение по имени столбца для всех таблиц сразу.…
Now discuss on the forum

django rest framework лишние символы

Покажите код сериализатора вашего.

Здравствуйте помогите с qml

нужно высчитывать координаты того, что должно двигаться, полагаю, что тот маленький круг, и в случае выхода за пределы круга менять переменную типа bool на true/false, которая в свою очередь буд…
  • BlinCT
  • Jan. 30, 2023, 11:59 a.m.

Обращение к сигналу из qml который реализован в другом потоке

Хотя есть мысль что я не правильно создаю реакцию на данный сигнал. Но вроде как правильно все.
VA

Как добавить виртуальную клавиатура с Т9 в своей проект на QML.

Добрый день. Прошу помочь, пишу небольше приложение в Qt. Добвил в свой проект виртуальную клавиатуру от Qt. Но как добавить в него возможность изменения Т9 никак не могу понять.
P
About
Services
© EVILEG 2015-2022
Recommend hosting TIMEWEB