python - Django 联系电子邮件表单未在模板 home.html 中呈现/显示
问题描述
Django项目结构
父目录:personal_portfolio_project 主子目录(包含设置):personal_portfolio 应用:portfolio、blog
整个项目及其所有应用程序的目录结构(通过tree在控制台中打印出来):
├── personal_portfolio_project
│ ├── blog
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-39.pyc
│ │ │ ├── admin.cpython-39.pyc
│ │ │ ├── models.cpython-39.pyc
│ │ │ ├── urls.cpython-39.pyc
│ │ │ └── views.cpython-39.pyc
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── migrations
│ │ │ ├── 0001_initial.py
│ │ │ ├── 0002_auto_20210117_1306.py
│ │ │ ├── 0003_auto_20210117_1309.py
│ │ │ ├── 0004_auto_20210117_1432.py
│ │ │ ├── __init__.py
│ │ │ └── __pycache__
│ │ │ ├── 0001_initial.cpython-39.pyc
│ │ │ ├── 0002_auto_20210117_1306.cpython-39.pyc
│ │ │ ├── 0003_auto_20210117_1309.cpython-39.pyc
│ │ │ ├── 0004_auto_20210117_1432.cpython-39.pyc
│ │ │ └── __init__.cpython-39.pyc
│ │ ├── models.py
│ │ ├── templates
│ │ │ └── blog
│ │ │ ├── all_blogs.html
│ │ │ └── detail.html
│ │ ├── tests.py
│ │ ├── urls.py
│ │ └── views.py
│ ├── db.sqlite3
│ ├── manage.py
│ ├── media
│ │ └── portfolio
│ │ └── images
│ │ ├── DSC_0004a.jpg
│ │ └── DSC_0010a.jpg
│ ├── personal_portfolio
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-39.pyc
│ │ │ ├── settings.cpython-39.pyc
│ │ │ ├── urls.cpython-39.pyc
│ │ │ └── wsgi.cpython-39.pyc
│ │ ├── asgi.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ ├── portfolio
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-39.pyc
│ │ │ ├── admin.cpython-39.pyc
│ │ │ ├── forms.cpython-39.pyc
│ │ │ ├── models.cpython-39.pyc
│ │ │ └── views.cpython-39.pyc
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── forms.py
│ │ ├── migrations
│ │ │ ├── 0001_initial.py
│ │ │ ├── __init__.py
│ │ │ └── __pycache__
│ │ │ ├── 0001_initial.cpython-39.pyc
│ │ │ └── __init__.cpython-39.pyc
│ │ ├── models.py
│ │ ├── static
│ │ │ └── portfolio
│ │ │ ├── CV_Andreas_Luckert.pdf
│ │ │ ├── DSC_0010a.jpg
│ │ │ ├── Logo_Andreas_Luckert.png
│ │ │ ├── Logo_ZappyCode_DjangoCourse.png
│ │ │ ├── custom.css
│ │ │ └── main.js
│ │ ├── templates
│ │ │ └── portfolio
│ │ │ ├── about.html
│ │ │ ├── base.html
│ │ │ └── home.html
│ │ ├── tests.py
│ │ └── views.py
│ └── test_sendgrid.py
故事线
我portfolio/forms.py
在“投资组合”-应用程序中有一个文件,其中包含以下内容:
from django import forms
class ContactForm(forms.Form):
from_email = forms.EmailField(required=True)
subject = forms.CharField(required=True)
message = forms.CharField(widget=forms.Textarea, required=True)
# From docs: https://docs.djangoproject.com/en/3.1/topics/forms/#more-on-fields
cc_myself = forms.BooleanField(required=False)
在portfolio/views.py
我有以下相关部分:
from .forms import ContactForm # import module from same parent folder as this script
import General.Misc.general_tools as tools # custom module to import special-print function
def contactView(request, admin_email='blaa@blaaa.com'):
if request.method == 'GET':
sendemail_form = ContactForm()
else:
sendemail_form = ContactForm(request.POST)
if sendemail_form.is_valid():
# * Retrieve data and set up e-mail (subject, sender, message)
subject = sendemail_form.cleaned_data['subject']
from_email = sendemail_form.cleaned_data['from_email']
message = sendemail_form.cleaned_data['message']
# From docs: https://docs.djangoproject.com/en/3.1/topics/forms/#more-on-fields
cc_myself = sendemail_form.cleaned_data['cc_myself']
recipients = [admin_email]
if cc_myself:
recipients.append(from_email)
# * Send email
try:
# General Django docs: https://docs.djangoproject.com/en/3.1/topics/email/#send-mail
# NOTE on passed list as 4th parameter: recipient-list
## i) How to set up an email contact form - docs: https://learndjango.com/tutorials/django-email-contact-form
send_mail(subject,
message,
from_email,
recipients,
fail_silently=False)
# * Exceptions * #
# NOTE on scope: security
except BadHeaderError:
return HttpResponse('Invalid header found.')
# General exception to be printed out
except Exception as e:
tools.except_print(f"ERROR:\n{e}")
# Return success (if this code is reached)
return redirect('success')
# Send the completed (filled-in) form to the homepage - HTML - document
return render(request, "portfolio/home.html",
{'sendemail_form': sendemail_form})
def successView(request):
return HttpResponse('Success! Thank you for your message.')
这是我在最后包含的联系表格portfolio/templates/portfolio/home.html
(其余的HTML
工作非常好,并且在显示-webpage时通常Django
不会在控制台中显示任何错误):localhost
<!-- ** E-Mail contact form **
Docs: https://learndjango.com/tutorials/django-email-contact-form-->
{% if sendemail_form %}
<h2 class="mt-5">Contact Me</h2>
<hr>
<form method="post">
{% csrf_token %}
<!-- NOTE on ".as_p": https://docs.djangoproject.com/en/3.1/topics/forms/#form-rendering-options
Possible attributes: as_table, as_p, as_ul -->
{{ sendemail_form.as_p }}
<div class="form-actions">
<button type="submit">Send</button>
</div>
</form>
{% endif %}
我的内容personal_portfolio/urls.py
如下:
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings # get info from the settings.py - file
from portfolio import views # other views could also be imported (e.g. from the blog-app)
urlpatterns = [
path("", views.home, name="home"),
# Docs: https://learndjango.com/tutorials/django-email-contact-form
path("contact/", views.contactView, name='contact'),
path("success/", views.successView, name='success'),
# Add "About me" for additonal info about the creator of the webpage
path("about/", views.about, name="about"),
# Standard admin page
path('admin/', admin.site.urls),
# NOTE on include: forwarding all /blog/ - related requests to the blog-app
path('blog/', include('blog.urls')),
]
# * Add a static link to the MEDIA - files * #
# NOTE on processing: import certain variables defined in the settings.py of this project
# Docs: google django images (or media (folder)) etc.
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
我尝试在 中portfolio/admin.py
定义的类中注册表单portfolio/models.py
,但首先我不知道这是否有必要,其次由于 ,它甚至无法正常工作TypeError: 'DeclarativeFieldsMetaclass' object is not iterable
,因此我从portfolio/admin.py
之后删除了以下代码:
from django.contrib import admin
# !!! CAUTON: TypeError: 'DeclarativeFieldsMetaclass' object is not iterable
from .forms import ContactForm
# NOTE on registering form: doesn't work due to the following error:
# TypeError: 'DeclarativeFieldsMetaclass' object is not iterable
admin.site.register(ContactForm)
总的来说,我对如何使表单最终出现在我的portfolio/templates/portfolio/home.html
. 当{% if sendemail_form %}
扫描non-None
要传递的表单时,这表明表单没有正确传递。
测试contactView()
以检查views.py
调用联系表单的函数是否已通过打印输出到达:
$ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
January 19, 2021 - 14:16:37
Django version 3.1.5, using settings 'personal_portfolio.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
[19/Jan/2021 14:16:42] "GET / HTTP/1.1" 200 31617
[19/Jan/2021 14:16:42] "GET /static/portfolio/custom.css HTTP/1.1" 304 0
[19/Jan/2021 14:16:42] "GET /static/portfolio/main.js HTTP/1.1" 304 0
[19/Jan/2021 14:16:43] "GET /static/portfolio/Logo_ZappyCode_DjangoCourse.png HTTP/1.1" 200 442438
--> 根据控制台,它没有到达,因为打印输出没有出现。
解决方案
您需要ContactForm
在呈现主页的主页视图中创建。我们需要这样做,因为表单出现在主页模板中;如果我们不在此视图中添加表单,那么模板的联系表单部分将永远无法工作,因为它接收None
.
def home(request):
... your code here ...
# send empty contact form to template
sendemail_form = ContactForm()
return render(
request,
"portfolio/home.html",
{'sendemail_form': sendemail_form})
然后不contactView
应该渲染模板,只是重定向。的工作contactView
是获取 POST 数据并对其进行处理,然后重定向到不同的视图;它永远不应该呈现模板。
def contactView(request, admin_email='blaa@blaaa.com'):
if request.method == 'POST':
sendemail_form = ContactForm(request.POST)
if sendemail_form.is_valid():
subject = sendemail_form.cleaned_data['subject']
from_email = sendemail_form.cleaned_data['from_email']
message = sendemail_form.cleaned_data['message']
cc_myself = sendemail_form.cleaned_data['cc_myself']
recipients = [admin_email]
if cc_myself:
recipients.append(from_email)
try:
send_mail(subject,
message,
from_email,
recipients,
fail_silently=False)
except BadHeaderError:
return HttpResponse('Invalid header found.')
except Exception as e:
tools.except_print(f"ERROR:\n{e}")
return HttpResponse('errors.')
# Return success (if this code is reached)
return redirect('success')
# return to home page
return redirect('home')
此外,将您的联系表格(位于主页模板中)指向正确的 URL(这是联系 URL,而不是主页 URL);你可以改变:
{% if sendemail_form %}
...
<form method="post">
...
{% endif %}
至
{% if sendemail_form %}
...
<form method="post" action="{% url 'contact' %}">
...
{% endif %}
推荐阅读
- c - 如何使用socket可以扩展框架?
- typescript - typescript 静态类型检查 ES 模块导出
- javascript - 如何合并列表中 3 个不同对象的字符串?
- rest - FHIR 服务返回的字符串显示在变量中并且具有长度但在日志记录中不打印(或打印为空格)
- database - PostgreSQL 中的循环外键
- javascript - 来自数据库的自动填充文本框值
- android - Android 11 模拟器使 PCI 总线不适用于 hda
- azure-devops - Azure Visual Studio 2019 无法推送到 Azure DevOps Git
- c# - editorconfig - PascalCase 方法命名的正确 IDE 建议
- javascript - Ionic4 + Angular:使用 *ngFor 动态创建 ion-select 导致将所有 ion-select-options 链接在一起(无意中)