Опубликован: 25.01.2016 | Уровень: для всех | Доступ: платный | ВУЗ: Российский Новый Университет
Лекция 9:

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

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

Цель лекции: Создать модель данных приглашения и реализовать ее; создание страницы отправки приглашения; ознакомиться с системой интернационализации; научиться работать с системой кэширования.

Ключевые термины: интернационализация, проект, электронная почта, кэширование, память, файл, Django, модель, класс, язык, перевод, строка, тестирование, получатель, отправитель

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

Отправка приглашения друзьям по электронной почте

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

Для построения функции требуются следующие компоненты:

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

В этом разделе мы осуществим каждый из этих компонентов. Но, поскольку этот раздел включает в себя отправку сообщений электронной почты, нам сначала нужно настроить Django для отправки электронной почты, добавив некоторые параметры в файл settings.py.Таким образом, откройте settings.py и добавьте следующие строки:

SITE_HOST="127.0.0.1:8000" 
DEFAULT_FROM_EMAIL='MyTwitter<noreply@mytwitter.com>'
</noreply@mytwitter.com>
EMAIL_HOST = "mail.yourisp.com"
EMAIL_PORT = ''
EMAIL_HOST_USER = ' usemame+mail.yourisp.com'
EMAIL_HOST_PASSWORD = ''

Давайте посмотрим, что делает каждая переменная в предыдущем коде:

  • SITE_HOST: Это имя вашего сервера. Оставьте его пока как 127.0.0.l: 8000.Когда мы развернем наш сервер в следующей главе, мы изменим его.
  • DEFAULT_FROM_EMAIL: Это адрес электронной почты, который появляется в поле From для исходящего почтового сервера. Для пользователя хоста введите свое имя плюс ваш почтовый сервер, как показано в предыдущем образце кода. Оставьте это поле пустым, если ваш провайдер не требует этого.
  • DEFAULT_FROM_EMAIL: Это адрес электронной почты, который появляется в поле From для исходящего почтового сервера. Для пользователя хоста введите свое имя плюс ваш почтовый сервер, как показано в предыдущем образце кода. Оставьте это поле пустым, если ваш провайдер не требует этого.
  • EMAIL_PORT: Это номер порта сервера электронной почты.Если вы оставите его пустым, будет использоваться значение по умолчанию (25).Вам также нужно получить его от вашего провайдера.
  • EMAIL_HOST_USER И EMAIL_HOST_PASSWORD: Это имя пользователя и пароль, для электронной почты,отправленной Django.

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

Чтобы проверить правильность настройки, запустите интерактивную оболочку и введите следующее:

>>> from django.core.mail import EmailMessage
>>>email=EmailMessage('Hello','World',to=['your_email@example.com']) 
>>> email.send()

Замените параметр your_email@example.com вашим адресом электронной почты. Если предшествующий вызов для отправки почты не вызывает исключение и вы получите сообщение электронной почты, то все устанавливается в противном случае, вам необходимо проверить настройки с вашим провайдером и повторить попытку.

Но, что делать, если вы не получите какую-либо информацию от провайдера? Мы можем попробовать пойти альтернативным путем: использовать Gmail для отправки почты (конечно, не от noreply@mytweet.example.com, но от реальной электронной почты ).Давайте посмотрим на изменения, которые вам придется сделать в файле settings.py проекта MyTweeets для этого.

Удалите предыдущие записи файла settings.py целиком и добавьте следующее:

EMAIL_USE_TLS = True 
EMAIL_HOST = ‘smtp.gmail.com'
EMAIL_HOST_USER = ' ID вашей электронной почты gmail’
EMAIL_HOST_PASSWORD = "gmail пароль"
EMAIL_PORT = 587 
SITE_HOST = "127.0.0.1:8000"

Если вы получаете ошибку, такую как:

(534,'5.7.9 Application-specific password required. Learn more at\
n5.7.9 http://support.google.com/accounts/bin/answer.py?answer=185833 zr2sm8629305pbb.83 - gsmtp') 

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

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

>>> from django.core.mail import EmailMessage
>>>email=EmailMessage(1Hello1,'World', to=[1your_email@example.com']) 
>>> email.send()

Здесь параметр your_email@example.com является любым адресом электронной почты, на который вы хотите отправить почту. Адрес электронной почты будет адресом электронной почты Gmail, который мы указали после переменной:

EMAIL_HOST_USER = ' ID вашей электронной почты gmail’

Теперь, после того как параметры заданы правильно, отправка электронной почты в Django лишь кусок пирога! Мы будем использовать функцию EmailMessage чтобы отправить приглашение, но сперва, давайте создадим модель данных для сохранения приглашения.

Модель данных приглашения

Приглашение состоит из следующих данных:

  1. Имя получателя
  2. Адрес электронной почты получателя
  3. Объект пользователя отправителя

Нам также необходимо хранить код активации для приглашения. Этот код будет отправлен с приглашением по электронной почте. Код будет выполнять две цели:

  • Прежде чем принять приглашение, мы можем использовать код для проверки, что приглашение действительно существует в базе данных
  • После принятия приглашения, мы можем использовать код, чтобы получить сведения о приглашении из базы данных и отследить отношения между отправителем и получателем

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

class Invitation(models.Model):
    email = models.EmailField(unique=True)
    code = models.CharField(max_length=100)
    sender = models.ForeignKey(User)

    def __unicode__(self):
        return '%s, %s' % (self.sender.username, self.email)

Здесь не должно быть ничего нового или трудного для понимания этой модели. Просто мы определили поля для имени получателя, адреса электронной почты получателя, кода активации иотправителя приглашения. Мы также создали метод __unicode__ для отладки и разрешили модель в интерфейсе администрирования.Не забудьте выполнить команду python manage.py syncdb для создания новой модели таблицы в базе данных.

Мы также создадим форму приглашения для этого. Создайте файл с именем forms.py в каталоге user_profile и обновите его следующим кодом:

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

Создание страницы просмотра откуда будут направляться приглашения аналогично созданию других страниц, которые мы создали для поиска и формs твита, которую мы сделаем, создав новый файл под названием template/invite. html:

{% extends "base.html" %}
{% load staticfiles %}

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

URL-запись для этого будет следующей :

url(r'^invite/$', Invite.as_view()),

Теперь нам нужно создать методы get() и post(), чтобы отправить приглашение с помощью этой формы.

Так как отправка электронной почты более характерна для пользователя, чем твиты, мы создадим этот метод в user_profile, в противовес представлению tweets, которjt мы использовали ранее.

Обновите файл user_profile/views.py следующим кодом:

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

Здесь метод get () так же прост, как и отображениефайла invite.html с формой приглашения в качестве параметра, флагом success и переменной email первоначально не заданной.

Метод post() обычная форма проверки и концепция извлечения переменной; код, который вы увидите в первый раз выглядит следующим образом:

invite_code = Invite.generate_invite_code(email)

Это на самом деле вызов статической функции, создающий токен активации с уникальным ключом для каждого приглашенного пользователя. Метод render_to_string работает , когда вы загружаете шаблон под названием _invite_email_template.html и ему нужно передать следующие переменные:

  • sender_name: это имя лица, который пригласил вас или отправителя электронной почты
  • sender_email: это адрес электронной почты отправителя
  • email: это адрес электронной почты человека, который был приглашен
  • link: это ссылка принятия приглашения

Шаблон будет потом использоваться для отображения тела приглашения по электронной почте. После этого мы используем метод EmailMultiAlternatives для отправки письма, как мы делали во время интерактивного сеанса в предыдущем разделе.

Есть несколько замечаний, которые нужно здесь сделать:

  • Форматом ссылки активации является http: //SlTE_HOST/invite/accept/ code /.Мы мы напишем представление, чтобы обрабатывать такие URL-адреса в этом разделе.
  • В первый раз мы используем шаблон для отображения чего-то, отличного от веб-страницы.Как вы можете видеть, система шаблонов является достаточно гибкой и позволяет нам строить письма, а также веб-страницу или любой другой текст по этому вопросу.
  • Мы использовали методы render_to_string() и render() для построения тела сообщения в отличие от обычных вызовов render_to_response.Если вы помните, это ранее в этой книге это использовалось для отображения шаблонов.Мы делаем это здесь, потому что мы не отображаем веб-страницы.

Поскольку метод send() загружает шаблон под названием _invite_email_template.html, создайте файл с этим именем в каталоге templates и вставьте следующее содержимое:

Привет
{{sender_name}} ({{sender_email}}) приглашает вас присоединиться к Mytweet.
Присоединитtcm, пожалуйста, нажав по ссылке{{link}}.
Это письмо было отправлено на {{email}}. Если вы считаете, оно послано ошибочно, пожалуйста, проигнорируйте.

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

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

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

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

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

Дмитрий Молокоедов
Дмитрий Молокоедов
Россия, Новосибирск, НГПУ, 2009
Акбар Ахвердов
Акбар Ахвердов
Россия, г. Москва