Evgenii Legotckoi
Маусым 1, 2022, 2:30 Т.Қ.

Django - Сабақ 059. Таңдалған тілді пайдаланушы параметрлерінде сақтау

Бұл мақалада мен пайдаланушы сайттағы тілдер арасында ауыса алатындай етіп сайтта сілтеме жасаудың мысалын көрсеткім келеді.

Бірақ мен бұл функцияның жетілдірілген нұсқасын көрсетемін, атап айтқанда таңдалған тілді пайдаланушы кестесінде сақтау, сондай-ақ пайдаланушыны пайдаланушы таңдаған дұрыс тілі бар бетке қайта бағыттау, егер олар әрине рұқсат етілген болса. Яғни, егер пайдаланушы неміс тілін өзі үшін орнатқан болса, онда ағылшын тіліндегі сілтеме арқылы сайтқа кіргенде, сайт пайдаланушыны неміс тілі бар бетке автоматты түрде қайта бағыттайды.

Ол үшін пайдаланушы үлгісіне тіл коды өрісін қосу керек, әркім әдепкі емес Django-да өзінің пайдаланушы үлгісін пайдаланып жатыр деп үміттенемін.
Стандартты Django тілін орнату функциясын қайта жазыңыз, сондай-ақ тораптан сұралған URL мекенжайларын өңдейтін орта бағдарламалық құралды қосыңыз.

Басқа нәрселермен қатар, бұл функция тіркелген пайдаланушылар үшін дұрыс тілде әріптер жасау үшін пайдалы болады.

Бұл мақала Django 4 нұсқасына негізделген және Django ескі нұсқаларына сәйкес келмеуі мүмкін.

Пайдаланушы үлгісін орнату

Таңдалған тілдің коды қосылатын пайдаланушы үлгісіне тіл өрісін қосамыз, әдепкі бойынша ол сіздің сайтыңыздың негізгі тілі болып табылатын тіл болады.

Файл 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)

Тиісінше, біз көші-қонды жасап, оны орындаймыз.

python manage.py makemigrations
python manage.py migrate

Тілді орнату үшін көрініс қосыңыз

Файл yourapp/yorauthapp/views.py

Мұнда екі маңызды тармақ бар:

  • Бастапқы функция пішінді пайдалану және POST хабарламасын жіберу болып табылады. Мен тіл коды бар сілтемені қалаймын.
  • Пайдаланушы рұқсат етілген жағдайда,
# -*- 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

Негізгі urls.py файлыңызға set_language қосыңыз

Енді үлгілердегі тілді ауыстыруға арналған сілтемелерді жасау үшін көріністі қосу керек.

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

from django.urls import path

from yourauthapp import views


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

Үлгідегі сілтемелерді құру

Пайдаланушы тілді ауыстыруды таңдаған бастапқы бетке дұрыс бағыттауды алу үшін сілтемеге ?next={{ request.path }} қосатынымды ескеріңіз.

{% 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 %}

қолданбаңыз/yourauthapp/middleware.py

Ал енді пайдаланушыны автоматты түрде сәйкес тілі бар бетке қайта бағыттайтын аралық бағдарламаны жазайық.

# -*- 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

Бұл сайт параметрлерінде аралық бағдарламаны қосу үшін ғана қалады және бәрі жұмыс істейді.

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',
]

Қорытынды

Енді барлық рұқсат етілген пайдаланушылар әрқашан таңдаған тілі бар беттерге қайта бағытталады.

Әрине, рұқсат етілмеген пайдаланушылар үшін бұл жұмыс істемейді, бірақ кем дегенде олар әрқашан сіздің сайтыңызда қол жетімді тілдің ішінен өздері қалаған тілді таңдай алады.

Мақала бойынша сұралады0сұрақтар(лар)

6

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

IscanderChe
  • Маусым 1, 2022, 2:54 Т.Қ.

Добрый день.

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

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

Evgenii Legotckoi
  • Маусым 1, 2022, 3:57 Т.Қ.
  • (өңделген)

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

Владислав Меленчук
  • Маусым 4, 2022, 1:42 Т.Қ.

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

Evgenii Legotckoi
  • Маусым 4, 2022, 5:07 Т.Қ.

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

Владислав Меленчук
  • Маусым 5, 2022, 12:56 Т.Қ.

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

NSProject
  • Маусым 5, 2022, 4:47 Т.Қ.

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

                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,
Evgenii Legotckoi
  • Маусым 6, 2022, 4:18 Т.Қ.

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

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

NSProject
  • Маусым 6, 2022, 8:57 Т.Қ.

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

Evgenii Legotckoi
  • Маусым 7, 2022, 1:06 Т.Қ.

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

c
  • Жел. 2, 2023, 4:34 Т.Ж.

It tries to do language translation in API views. That's why it sends or receives the same API request twice. Do you have any suggestions on this? Example: stripe webhook.

"GET /warehouse/webhook/ HTTP/1.1" 302
"GET /en/warehouse/webhook/ HTTP/1.1" 200

Evgenii Legotckoi
  • Жел. 3, 2023, 7:39 Т.Қ.

It is redirect from untranslated url to translated url. It is normal behavior for mutlilanguage web site based on the Django.

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз