Форма Django не отображается
Я пытаюсь разработать простое приложение Django, состоящее из контактной формы и страницы благодарности, но я не могу заставить фактическую форму отображаться на /contact/contact; все, что я вижу, это кнопку отправки.
Я вообще не использую Django 'admin'; базы данных тоже нет. Я работаю на locolhost, используя python manage.py runserver
Почему моя форма не отображается?
Нужна ли мне модель формы?
Такова структура каталога:
/contact/contact/urls.py
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]
from django.urls import include
urlpatterns += [
path('contact/', include('contactform.urls')),
]
from django.conf import settings
from django.conf.urls.static import static
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
/contact/contactform/urls.py
from django.urls import path
from . import views
app_name = 'contactform'
urlpatterns = [
path('thanks/', views.thanks, name='thanks'),
path('contact/', views.contact, name='contact'),
]
/contact/contactform/views.py
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from django.http import HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from contactform.forms import ContactForm
from contact.settings import EMAIL_HOST_USER, EMAIL_PORT, EMAIL_HOST_PASSWORD, EMAIL_HOST
def thanks(request):
return render(request, 'thanks.html', {})
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
form_data = form.cleaned_data
msg = MIMEMultipart()
msg['From'] = EMAIL_HOST_USER
msg['To'] = EMAIL_HOST_USER
msg['Subject'] = f'Personal site: {form_data["subject"]}'
message = f'Name: {form_data["name"]}\n' \
f'Email address: {form_data["email_address"]}\n\n' \
f'{form_data["message"]}'
msg.attach(MIMEText(message))
with smtplib.SMTP(EMAIL_HOST, EMAIL_PORT) as server:
server.ehlo()
server.starttls()
server.login(EMAIL_HOST_USER, EMAIL_HOST_PASSWORD)
server.sendmail(EMAIL_HOST_USER, EMAIL_HOST_USER, msg.as_string())
return HttpResponseRedirect('/thanks')
else:
form = ContactForm()
return render(request, 'contact.html')
/contact/contactform/models.py
from django.urls import reverse
/contact/contactform/apps.py
from django.apps import AppConfig
class ContactformConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'contactform'
/contact/contactform/forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(required=True, widget=forms.TextInput(
attrs={'class': 'form-control', 'maxlength': '100'}
))
email_address = forms.EmailField(required=True, widget=forms.EmailInput(
attrs={'class': 'form-control', 'maxlength': '100'}
))
subject = forms.CharField(required=True, widget=forms.TextInput(
attrs={'class': 'form-control', 'maxlength': '100'}
))
message = forms.CharField(required=True, widget=forms.Textarea(
attrs={'class': 'form-control', 'maxlength': '1000', 'rows': 8}
))
/contact/contactform/templates/contact.html
<h2>Form</h2>
<form action="/contact/" method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Send</button>
</form>
Представление form не отображается, поскольку вы не передаете его в свой шаблон. Вы можете сделать это вместо этого в представлении contact:
return render(request, 'contact.html', {
'form': form
})
РЕДАКТИРОВАНИЕ:
Если вы получаете 'return' outside function ошибку, вы можете сделать это в вашем contact представлении.
def contact(request):
form = ContactForm() # Before if condition
Вы можете удалить условие else.
ОТРЕДАКТИРУЙТЕ 2:
Это должно быть ваше представление contact.
def contact(request):
form = ContactForm()
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
form_data = form.cleaned_data
msg = MIMEMultipart()
msg['From'] = EMAIL_HOST_USER
msg['To'] = EMAIL_HOST_USER
msg['Subject'] = f'Personal site {form_data["subject"]}'
message = f'Name: {form_data["name"]}\n' \
f'Email address: {form_data["email_address"]}\n\n' \
f'{form_data["message"]}'
msg.attach(MIMEText(message))
with smtplib.SMTP(EMAIL_HOST, EMAIL_PORT) as server:
server.ehlo()
server.starttls()
server.login(EMAIL_HOST_USER, EMAIL_HOST_PASSWORD)
server.sendmail(EMAIL_HOST_USER, EMAIL_HOST_USER, msg.as_string())
return HttpResponseRedirect('/thanks')
else:
return HttpResponseRedirect(reverse('contactform:contact'))
return render(request, 'contact.html')
Ваша форма Django не отображается, потому что вы не передаете форму в ваш html шаблон. вы должны передать ее.
return render(request, 'contact.html','form':form)
попробуйте это и это должно работать:
def contact(request):
form = ContactForm()
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
form_data = form.cleaned_data
msg = MIMEMultipart()
msg['From'] = EMAIL_HOST_USER
msg['To'] = EMAIL_HOST_USER
msg['Subject'] = f'Personal site {form_data["subject"]}'
message = f'Name: {form_data["name"]}\n' \
f'Email address: {form_data["email_address"]}\n\n' \
f'{form_data["message"]}'
msg.attach(MIMEText(message))
with smtplib.SMTP(EMAIL_HOST, EMAIL_PORT) as server:
server.ehlo()
server.starttls()
server.login(EMAIL_HOST_USER, EMAIL_HOST_PASSWORD)
server.sendmail(EMAIL_HOST_USER, EMAIL_HOST_USER, msg.as_string())
return HttpResponseRedirect('/thanks')
else:
return HttpResponseRedirect('contactform:contact')
return render(request, 'contact.html','form':form)
После этого вы обновили проект на Update 2/20/22
Вы забыли зарегистрировать приложение по умолчанию path для contactform в url_patterns списке.
ваш /contact/contact/urls.py
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]
from django.urls import include
urlpatterns += [
path('contact/', include('contactform.urls')),
]
from django.conf import settings
from django.conf.urls.static import static
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Должно быть :
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('contactform.urls'))
]
from django.urls import include
urlpatterns += [
path('contact/', include('contactform.urls')),
]
from django.conf import settings
from django.conf.urls.static import static
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Попробуйте и скажите, работает ли это?
вы должны добавить path('', include('contactform.urls')) в urls.py основного проекта.
А если мы удалим все вещи, протестировав его очень просто и обновив views.py через следующий код:
/contact/contactform/views.py
from contactform.forms import ContactForm
from django.http import HttpResponseRedirect
from django.shortcuts import render
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
form_data = form.cleaned_data
return HttpResponseRedirect('/thanks/')
else:
form = ContactForm()
return render(request, 'contact.html', {'form': form})
def thanks(req):
return render(req, 'thanks.html')
Приведенный выше код работал очень эффективно, поэтому я сделал вывод, что он будет работать.
Попробуйте.
И еще одна вещь, на которой я хотел бы заострить внимание - всегда используйте следующий шаблон при создании файла шаблонов.
Appname/templates/Appname/anyfile.html
Как в вашем случае:
contactform/templates/contactform/contact.html
Вы пропустили третий шаг после templates, ну это не обязательно, но если вы это сделаете, то это будет хорошей практикой.
Вы тоже забыли / при перенаправлении в вашем views.py.
Это должно быть return HttpResponseRedirect('/thanks/')
а не return HttpResponseRedirect ('/thanks')
Действие вашей формы должно указывать на
<form action="/contact/contact/"....
или лучше
<form action="{% url 'contactform:contact' %}" ...)

