Продовжуючи розробку сайту, хочу поділитися прикладом коду додавання контактної форми на сайті на Django . Вже були статті з різними формами, наприклад, для додавання коментарів, але якщо говоримо про весь процес загалом, то й не обходимо цю тему стороною.
Тим більше, що для сайту на Wordpress це було для мене хворою темою. Напевно, всьому виною була лінь, бо в мене так і не виникло бажання почати розбиратися з PHP, щоб накидати контактну форму самостійно (в результаті був задіяний черговий плагін).
А якщо врахувати, що розробка на Django , передбачає досить часту роботу з різними формами даних і є модуль для роботи з поштовими сервісами, то і додавання подібної форми не становить особливих труднощів.
Налаштування settings.py, urls.py, home/urls.py
Перше, що зробимо, це налаштуємо конфігураційний файл, оскільки в ньому необхідно буде вказати дані для підключення до поштової скриньки з якого буде надсилатися лист із вмістом з контактної форми.
EMAIL_HOST = 'smtp.example.com' # Сервер для отправки сообщений EMAIL_HOST_USER = 'info@example.com' # имя пользователя EMAIL_HOST_PASSWORD = 'password123' # пароль от ящика EMAIL_PORT = 2525 # порт для подключения EMAIL_USE_TLS = True # использование протокола шифрования DEFAULT_FROM_EMAIL = 'info@example.com' # email, с которого будет отправлено письмо
Також в даному файлі необхідно вказати ту програму, яка відповідатиме за контактну форму. У моєму випадку це додаток home, який відповідає за сторінки, що рідко змінюються, наприклад, сторінку з контактною формою. А також модуль, що використовується на сайті django-bootstrap3
INSTALLED_APPS = [ ... 'home.apps.HomeConfig', 'bootstrap3', ... ]
Природно, в основному файлі urls.py вказаний шаблон, за яким в цю програму надсилається запит.
urlpatterns = [ url(r'^', include('home.urls')), ]
Що стосується шаблону url для програми home , то він виглядатиме так:
from django.conf.urls import url from . import views app_name = 'home' urlpatterns = [ ... url(r'^contacts/$', views.EContactsView.as_view(), name='contacts'), ... ]
Контактна форма
У контактній формі присутні три поля:
- Ім'я - користувач обов'язково має представитися;
- email – користувач повинен вказати свою електронну пошту, щоб була можливість йому відповісти;
- Повідомлення - саме повідомлення, яке користувач бажає надіслати.
Усі поля будуть обов'язковими. При цьому перевірка коректності введення електронної пошти буде здійснюватися ще в браузері користувача.
# -*- coding: utf-8 -*- from django import forms class ContactForm(forms.Form): name = forms.CharField( label="Имя", widget=forms.TextInput ) email = forms.EmailField( widget=forms.EmailInput ) message = forms.CharField( label="Сообщение", widget=forms.Textarea )
Подання
А тепер напишемо уявлення, яке відповідатиме за обробку повідомлення та відображення сторінки з контактною формою.
from django.shortcuts import render_to_response, reverse from django.views import View from django.core.mail import send_mail from .forms import ContactForm from project import settings class EContactsView(View): template_name = 'home/contacts.html' # В случае get запроса, мы будем отправлять просто страницу с контактной формой def get(self, request, *args, **kwargs): context = {} context.update(csrf(request)) # Обязательно добавьте в шаблон защитный токен context['contact_form'] = ContactForm() return render_to_response(template_name=self.template_name, context=context) def post(self, request, *args, **kwargs): context = {} form = ContactForm(request.POST) # Если не выполнить проверку на правильность ввода данных, # то не сможем забрать эти данные из формы... хотя что здесь проверять? if form.is_valid(): email_subject = 'EVILEG :: Сообщение через контактную форму ' email_body = "С сайта отправлено новое сообщение\n\n" \ "Имя отправителя: %s \n" \ "E-mail отправителя: %s \n\n" \ "Сообщение: \n" \ "%s " % \ (form.cleaned_data['name'], form.cleaned_data['email'], form.cleaned_data['message']) # и отправляем сообщение send_mail(email_subject, email_body, settings.EMAIL_HOST_USER, ['target_email@example.com'], fail_silently=False) return render_to_response(template_name=self.template_name, context=context)
Тут є один ключовий момент щодо відображення сторінки для користувача. Якщо користувач надіслав листа, йому необхідно повідомити, що лист був надісланий. Для цього ми просто не поміщатимемо в контекст контактну форму і в шаблоні зробимо перевірку на її наявність, щоб відобразити коректну інформацію користувачеві.
Шаблон контактної форми
В контактній формі обов'язково необхідно вказати {% csrf_token %}, який захищатиме ваш сайт від атак через контактну форму. А також не забудьте підвантажити модуль bootsrtap3, який дозволить створити коректніший і красивіший вид сторінки.
Для використання контактної форми з модулем bootstrap3 необхідно лише вказати відповідний шаблонний тег і передати в нього нашу контактну форму. Звертаю вашу увагу також на те, що, залежно від наявності контактної форми, буде виведено різний зовнішній вигляд сторінки.
{% extends 'home/base.html' %}{% load bootstrap3 %} {% block title %}Контакты{% endblock %} {% block page %} <h1>Контакты</h1> <article> {% if contact_form %} <p>Добро пожаловать на сайт.</p> <p>Если у Вас есть пожелания или предложения по улучшению сайта, либо Вы желаете предложить статью к публикации на сайте, то Вы можете сделать это, воспользовавшись контактной формой:</p> <form id="contact_form" action="{% url 'home:contacts' %}" method="post"> {% csrf_token %} {% bootstrap_form contact_form %} {% buttons %} <button type="submit" class="btn btn-primary">{% bootstrap_icon "send" %} Отправить</button> {% endbuttons %} </form> {% else %} <p>Сообщение отправлено</p> {% endif %} </article> {% endblock %}
Для Django рекомендую VDS-сервер хостера Timeweb .
Код контактної форми буде розміщено у файлі forms.py.
Не полноценное решение, сильно вырвано из контекста.
Здавствуйте! обязательно ли форма в django должна быть привязана к модели? конкретно в этом случаи
Добрый день. Конкретно в этом случае модель не привязана к форме вообще потому, что здесь модель не используется. Вы можете использовать модель, чтобы дополнительно сохранять сообщения в базе данных сайта.
Добрый день,
не могу отправить загруженный файл, подскажите что нужно еще добавить.
Спасибо.
Добрый день.
Потому, что нужно не добавлять ссылку (или что там у вас в итоге получается) на файл и прикреплять его к письму.
Если не ошибаюсь, то для отправки письма с файлом нужно использовать класс EmailMessage
Могут быть некоторые разночтения в синтаксисе, в зависимости от версий Django
Добрый день, в итоге получилось как-то так, отправляет форму с файлом.
Спасибо.
Добрый день,
при отправки письма с файлом, выбираю несколько файлов, пишет выбранное количество файлов, а отправляет только один, весь код см.выше, добавил только в форму возможность выбора нескольких файлов. Подскажите,что нужно еще добавить, чтобы можно было отправить сразу несколько файлов.
Спасибо.
Думаю, что как-то так, возможно неправильно написание имени метода getlist, но выглядеть должно так
Спасибо, Евгений.
Все заработало.
Timeweb так себе провайдер.
Поддержка не отвечает. И smtp не отправляет письма.
Все перепробовал ничего найти не могу.
1. Ошибка sock.connect(sa) TimeoutError: [Errno 110] Connection timed out
2. Ошибка OSError: [Errno 101] Network is unreachable