Российский Новый Университет
Опубликован: 25.01.2016 | Доступ: свободный | Студентов: 2235 / 161 | Длительность: 16:40:00
Лекция 9:

Расширение и развертывание

< Лекция 8 || Лекция 9: 1234 || Лекция 10 >

Обработка ссылки активации

Мы добились хорошего прогресса; Пользователи теперь имеют возможность отправлять приглашения своим друзьям по электронной почте. Следующий шаг заключается в создании механизма, который обрабатывает ссылку активации в приглашениях. Вот краткое изложение того, что мы собираемся делать.

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

Давайте начнем с записи URL для представления. Откройте файл urls.py и добавьте выделенную строку к нему:

url(r'^invite/accept/(\w+)/$', InviteAccept.as_view()),

Создайте класс с именем InviteAccept() в файле user_profile/views.py.Создайте класс с именем InviteAccept() в файле user_profile/views.py.

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

Ради простоты мы перенаправим пользователя к странице регистрации с помощью кода активации, так, что когда он зарегистрируется, он автоматически становятся подписчиком.

Рассмотрим следующий код:

class InviteAccept(View):
    def get(self, request, code):
        return HttpResponseRedirect('/register?code='+code)

Затем мы напишем страницу регистрации с помощью следующего кода:

class Register(View):
    def get(self, request):
        params = dict()
        registration_form = RegisterForm()
        code = request.GET.get('code')
        params['code'] = code
        params['register'] = registration_form
        return render(request, 'registration/register.html', params)
        pass

    def post(self, request):
        form = RegisterForm(request.POST)
        if form.is_valid():
            print("HI")
            username = form.cleaned_data['username']
            email = form.cleaned_data['email']
            password = form.cleaned_data['password']
            try:
                print("Already registered")
            except:
                user = User()
                user.username = username
                user.email = email
                commit = True
                user = super(user, self).save(commit=False)
                user.set_password(password)
                if commit:
                    user.save()

Как вы можете видеть, представление соответствует формату URL-адреса, послал по электронной почте приглашение. Код активации захватывается из URL-адреса, используя регулярное выражение и затем, передается в виде параметра.

Это заняло немного времени, но мы смогли найти хорошее применение нашим знаниям Django ддя имплементации этого.Вы можете теперь нажать на ссылку приглашения, что вы получили по электронной почте, чтобы увидеть, что происходит. Вы будете перенаправлены на страницу регистрации; можно создать новый аккаунт там, войти и обратите внимание, как новая учетная запись и ваша исходная запись, стал подписчиками отправителя.

Интернационализация (i18n) - предложение сайта на нескольких языках

Люди не будут использовать наше приложение, если они не могут читать его страницы. Пока мы занимались только с англоговорящими пользователями. Однако есть люди во всем мире, которые не знают английского языка или предпочитают использовать затем родной язык. Чтобы привлечь этих людей, было бы неплохо предложить интерфейс нашего приложения на нескольких языках. Это позволит преодолеть языковой барьер и открыть новые горизонты для нашего приложения, особенно в регионах, где английский язык не является распространенным

Как вы уже догадались, Django предоставляет все компоненты, необходимые для перевода проекта на несколько языков .Система, которая отвечает за предоставление этой возможности называется функцией интернационализации (il8n). Процесс перевода проекта Django довольно прост.

Вы выполните следующие три действия:

  1. Задать, какие строки должны быть переведены в приложении — например, состояние и сообщения об ошибках могут быть переведены, тогда как имена не требуют перевода.
  2. Создайте файл перевода для каждого языка, который вы хотите поддерживать.
  3. Включить и настроить систему ilSn

Мы рассмотрим каждый шаг подробно в следующих подразделах. В конце раздела этой главы наше приложение будет поддерживать несколько языков, и вы сможете перевести любой другой проект Django с легкостью.

Маркировка строк как переводимых

Первый шаг в переводе приложения - указать Django, какие строки должны быть переведены. Вообще говоря строки, которые являются частью представления и шаблона должны быть переведены, в то время как строки, которые вводятся пользователем не требуется переводить.Маркировка строк как переводимых делается с помощью вызова функции. От имени функции и от того, как она называется, зависит, где находится строка: в представлении, шаблоне, модели или форме.

Этот шаг гораздо проще, , чем первоначально выглядит. Давайте узнаем об этом на примере .Мы переведем функциональную возможность"приглашение подписчика" ф в нашем приложении. Процесс перевода остальной части приложения будет точно таким же. Откройте файл user_profile/view.py и сделать подсвеченные изменения в представление:

 from django.utils.translation import ugettext as __
from django.views.generic import View
from django.conf import settings
from django.shortcuts import render
from django.template import Context

from django.template.loader import render_to_string
from user_profile.forms import InvitationForm, RegisterForm
from django.core.mail import EmailMultiAlternatives
from user_profile.models import Invitation, User
from django.http import HttpResponseRedirect
import hashlib
class Invite(View):
    def get(self, request):
        params = dict()
        success = request.GET.get('success')
        email = request.GET.get('email')
        invite = InvitationForm()
        params["invite"] = invite
        params["success"] = success
        params["email"] = email
        return render(request, 'invite.html', params)

    def post(self, request):
        global invitation
        form = InvitationForm(self.request.POST)
        if form.is_valid():
            email = form.cleaned_data['email']
            subject = 'Invitation to join MyTweet App'
            sender_name = request.user.username
            sender_email = request.user.email
            invite_code = Invite.generate_invite_code(email)
            link = 'http://%s/invite/accept/%s/' % (settings.SITE_HOST, invite_code)
            context = Context({"sender_name": sender_name, "sender_email": sender_email, "email": email, "link": link})
            invite_email_template = render_to_string('partials/_invite_email_template.html', context)
            msg = EmailMultiAlternatives(subject, invite_email_template, settings.EMAIL_HOST_USER, [email], cc=[settings.EMAIL_HOST_USER])
            user = User.objects.get(username=request.user.username)
            invitation = Invitation()
            invitation.email = email
            invitation.code = invite_code
            invitation.sender = user
            invitation.save()
            success = msg.send()
        return HttpResponseRedirect('/invite?success='+str(success)+'&email='+email)

    @staticmethod
  
 def generate_invite_code(email):
        secret = settings.SECRET_KEY
        if isinstance(email, unicode):
            email = email.encode('utf-8')
        activation_key = hashlib.sha1(secret+email).hexdigest()
        return activation_key

Заметьте, что строка субъекта начинается с символа "_"; альтернативно, вы могли написать так:

from django.utils.translation import ugettext
subject = ugettext'Invitation to join MyTweet App'

В любом случае, это отлично работает.

Как вы можете видеть, изменения минимальны:

  • Мы импортировали функцию под названием ugettext из django.utils.translation.
  • Мы использовали ключевое слово as, чтобы назначить более короткое имя функции (символ подчеркивания). Мы сделали это, потому что эта функция будет использоваться для обозначения строки как переводимой в представлениях, и так как это является весьма распространенной задачей, дать функции более короткое имя – хорошая идея.
  • Мы пометили строку как переводимую просто передав ее функции __.

Это было довольно просто, не так ли? Однако, давайте немного посмотрим, что нам нужно сделать здесь. Первое сообщение использует строку форматирования, и мы применяем оператор % после вызова функции _ (). Это необходимо, чтобы избежать перевода адреса электронной почты. Также предпочтительнее использовать именованные форматы, которые дают вам больший контроль, пока вы оставляете фактический перевод на потом. Таким образом вы можете определить следующий код:

message= \
_('An invitation was sent to %(email)s.') % {
'email': invitation.email}

Теперь, когда мы знаем, как пометить строки как переводимые в представлениях, давайте перейдем к шаблонам. Откройте файл invite.html в каталоге templates и измените его следующим образом:

{% extends "base.html" %}
{% load staticfiles %}
{% load i18n %}
{% block content %}
<div class="row clearfix">
        <div class="col-md-6 col-md-offset-3 column">
            {% if success == "1" %}
                <div class="alert alert-success" role="alert">
{ % trans Invitation Email was successfully sent to %} {{ email }}
</div>
            {% endif %}
            {% if success == "0" %}
                <div class="alert alert-danger" role="alert">Failed to send Invitation Email to {{ email }}</div>
            {% endif %}
            <form id="search-form" action="" method="post">{% csrf_token %}
            <div class="input-group input-group-sm">
                    {{ invite.email.errors }}
                    {{ invite.email }}
                  <span class="input-group-btn">
          <button class="btn btn-search" type="submit">Invite</button>
                  </span>
            </div>
          </form>
        </div>
	</div>
{% endblock %}

Здесь, мы разместили параметр{% load i18n %} в начале шаблона, чтобы дать ему доступ к тегам перевода. Тег <load> обычно используется для включения дополнительных тегов шаблона, которые не доступны по умолчанию.Вам нужно поместить его в верхней части каждого шаблона, который использует теги перевода .i18n это сокращение для интернационализации, который является именем фреймворка Django, предоставляющим функции перевода.

Далее мы использовали тег шаблона trans для обозначения строки как переводимой. Этот тег шаблона работает точно так же, как функция gettext в представлениях. Стоит отметить, что тег trans не работает, если строка содержит переменную шаблона.

В этом случае вам будет нужно использовать тег blocktrans:

{% blocktrans %}

Можно передать переменную блока, такую как {{variable}} также внутри блока {% endblocktrans %}, чтобы сделать его более значимым для читателя.

Теперь вы знаете, как бороться с переводимыми строки и в шаблонах. Итак давайте перейдем к формам и моделям. Маркировка строки как переводимой в форме или модели немного отличается от представления. Чтобы узнать, как это делается, откройте файл user_profile/models.py и измените форму приглашения следующим образом:

django.utils.translation gettext_lazy as _


class InvitationForm(forms.Form):
    email = forms.CharField(widget=forms.TextInput(attrs={'size': 32, 'placeholder': _('Email Address of Friend to invite.'), 'class':'form-control'}))

Единственная разница состоит в том, что мы импортировали функцию gettext_lazy вместо gettext. gettext_lazy создает задержку перевода строки, пока возращаемый результат не будет доступен.Здесь это необходимо потому, что атрибуты формы создаются только один раз: когда приложение запущено. Если мы используем функцию gettext, переведенные надписи будут храниться в форме атрибутов, используя язык по умолчанию (обычно английский) и никогда не будут переводиться снова. Однако если мы используем функцию gettext_lazy, функция будет возвращать специальный объект, который будет переводить строку каждый раз, когда осуществляется доступ к нему, и, следовательно, перевод будет сделан правильно. Эта особенность делает функцию gettext_lazy идеально подходящей для атрибутов формы и модели.

На этом мы закончим, маркировку строки вида "пригласить друга" для перевода.

Чтобы помочь вам вспомнить, что охватил этот подраздел ,вот краткий обзор методов, используемых для обозначения переводимых строк:

  • В представлениях, пометка переводимых строк осуществляется с помощью функции, gettext (как правило, импортируется как _)
  • В шаблонах, пометка переводимых строк осуществляется с помощью тега шаблона trans для строк, которые не содержат переменных и тега blocktrans для строк, которые их содержат
  • Для форм и моделей, пометка переводимых строк осуществляется с помощью функции gettext_lazy (как правило, импортируется как _)

Конечно,существуют особые случаи, которые могут быть обработаны отдельно. Например вы можете перевести значения параметров по умолчанию в представлениях, используя функцию gettext_lazy вместо gettext. До тех пор, как вы понимаете разницу между этими двумя функциями, вы в состоянии решить, когда вам нужно это осуществлять.

< Лекция 8 || Лекция 9: 1234 || Лекция 10 >
Константин Боталов
Константин Боталов

Вроде легкие вопросы и ответы знаю правильные, но система считает иначе и правильные ответысчитает неправильными. Приходится выполнть по несколько раз. Это я не правильно делаю или тест так составлен?

Владимир Филипенко
Владимир Филипенко

Листинг показывает в 4-ой лекции, что установлен Django 1.8.4. Тут же далее в этой лекции указаны настройки, которые воспринимает Django 1.7 и младше.