Продолжая разработку сайта, хочу поделиться примером кода по добавлению контактной формы на сайте на 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 - пользователь должен указать свою электронную почту, чтобы была возможность ему ответить;
- Сообщение - непосредственно само сообщение, которое пользователь желает отправить.
Все поля будут обязательными. При этом проверка корректности ввода 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