Django入门与实践-第16章:用户登录(完结)
# myproject/settings.py
LOGIN_REDIRECT_URL = 'home'
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
http://127.0.0.1:8000/login/
http://127.0.0.1:8000/signup/
http://127.0.0.1:8000/reset/
http://127.0.0.1:8000/reset/done/
http://127.0.0.1:8000/reset/Mw/set-password/
http://127.0.0.1:8000/reset/complete/
http://127.0.0.1:8000/settings/password/
http://127.0.0.1:8000/settings/password/done/
# myproject/urls.py from django.conf.urls import url from django.contrib import admin from django.contrib.auth import views as auth_views from accounts import views as accounts_views from boards import views urlpatterns = [ url(r'^$', views.home, name='home'), url(r'^signup/$', accounts_views.signup, name='signup'), url(r'^login/$', auth_views.LoginView.as_view(template_name='login.html'), name='login'), url(r'^logout/$', auth_views.LogoutView.as_view(), name='logout'), url(r'^boards/(?P<pk>\d+)/$', views.board_topics, name='board_topics'), url(r'^boards/(?P<pk>\d+)/new/$', views.new_topic, name='new_topic'), url(r'^admin/', admin.site.urls), ]
<!--templates/base.html--> {% load static %}<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>{% block title %}Django Boards{% endblock %}</title> <link href="https://fonts.googleapis.com/css?family=Peralta" rel="stylesheet"> <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}"> <link rel="stylesheet" href="{% static 'css/app.css' %}"> {% block stylesheet %}{% endblock %} <!-- 这? --> </head> <body> {% block body %} <!-- 这? --> <nav class="navbar navbar-expand-sm navbar-dark bg-dark"> <div class="container"> <a class="navbar-brand" href="{% url 'home' %}">Django Boards</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#mainMenu" aria-controls="mainMenu" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="mainMenu"> {% if user.is_authenticated %} <ul class="navbar-nav ml-auto"> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" href="#" id="userMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> {{ user.username }} </a> <div class="dropdown-menu dropdown-menu-right" aria-labelledby="userMenu"> <a class="dropdown-item" href="#">My account</a> <a class="dropdown-item" href="#">Change password</a> <div class="dropdown-divider"></div> <a class="dropdown-item" href="{% url 'logout'%}">Log out</a> </div> </li> </ul> {% else %} <form class="form-inline ml-auto"> <a href="#" class="btn btn-outline-secondary">Log in</a> <a href="{% url 'signup' %}" class="btn btn-primaryml-2">Sign up</a> <a href="{% url 'login' %}" class="btn btn-outline-secondary">Log in</a> </form> {% endif %} </div> </div> </nav> <div class="container"> <ol class="breadcrumb my-4"> {% block breadcrumb %} {% endblock %} </ol> {% block content %} {% endblock %} </div> {% endblock body %} <!-- 这? --> <script src="{% static 'js/jquery-3.2.1.min.js' %}"></script> <script src="{% static 'js/popper.min.js' %}"></script> <script src="{% static 'js/bootstrap.min.js' %}"></script> </body> </html> <!--templates/login.html--> {% extends 'base.html' %} {% load static %} {% block stylesheet %} <link rel="stylesheet" href="{% static 'css/accounts.css' %}"> {% endblock %} {% block body %} <div class="container"> <h1 class="text-center logo my-4"> <a href="{% url 'home' %}">Django Boards</a> </h1> <div class="row justify-content-center"> <div class="col-lg-4 col-md-6 col-sm-8"> <div class="card"> <div class="card-body"> <h3 class="card-title">Log in</h3> <form method="post" novalidate> {% csrf_token %} {% include 'includes/form.html' %} <button type="submit" class="btn btn-primary btn-block">Log in</button> </form> </div> <div class="card-footer text-muted text-center">New to Django Boards?
<a href="{% url 'signup' %}">Sign up</a> </div> </div> <div class="text-center py-2"> <small> <a href="#" class="text-muted">Forgot your password?</a> </small> </div> </div> </div> </div> {% endblock %}
<!--templates/base_accounts.html--> {% extends 'base.html' %} {% load static %} {% block stylesheet %} <link rel="stylesheet" href="{% static 'css/accounts.css' %}"> {% endblock %} {% block body %} <div class="container"> <h1 class="text-center logo my-4"> <a href="{% url 'home' %}">Django Boards</a> </h1> {% block content %} {% endblock %} </div> {% endblock %} <!--templates/login.html--> {% extends 'base_accounts.html' %} {% block title %}Log in to Django Boards{% endblock %} {% block content %} <div class="row justify-content-center"> <div class="col-lg-4 col-md-6 col-sm-8"> <div class="card"> <div class="card-body"> <h3 class="card-title">Log in</h3> <form method="post" novalidate> {% csrf_token %} {% include 'includes/form.html' %} <button type="submit" class="btn btn-primary btnblock">Log in</button> </form> </div> <div class="card-footer text-muted text-center">New to Django Boards? <a href="{% url 'signup' %}">Sign up</a></div> </div> <div class="text-center py-2"> <small> <a href="#" class="text-muted">Forgot your password?</a> </small> </div> </div> </div> {% endblock %} <!--templates/signup.html--> {% extends 'base_accounts.html' %} {% block title %}Sign up to Django Boards{% endblock %} {% block content %} <div class="row justify-content-center"> <div class="col-lg-8 col-md-10 col-sm-12"> <div class="card"> <div class="card-body"> <h3 class="card-title">Sign up</h3> <form method="post" novalidate> {% csrf_token %} {% include 'includes/form.html' %} <button type="submit" class="btn btn-primary btnblock">Create an account</button> </form> </div> <div class="card-footer text-muted text-center">Already have an account? <a href="{% url 'login' %}">Log in</a></div> </div> </div> </div> {% endblock %}
<!--templates/includes/form.html--> {% load widget_tweaks %} {% if form.non_field_errors %} <div class="alert alert-danger" role="alert"> {% for error in form.non_field_errors %} <p{% if forloop.last %} class="mb-0"{% endif %}>{{ error }}</p> {% endfor %} </div> {% endif %} {% for field in form %} <div class="form-group"> {{ field.label_tag }} {% if form.is_bound %} {% if field.errors %} {% render_field field class="form-control is-invalid" %} {% for error in field.errors %} <div class="invalid-feedback"> {{ error }} </div> {% endfor %} {% else %} {% render_field field class="form-control is-valid" % } {% endif %} {% else %} {% render_field field class="form-control" %} {% endif %} {% if field.help_text %} <small class="form-text text-muted"> {{ field.help_text|safe }} <!-- 新的代码 --> {{ field.help_text }} </small> {% endif %} </div> {% endfor %}
#在boards应用中,创建一个名为templatetags的新文件夹。然后在该文件夹内创建两个名为 init.py 和 form_tags.py的空文件。 # boards/templatetags/form_tags.py from django import template register = template.Library() @register.filter def field_type(bound_field): return bound_field.field.widget.__class__.__name__ @register.filter def input_class(bound_field): css_class = '' if bound_field.form.is_bound: if bound_field.errors: css_class = 'is-invalid' elif field_type(bound_field) != 'PasswordInput': css_class = 'is-valid' return 'form-control {}'.format(css_class) <!--templates/includes/form.html--> {% load form_tags widget_tweaks %} {% if form.non_field_errors %} <div class="alert alert-danger" role="alert"> {% for error in form.non_field_errors %} <p{% if forloop.last %} class="mb-0"{% endif %}>{{ error }}</p> {% endfor %} </div> {% endif %} {% for field in form %} <div class="form-group"> {{ field.label_tag }} {% render_field field class=field|input_class %}
{% for error in field.errors %} <div class="invalid-feedback"> {{ error }} </div> {% endfor %} {% if field.help_text %} <small class="form-text text-muted"> {{ field.help_text|safe }} </small> {% endif %} </div> {% endfor %}
myproject/urls.py url(r'^reset/$', auth_views.PasswordResetView.as_view( template_name='password_reset.html', email_template_name='password_reset_email.html', subject_template_name='password_reset_subject.txt' ), name='password_reset'), url(r'^reset/done/$', auth_views.PasswordResetDoneView.as_view(template_name='password_reset_done.html'), name='password_reset_done'), url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', auth_views.PasswordResetConfirmView.as_view(template_name='password_reset_confirm.html'), name='password_reset_confirm'), url(r'^reset/complete/$', auth_views.PasswordResetCompleteView.as_view(template_name='password_reset_complete.html'), name='password_reset_complete'), <!--templates/password_reset.html--> {% extends 'base_accounts.html' %} {% block title %}Reset your password{% endblock %} {% block content %} <div class="row justify-content-center"> <div class="col-lg-4 col-md-6 col-sm-8"> <div class="card"> <div class="card-body"> <h3 class="card-title">Reset your password</h3> <p>Enter your email address and we will send you a link to reset your password.</p> <form method="post" novalidate> {% csrf_token %} {% include 'includes/form.html' %} <button type="submit" class="btn btn-primary btnblock">Send password reset email</button> </form> </div> </div> </div> </div> {% endblock %}
#templates/password_reset_subject.txt [Django Boards] Please reset your password <!--templates/password_reset_email.html--> Hi there, Someone asked for a password reset for the email address {{ email }}. Follow the link below: {{ protocol }}://{{ domain }}{% url 'password_reset_confirm'uidb64=uid token=token %} In case you forgot your Django Boards username: {{ user.username }} If clicking the link above doesn't work, please copy and paste the URLin a new browser window instead. If you've received this mail in error, it's likely that another user entered your email address by mistake while trying to reset a password.
If you didn'tinitiate the request, you don't need to take any further action and can safely disregard this email. Thanks, The Django Boards Team
<!--templates/password_reset_done.html--> {% extends 'base_accounts.html' %} {% block title %}Reset your password{% endblock %} {% block content %} <div class="row justify-content-center"> <div class="col-lg-4 col-md-6 col-sm-8"> <div class="card"> <div class="card-body"> <h3 class="card-title">Reset your password</h3> <p>Check your email for a link to reset your password. If it doesn't appear within a few minutes, check your spam folder.</p> <a href="{% url 'login' %}" class="btn btn-secondary btn-block">Return to log in</a> </div> </div> </div> </div> {% endblock %}
<!--templates/password_reset_confirm.html--> {% extends 'base_accounts.html' %} {% block title %} {% if validlink %} Change password for {{ form.user.username }} {% else %} Reset your password {% endif %} {% endblock %} {% block content %} <div class="row justify-content-center"> <div class="col-lg-6 col-md-8 col-sm-10"> <div class="card"> <div class="card-body"> {% if validlink %} <h3 class="card-title">Change password for @{{ form.user.username }}</h3> <form method="post" novalidate> {% csrf_token %} {% include 'includes/form.html' %} <button type="submit" class="btn btn-success btn-block">Change password</button> </form> {% else %} <h3 class="card-title">Reset your password</h3> <div class="alert alert-danger" role="alert"> It looks like you clicked on an invalid password reset link. Please try again. </div> <a href="{% url 'password_reset' %}" class="btn btn-secondary btn-block">Request a new password reset link</a> {% endif %} </div> </div> </div> </div> {% endblock %}
<!--templates/password_reset_complete.html--> {% extends 'base_accounts.html' %} {% block title %}Password changed!{% endblock %} {% block content %} <div class="row justify-content-center"> <div class="col-lg-6 col-md-8 col-sm-10"> <div class="card"> <div class="card-body"> <h3 class="card-title">Password changed!</h3> <div class="alert alert-success" role="alert"> You have successfully changed your password! You may now proceed to log in. </div> <a href="{% url 'login' %}" class="btn btn-secondary btn-block">Return to log in</a> </div> </div> </div> </div> {% endblock %}
#myproject/urls.py (view complete file contents) url(r'^settings/password/$', auth_views.PasswordChangeView.as_view(template_name='password_change.html'), name='password_change'), url(r'^settings/password/done/$', auth_views.PasswordChangeDoneView.as_view(template_name='password_change_done.html'), name='password_change_done'), #myproject/settings.py LOGIN_URL = 'login' <!--templates/password_change.html--> {% extends 'base.html' %} {% block title %}Change password{% endblock %} {% block breadcrumb %} <li class="breadcrumb-item active">Change password</li> {% endblock %} {% block content %} <div class="row"> <div class="col-lg-6 col-md-8 col-sm-10"> <form method="post" novalidate> {% csrf_token %} {% include 'includes/form.html' %} <button type="submit" class="btn btn-success">Change password</button> </form> </div> </div> {% endblock %}
<!--templates/password_change_done.html--> {% extends 'base.html' %} {% block title %}Change password successful{% endblock %} {% block breadcrumb %} <li class="breadcrumb-item"><a href="{% url 'password_change' %}">Change password</a></li> <li class="breadcrumb-item active">Success</li> {% endblock %} {% block content %} <div class="alert alert-success" role="alert"> <strong>Success!</strong> Your password has been changed! </div> <a href="{% url 'home' %}" class="btn btn-secondary">Return to home page</a> {% endblock %}