D先生 2020-02-22
? 上一部分内容完成了博客项目的搭建,以及博客标题和博客内容的展示,熟悉了Django的使用,下面,接着实现用户管理部分功能。
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 当前文件路径的上两级文件路径--即是根目录 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] #即模板目录的位置是相对项目根目录的templates目录——./templates , 'APP_DIRS': False,# True, # False表示不允许Django按照默认方式寻找模板文件 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
# settings 文件的最后三行 # Django 支持这三种静态文件 # Static files (CSS, JavaScript, Images) # 想知道Django是如何实现的可以查看上面这个网址 # https://docs.djangoproject.com/en/3.0/howto/static-files/ #在默认状态下,如果通过URL访问静态文件,各个应用的静态文件都有自己的静态文件存放地 #例如可以通过http://localhost:8000/blog/static/newton.jpg的模式进行访问,blog应用的静态文件newton.jpg STATIC_URL = '/static/' #注,本项目不打算这样设置,而是把静态文件放到指定的目录,在上一行下面添加如下代码: STATICFILES_DIRS =( os.path.join(BASE_DIR, "static"), ) # 在根目录下创建static目录,添加newton.jpg文件,在浏览器进行测试
? 1、首先下载jquery和bootstrap等相关的文件并放到创建的static目录下:
bootstrap下载链接:https://www.bootcss.com/
? 2、创建新的通用的基础模板
头部代码:header.html {% load staticfiles %} <div class="container"> <nav class="navbar navbar-default" role="navigation"> <div class="navbar-header"> <a class="navbar-brand" href="http://www.itdiffer.com"> <img src="{% static '/images/logo.jpg' %}" width="100px"> </a> </div> <div> <ul class="nav navbar-nav" role="navigation"> <li><a href="{% url 'blog:blog_title' %}"></a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li><a href="#">LOGIN</a></li> </ul> </div> </nav> </div>
脚部代码:footer.html <div class="container"> <hr> <p class=""text-center> copy right www.itdiffer.com </p> </div>
base.html {% load staticfiles %} <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>{% block title %} {% endblock %}</title> <link rel="stylesheet" href="{% static 'css/bootstrap.css' %}"> </head> <body> {% include "header.html" %} <div class="container"> {% block content %} {% endblock %} </div> {% include "footer.html" %} {% block javascript %}{% endblock %} </body> </html>
方式一: 在./mysite/urls.py的urlpatterns中进行如下设置。特别注意,include()中的第一参数提供的是一个二元的元组。 urlpatterns=[ path('admin/',admin.site.urls), # path('blog/', include('blog.urls')) path('blog/', include(('blog.urls', 'blog'), namespace='blog')) ] 在./blog/urls.py的urlpatterns中进行如下配置。 urlpatterns = [ # path('', views.blog_title), # 此处将函数视图添加进来 # path('<int:article_id>', views.blog_article) path('', views.blog_title, name='blog_title'), # 此处将函数视图添加进来 path('<int:article_id>/', views.blog_article, name='blog_article') ] 方式二: 在./mysite/urls.py的urlpatterns中进行如下设置。注意,被注释了的那一行是“方式一”的配置,请读者注意比较两种配置方式之不同。 urlpatterns=[ path('admin/',admin.site.urls), # path('blog/', include('blog.urls')), # path('blog/', include(('blog.urls', 'blog'), namespace='blog')), path('blog/', include('blog.urls', namespace='blog')), ] 在./blog/urls.py的urlpatterns中进行如下配置,比“方式一”增加了app_name = "blog"这一行。 app_name = "blog" # 新增加这一行 urlpatterns = [ # path('', views.blog_title), # 此处将函数视图添加进来 # path('<int:article_id>', views.blog_article) path('', views.blog_title, name='blog_title'), # 此处将函数视图添加进来 path('<int:article_id>/', views.blog_article, name='blog_article') ] 以上两种方式,供读者自行选择。
1、创建新应用(account)
python manage.py startapp account # 修改配置: ./mysite/settings.py 中: INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'blog', 'account', ]
2、URL配置
# ./mysite/urls.py urlpatterns=[ path('admin/', admin.site.urls), # path('blog/', include('blog.urls')), path('blog/', include(('blog.urls', 'blog'), namespace='blog')), # path('blog/', include('blog.urls', namespace='blog')), #该方法配置和上面一样的效果 # 新添加的路由 path('account/', include(('account.urls', 'account'), namespace='account')), ] # 在新应用account目录下,创建urls.py, 进行配置。 from django.urls import path from . import views urlpatterns = [ path('login/', views.user_login, name='user_login'), ]
在 ./account目录中新建文件forms.py ,在forms.py中创建表单类用于用户登录:
from django import forms class LoginForm(forms.Form): username = forms.CharField() password = forms.CharField(widget=forms.PasswordInput)
在 ./account/views.py文件中创建视图函数user_login()
from django.shortcuts import render from django.http import HttpResponse from django.contrib.auth import authenticate, login from .forms import LoginForm # Create your views here. def user_login(request): if request.method == "POST": login_form = LoginForm(request.POST) if login_form.is_valid(): cd = login_form.cleaned_data user = authenticate(username=cd['username'], password=cd['password']) if user: login(request, user) return HttpResponse("Welcome you. You have been authenticated successfully. ") else: return HttpResponse("Your username or password is not right.") else: return HttpResponse("Invalid login") if request.method == "GET": login_form = LoginForm() return render(request, "account/login.html", {"form": login_form})
? 在./templates/account/login.py 里添加如下代码:
{% extends "base.html" %} {% block title %}Login{% endblock %} {% block content %} <div class="row text-center vertical-middle-sm"> <h1>Login</h1> <p>Input your username and password</p> <form class="form-horizontal" action="." method="post"> {% csrf_token %} {{ form.as_p }} <input type="submit" value="Login"> </form> </div> {% endblock %}
? 1、在./account/urls.py 中配置路由如下:
from django.urls import path from . import views from django.contrib.auth import views as auth_views # 用户内置登录引入 urlpatterns = [ # path('login/', views.user_login, name='user_login'), path('login/', auth_views.LoginView.as_view(template_name='account/login2.html'), name='user_login'), ]
? 2、添加路由配置里的网页login2.html
{% extends "base.html" %} {% load staticfiles %} {% block title %}Login{% endblock %} {% block content %} <div class="row text-center vertical-middle-sm"> <h1>Login--Built in method of Django</h1> {% if form.errors %} <p>Your username and password didn't match.Please try agin.</p> {%endif %} <p>Input your username and password</p> <form calss="form-horizontal" action="{% url 'account:user_login' %}" method="post"> {% csrf_token %} <div class="form-group"> <label for="{{ form.username.id_for_label }}" class="col-md-5 control-label" style="color:red"> <span class="glyphicon glyphicon-user"> </span> Username </label> <div class="col-md-6 text-left"> {{ form.username }} </div> </div> <div class="form-group"> <label for="{{ form.password.id_for_label }}" class="col-md-5 control-label" style="color:blue"> <span class="glyphicon glyphicon-user"> </span> Password </label> <div class="col-md-6 text-left"> {{ form.password }} </div> </div> <input type="submit" class="btn btn-primary btn-lg" value="Login"> </form> </div> {% endblock %}
? 3、修改配置文件
为了设置项目所需要的转向目标,需要在./mysite/settings.py中增加LOGIN_REDIRECT_URL的值(将以下配置放置到./mysite/settings.py文件的最后)。 LOGIN_REDIRECT_URL = '/blog/'
{% load staticfiles %} <div class="container"> <nav class="navbar navbar-default" role="navigation"> <div class="navbar-header"> <a class="navbar-brand" href="http://www.itdiffer.com"> <img src="{% static '/images/logo.png' %}" width="100px"> </a> </div> <div> <ul class="nav navbar-nav" role="navigation"> <li><a href="{% url 'home' %}">HOME</a></li> <li><a href="{% url 'blog:blog_title' %}">BLOG</a></li> <li><a href="{% url 'article:article_titles' %}">文章</a></li> <li><a href="{% url 'image:falls_images' %}">美图</a></li> <li><a href="{% url 'course:course_list' %}">课程</a></li> <li><a href="{% url 'course:about'%}">关于本站</a></li> </ul> <ul class="nav navbar-nav navbar-right" style="margin-right:10px"> {% if user.is_authenticated %} <li> <div class="dropdown" style="margin-top:8px"> <button class='btn btn-default dropdown-toggle' type='button' id='dropdownMenu' data-toggle='dropdown'>{{ user.username }} <span class='caret'></span> </button> <ul class="dropdown-menu"> <li><a href="{% url 'account:password_change' %}">修改密码</a></li> <li><a href="{% url 'account:my_information' %}">个人信息</a></li> <li><a href="{% url 'article:article_column' %}">后台管理</a></li> </ul> </div> </li> <li><a href="{% url 'account:user_logout' %}">Logout</a></li> {% else %} <li><a href="{% url 'account:user_login' %}">LOGIN</a></li> <li><a href="{% url 'account:user_register' %}">Sign up</a></li> {% endif %} </ul> </div> </nav> </div> <script src="{% static 'js/jquery.js' %}"></script> <script src="{% static 'js/bootstrap.js' %}"></script>
<!-- 现在就来修改./templates/header.html模板,使LOGIN所在的位置根据用户登录状态显示不同的内容。如果用户已经登录,则显示用户名和Logout字样;如果用户尚未登录,则显示LOGIN字样,并做超链接到登录界面。 --/>
{% load staticfiles %} <div class="container"> <nav class="navbar navbar-default" role="navigation"> <div class="navbar-header"> <a class="navbar-brand" href="http://www.itdiffer.com"> <img src="{% static '/images/logo.jpg' %}" width="100px"> </a> </div> <div> <ul class="nav navbar-nav" role="navigation"> <li><a href="{% url 'blog:blog_title' %}">BLOG</a></li> </ul> <ul class="nav navbar-nav navbar-right" style="margin-right: 10px"> {% if user.is_authenticated %} <li><a href="#">{{ user.username }}</a></li> <li><a href="#">Logout</a></li> {% else %} <li><a href="{% url 'account:user_login' %}">LOGIN</a></li> {% endif %} </ul> </div> </nav> </div>
? 与登录类似,首先配置URL。编辑./account/urls.py文件,增加如下内容。
urlpatterns = [ # path('login/', views.user_login, name='user_login'), path('login/', auth_views.LoginView.as_view(template_name='account/login2.html'), name='user_login'), path('logout/', auth_views.LoginView.as_view(template_name='account/logout.html'), name='user_logout'), ]
? 此处配置好后,把./templates/header.html文件中那个针对Logout的超链接修改一下。
<li><a href="{% url 'account:user_logout' %}">Logout</a></li>
? 在./templates/account/中创建一个退出的模板文件,名为logout.html,代码如下。
{% extends "base.html" %} {% block title %}Login{% endblock %} {% block content %} <div class="row text-center vertical-middle-sm"> <p>You have log out</p> <p>You can <a href="{% url 'account:user_login' %}" >Login</a> again .</p> </div> {% endblock %}
? 1、编写表单类 ./account/form.py文件,增加一个注册用户表单类:
from django import forms from django.contrib.auth.models import User class RegistrationForm(forms.ModelForm): password = forms.CharField(label="Password", widget=forms.PasswordInput) password2 = forms.CharField(label="Confirm Password", widget=forms.PasswordInput) class Meta: model = User fields = ("username", "email") def clean_password2(self): cd = self.cleaned_data if cd['password'] != cd['password2']: raise forms.ValidationError("passwords do not match.") return cd['password2']
? 2、在./account/views.py中 ,添加视图函数:
from .forms import RegistrationForm def register(request): if request.method == "POST": user_form = RegistrationForm(request.POST) if user_form.is_valid(): new_user = user_form.save(commit=False) new_user.set_password(user_form.cleaned_data['password']) new_user.save() return HttpResponse("successfully .") else: return HttpResponse("sorry, your can not register .") else: user_from = RegistrationForm() return render(request, "account/register.html", {"form":user_from})
3、在./templates/account/ 下创建前端页面 register.html:
{% extends base.html %} {% load staticfiles %} {% block title %} register user{% endblock %} {% block content %} <div class="row text-center vertical-middle-sm"> <h1>Register</h1> <p>If you are a user,<strong><a href="{% url 'account:user_login' %}">Login</a></strong>,please</p> <p>or register.</p> <from class="form-horizontal" action="." method="post"> {% csrf_token %} <div class="form-group"> <label for="{{ form.username.id_for_label }}" class="col-md-5 control-label"> Username </label> <div class="col-md-6 text-left">{{ form.username }}</div> </div> <div class="form-group"> <label for="{{ form.eamil.id_for_label }}" class="col-md-5 control-label"> Email </label> <div class="col-md-6 text-left">{{ form.email }}</div> </div> <div class="form-group"> <label for="{{ form.password.id_for_label }}" class="col-md-5 control-label"> PassWord </label> <div class="col-md-6 text-left">{{ form.password }}</div> </div> <div class="form-group"> <label for="{{ form.password2.id_for_label }}" class="col-md-5 control-label"> Confirm Password </label> <div class="col-md-6 text-left">{{ form.password2 }}</div> <input type="submit" class="btn btn-primary btn-lg" value="REGISTER"> </div> </from> </div> {% endblock %}
4、配置路由, ./account/urls.py 中配置:
urlpatterns = [ path('register/',views.register, name ='user_register') # 新增 ]
? 5、进行测试
http://127..0.0.1:8080/account/register.html
1、要增加一个User数据模型中没有的字段(比如手机号),编辑./account中的models.py文件,并在其中输入如下代码。
from django.db import models from django.contrib.auth.models import User # Create your models here. class UserProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, unique=True) birth = models.DateField(blank=True, null=True) phone = models.CharField(max_length=20, null=True) def __str__(self): return 'user {}'.format(self.user.username) # 数据迁移 python manage.py makemigrations account python manage.py migrate account
2、按照流程,下面应该编写表单类了,编辑./account/forms.py文件,代码如下:
from .models import UserProfile class UserProfileForm(forms.ModelForm): class Meta: model = UserProfile fields = ("phone", "birth")
3、下面要完善视图函数。编辑./account/views.py文件,增加和修改如下代码。修改后的视图函数与原来相比,主要是兼顾了另外一个表单类,所以只是在代码行数上增加了,并没有增加新的内容。
def register(request): if request.method == "POST": user_form = RegistrationForm(request.POST) userprofile_form = UserProfileForm(request.POST) if user_form.is_valid()*userprofile_form.is_valid(): new_user = user_form.save(commit=False) new_user.set_password(user_form.cleaned_data['password']) new_user.save() new_profile = userprofile_form.save(commit=False) new_profile.user = new_user new_profile.save() return HttpResponse("successfully") else: return HttpResponse("sorry, your can not register.") else: user_form = RegistrationForm() userprofile_form = UserProfileForm() return render(request, "account/register.html", {"form": user_form, "profile":userprofile_form})
? 4、修改模板,重新编辑./templates/account/register.html文件,代码如下:
{% extends "base.html" %} {% load staticfiles %} {% block title %}register user{% endblock %} {% block content %} <div class="row text-center vertical-middle-sm"> <h1>Register</h1> <p>If you are a user, <strong><a href="{% url 'account:user_login' %}">Login</a> </strong>,please</p> <p>or register.</p> <form class="form-horizontal" action="." method="post">{% csrf_token %} <div class="form-group"> <label for="{{ form.username.id_for_label }}" class="col-md-5 control-label">Username</label> <div class="col-md-6 text-left">{{ form.username }}</div> </div> <div class="form-group"> <label for="{{ form.email.id_for_label }}" class="col-md-5 control-label"> Email</label> <div class="col-md-6 text-left">{{ form.email }}</div> </div> <div class="form-group"> <label for="{{ form.password.id_for_label }}" class="col-md-5 control-label">Password</label> <div class="col-md-6 text-left">{{ form.password }}</div> </div> <div class="form-group"> <label for="{{ form.password.id_for_label }}" class="col-md-5 control-label"> Confirm Password</label> <div class="col-md-6 text-left">{{ form.password2 }}</div> </div> <div class="form-group"> <label for="{{ profile.birth.id_for_label }}" class="col-md-5 control-label"> Birth Date</label> <div class="col-md-6 text-left">{{ profile.birth }}</div> </div> <div class="form-group"> <label for="{{ profile.phone.id_for_label }}" class="col-md-5 control-label">Phone</label> <div class="col-md-6 text-left">{{ profile.phone }}</div> </div> <input type="submit" class="btn btn-primary btn-lg" value="REGISTER"> </form> </div> {% endblock %}
? 1、在我们增加用户注册信息后,所增加的内容能不能也在超级管理员界面中进行集中管理,要实现这个功能,需要对./account/admin.py文件进行编辑,代码如下:
class UserProfileAdmin(admin.ModelAdmin): list_display = ('user', 'birth', 'phone') list_filter = ("phone",) admin.site.register(UserProfile, UserProfileAdmin) #· list_display属性的作用是列出列表中的项目。注意这个属性的名称不能改变,后面所有类似的属性也是如此。 #· list_filter的作用是规定网页右边FILTER的显示内容,读者可以根据这里的电话号码过滤显示列表的内容。
在进行具体操作之前,先梳理清楚修改密码的步骤: 第一步,要判断用户是否登录,只有登录用户才能修改密码。 第二步,要打开设置新密码的界面,在该界面中提交新密码。 第三步,要给用户反馈,是否修改完成。
? 1、先写上述第二步中用于提交新密码的界面,即在./templates/account/中创建password_change_form.html文件。以下是./templates/account/password_change_form.html的代码:
{% extends "base.html" %} {% block title %}passowrd change{% endblock %} {% block content %} <div class="row text-center vertical-middle-sm"> <h1>Change Password</h1> <p>Please enter your old password,for security's sake, and then enter your new password twice so we can verify you typed it in correctly.</p> {% if form.new_password1.help_text %} <div class="text-left" style="margin-left:400px"> <p>{{ form.new_password1.help_text|safe }}</p> </div> {% endif %} <form class="form-horizontal" action="." method="post">{% csrf_token %} <div class="form-group"> <label class='col-md-5 control-label text-right'> {{ form.old_password.label_tag }} </label> <div class="col-md-6 text-left">{{ form.old_password }}</div> </div> <div class="form-group"> <label class='col-md-5 control-label text-right'> {{ form.new_password1.label_tag }} </label> <div class="col-md-6 text-left">{{ form.new_password1 }}</div> </div> <div class="form-group"> <label class="col-md-5 control-label text-right"> {{ form.new_password2.label_tag }} </label> <div class="col-md-6 text-left">{{ form.new_password2 }}</div> </div> <input type="submit" value="Change my password" class="btn btn-primary btn-lg"/> </form> </div> {% endblock %}
? 2、同样,也写好第三步中密码修改完成的页面,即./templates/account/password_change_done.html,代码如下:
app_name = "account" urlpatterns = [ path('login/', auth_views.LoginView.as_view(template_name='account/login2.html'), name='user_login'), path('logout/', auth_views.LogoutView.as_view(template_name='account/logout.html'), name='user_logout'), path('register/', views.register, name='user_register'), path('password-change/', auth_views.PasswordChangeView.as_view(template_name="account/password_change_form.html", success_url="/account/password-change-done/"), name='password_change'), path('password-change-done/', auth_views.PasswordChangeDoneView.as_view(template_name="account/password_change_done.html"), name='password_change_done'), ]
3、如何让Django能够跳转到/account/login/请编辑./mysite/settings.py文件,在文件中增加如下内容:
LOGIN_URL = '/account/login/'
? 4、为了实现再次跳转,还需要编辑./templates/account/login2.html文件,该文件新增代码如下:
{% extends "base.html" %} {% load staticfiles %} {% block title %}Login{% endblock %} {% block content %} <div class="row text-center vertical-middle-sm"> <h1>Login</h1> {% if form.errors %} <p>Your username and password didn't match. Please try again.</p> {% else %} <p>Input your username and password</p> {% endif %} # 新增 {% if next %} <form class="form-horizontal" action="{% url 'account:user_login' %}?next={{next}}" method="post" > {% else %} <form class="form-horizontal" action="{% url 'account:user_login' %}" method="post"> {% endif %} # {% csrf_token %} <div class="form-group"> <label for="{{ form.username.id_for_label }}" class="col-md-5 control-label" style="color:red"> <span class="glyphicon glyphicon-user"></span>Username</label> <div class="col-md-6 text-left">{{ form.username }}</div> </div> <div class="form-group"> <label for="{{ form.password.id_for_label }}" class="col-md-5 control-label" style="color:blue"> <span class="glyphicon glyphicon-floppy-open"></span>Password</label> <div class="col-md-6 text-left">{{ form.password }}</div> </div> <input type="submit" class="btn btn-primary btn-lg" value="Login"> </form> </div> {% endblock %}
按照上面的方式修改了登录模板文件之后,再次测试,就能够实现登录之后跳转到修改密码页面的功能了。
修改的仅仅是一个模板文件./templates/header.html,修改之后其代码如下:
{% if user.is_authenticated %} <li> <div class="dropdown" style="margin-top:8px"> <button class='btn btn-default dropdown-toggle' type='button' id='dropdownMenu' data-toggle='dropdown'> {{ user.username }}<span class='caret'></span> </button> <ul class="dropdown-menu"> <li><a href="{% url 'account:password_change' %}">修改密码</a></li> {# <li><a href="{% url 'account:my_information' %}">个人信息</a></li>#} {# <li><a href="{% url 'article:article_column' %}">后台管理</a></li>#} </ul> </div> </li> <li><a href="{% url 'account:user_logout' %}">Logout</a></li> {% else %} <li><a href="{% url 'account:user_login' %}">LOGIN</a></li> <li><a href="{% url 'account:user_register' %}">Sign up</a></li> {% endif %}
? 上述代码中
? 重置密码的流程,下面就按照这个流程完成此功能的开发
1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|
开始 | 请求重置密码 | 输入邮箱 | 发送邮件提示信息 | 阅读邮件点击超链接 | 重置密码 | 结速 |
? 1、对用户请求重置密码的响应,使用Django内置的PasswordResetView类视图完成,即在./account/urls.py中配置如下URL映射。
path('password-reset/', auth_views.PasswordResetView.as_view(template_name="account/password_reset_form.html", email_template_name="account/password_reset_email.html", success_url='/account/password-reset-done/'), name='password_reset'),
2、在./templates/account/中新建password_reset_form.html文件,其代码如下:
{% extends "base.html" %} {% block title %}password reset{% endblock %} {% block content %} <div class="row text-center vertical-middle-sm"> <h1>Forgotten your password? Reset, please.</h1> <p>Enter your email to set a new password.</p> <form class="form-horizontal" action="." method="post"> {% csrf_token %} <div class="form-group"> <label class="col-md-5 control-label text-right">Email</label> <div class="col-md-6 text-left">{{ form.email }}</div> </div> <input type="submit" value="Send email" class="btn btn-primary btn-lg"> </form> </div> {% endblock %}
? 3、置向申请重置密码的用户邮箱所发送的邮件内容,创建新的文件 password_reset_email.html,代码如下:
<p> You're receiving this email because you requested a password reset for your user account at <a href="http://www.blog.com">blog.com</a> </p> <p>Please go to the following page and choose a new password:</p> {{ protocol }}://{{ domain }}{% url 'account:password_reset_confirm' uidb64=uid token=token %} <p>Your username, in case you've forgotten:{{ user.get_username }}</p> <p>Thanks for using our site!</p> <p>The blog.com team</p>
? 4、在此处又出现了password_reset_done.html,还需要在./templates/account/中创建该文件,并录入以下代码。
{% extends "base.html" %} {% block title %}password reset{% endblock %} {% block content %} <div class="row text-center vertical-middle-sm"> <h1>Reset your password</h1> <p>We've emailed you instructions for setting your password, if an account exists with the email you entered. You should receive them shortly.</p> <p>If you don't receive an email, please make sure you've entered the address you registered with, and check your spam folder.</p> </div> {% endblock %}