Evgenii Legotckoi
Evgenii LegotckoiҚаз. 15, 2016, 9:50 Т.Ж.

Джанго - Оқулық 013. Джанго байланыс формасы

Сайтты дамытуды жалғастыра отырып, мен 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, с которого будет отправлено письмо

Сондай-ақ осы файлда сіз байланыс формасына жауап беретін қолданбаны көрсетуіңіз керек. Менің жағдайда, бұл беттерді сирек өзгертуге жауап беретін үй қолданбасы, мысалы, байланыс пішіні бар бет. Сондай-ақ [django-bootstrap3] сайтында қолданылатын модуль (https://evileg.com/en/post/6/)

INSTALLED_APPS = [
    ...
    'home.apps.HomeConfig',
    'bootstrap3',
    ...
]

Әрине, негізгі urls.py файлы осы қолданбаға сұрау жіберілетін үлгіні көрсетеді.

urlpatterns = [
    url(r'^', include('home.urls')),
]

Үй қолданбасының url үлгісіне келетін болсақ, ол келесідей болады:

from django.conf.urls import url

from . import views

app_name = 'home'
urlpatterns = [
    ...
    url(r'^contacts/$', views.EContactsView.as_view(), name='contacts'),
    ...
]

Байланыс формасы

Байланыс пішінінде үш өріс бар:

  1. Аты – пайдаланушы өзін таныстыруы керек;
  2. электрондық пошта – пайдаланушы оған жауап беру үшін өзінің электрондық пошта мекенжайын көрсетуі керек;
  3. Хабарлама – тікелей пайдаланушы жібергісі келетін хабарлама.

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

# -*- 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" %}&nbsp;&nbsp;Отправить</button>
            {% endbuttons %}
        </form>
    {% else %}
        <p>Сообщение отправлено</p>
    {% endif %}
    </article>
{% endblock %}

Django үшін Timeweb хостының VDS сервері ұсынамын.

Байланыс пішінінің коды forms.py файлында орналасады.

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

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

DR
  • Мамыр 31, 2019, 11:12 Т.Ж.
  • (өңделген)

Не полноценное решение, сильно вырвано из контекста.

B
  • Жел. 26, 2019, 1:08 Т.Ж.

Здавствуйте! обязательно ли форма в django должна быть привязана к модели? конкретно в этом случаи

Evgenii Legotckoi
  • Қаң. 6, 2020, 3:16 Т.Ж.

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

S
  • Мамыр 17, 2020, 6:37 Т.Ж.

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

forms:
class ContactForm(forms.Form):

    name = forms.CharField(
        label="Имя",
        widget=forms.TextInput
    )

    email = forms.EmailField(
        widget=forms.EmailInput
    )

    message = forms.CharField(
        label="Сообщение", required=False,
        widget=forms.Textarea
    )
    file = forms.FileField(
        label="Загрузить файл", required=False,
    )

views:
class EContactsView(View):
    template_name = 'main/contacts.html'

    # В случае get запроса, мы будем отправлять просто страницу с контактной формой
    def get(self, request, *args, **kwargs):
        context = {}
        context['contact_form'] = ContactForm()
        return render(request, template_name=self.template_name, context=context)

    def post(self, request, *args, **kwargs):
        context = {}

        form = ContactForm(request.POST, request.FILES)

        # Если не выполнить проверку на правильность ввода данных,
        # то не сможем забрать эти данные из формы... хотя что здесь проверять?
        if form.is_valid():

            email_subject = ':: Сообщение через контактную форму '
            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'], form.cleaned_data['file'])


            # и отправляем сообщение

            send_mail(email_subject, email_body, settings.EMAIL_HOST_USER, ['mymail@gmail.com'], fail_silently=False)

        return render(request, template_name=self.template_name, context=context)

шаблон:

{% extends "layout/basic.html" %}
{% load thumbnail %}
{% load static %}
{% load bootstrap4 %}
{% block title %}Контакты{% endblock %}

{% block content %}
    <h1>Контакты</h1>
    <article>
    {% if contact_form %}
        <p>Добро пожаловать на сайт.</p>
        <p>Если у Вас есть пожелания или предложения по улучшению сайта, либо Вы желаете предложить статью к публикации на сайте, то Вы можете сделать это, воспользовавшись контактной формой:</p>
        <form id="contact_form" action="{% url 'main:contacts' %}" method="post" enctype="multipart/form-data">
            {% csrf_token %}
            {% bootstrap_form contact_form %}

            {% buttons %}
                <button type="submit" class="btn btn-success">&nbsp;&nbsp;Отправить</button>
            {% endbuttons %}
        </form>
    {% else %}
        <p>Сообщение отправлено</p>
    {% endif %}
    </article>
{% endblock %}
Evgenii Legotckoi
  • Мамыр 18, 2020, 3:20 Т.Ж.

Добрый день.
Потому, что нужно не добавлять ссылку (или что там у вас в итоге получается) на файл и прикреплять его к письму.
Если не ошибаюсь, то для отправки письма с файлом нужно использовать класс EmailMessage

def send_email(request):
    ...
    email = EmailMessage(
        subject,
        content,
        contact_email,
        [to],
        headers={'Reply-To': contact_email}
    )
    if request.FILES:
        uploaded_file = request.FILES['file'] # file is the name value which you have provided in form for file field
        email.attach(uploaded_file.name, uploaded_file.read(), uploaded_file.content_type)
    email.send()

Могут быть некоторые разночтения в синтаксисе, в зависимости от версий Django

S
  • Мамыр 20, 2020, 7:08 Т.Ж.

Добрый день, в итоге получилось как-то так, отправляет форму с файлом.
Спасибо.

settings:

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

views:

from django.core.mail import EmailMessage
from django.conf import settings

def contacts(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            email_subject = ' Сообщение через контактную форму '
            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'])

    email = EmailMessage(
        email_subject,
        email_body,
        settings.EMAIL_HOST_USER,
        ['mymail@gmail.com'],
    )
    if request.FILES:
        uploaded_file = request.FILES['file'] # file is the name value which you have provided in form for file field
        email.attach(uploaded_file.name, uploaded_file.read(), uploaded_file.content_type)
    email.fail_silently=False

    email.send()
    return render(request, 'main/contacts.html')
S
  • Мамыр 22, 2020, 7:52 Т.Ж.

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

class ContactForm(forms.Form):
file = forms.FileField(
        label="Загрузить файл", required=False,
        widget = forms.FileInput(attrs={'multiple': True})

    )
Evgenii Legotckoi
  • Мамыр 22, 2020, 7:57 Т.Ж.

Думаю, что как-то так, возможно неправильно написание имени метода getlist, но выглядеть должно так

if request.FILES:
    for f in request.FILES.getlist('file'):
        email.attach(f.name, f.read(), f.content_type)
S
  • Мамыр 22, 2020, 11:10 Т.Ж.

Спасибо, Евгений.
Все заработало.

def contacts(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            email_subject = ' Сообщение через контактную форму '
            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'])

        email = EmailMessage(
            email_subject,
            email_body,
            settings.EMAIL_HOST_USER,
            ['mymail@gmail.com'],
            )
        if request.FILES:
            for f in request.FILES.getlist('file'):
                email.attach(f.name, f.read(), f.content_type)
        email.fail_silently=False
        email.send()
    return render(request, 'main/contacts.html')
d
  • Ақп. 16, 2023, 11:15 Т.Ж.

Timeweb так себе провайдер.
Поддержка не отвечает. И smtp не отправляет письма.
Все перепробовал ничего найти не могу.
1. Ошибка sock.connect(sa) TimeoutError: [Errno 110] Connection timed out
2. Ошибка OSError: [Errno 101] Network is unreachable

Пікірлер

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

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:66ұпай,
  • Бағалау ұпайлары-1
t

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:33ұпай,
  • Бағалау ұпайлары-10
t

Qt - Тест 001. Сигналы и слоты

  • Нәтиже:52ұпай,
  • Бағалау ұпайлары-4
Соңғы пікірлер
G
GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssrАқп. 8, 2024, 6:43 Т.Қ.
Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
F
FynjyШілде 22, 2024, 4:15 Т.Ж.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
BlinCT
BlinCTМаусым 25, 2024, 1 Т.Ж.
Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
BlinCT
BlinCTМамыр 5, 2024, 5:46 Т.Ж.
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

Бізді әлеуметтік желілерде бақылаңыз