- 1.1设计社交型网站
- 1.2.使用Django验证框架
- 1.2.1构建登录视图
- 1.2.3登录和注销视图
- 1.2.4修改密码视图
- 1.2.5 重置密码视图
- 1.3.用户注册和用户配置
- 1.3.1用户注册
- 1.3.2扩展用户模型
- 1.3.3使用消息框架
- 1.4.构建自定义后端
- 1.5.向站点中添加社交网站验证
- 2.1构建图像书签网站
- 2.1.1构建视图模型
- 2.1.2生成多对多关系
- 2.1.3在管理站点找那个注册图像模型
- 2.2发布其他站点的内容
- 2.2.1清空表单字段
- 2.2.2覆写ModelForm的save()方法
用户可以在此共享他们在互联网中搜索的图片。针对该项目,需要设置以下元素
- 用户验证系统,以实现注册,登录,配置文件的编辑以及密码的修改和重置等操作
- 关注系统,以使用户间可彼此查看
- 显示共享照片,并实现用户标签工具,进而共享来自任意网站的图像
- 每名用户的操作流,以使用户可查看所关注的上传内容
创建项目
django-admin startproject bookmarks cd bookmarks python manage.py startapp account
将创建的应用程序加入到INSTALLED_APPS中
‘account.apps.AccountConfig’
- User表述包含基本字段的用户模块,该模块的主要字段包括username、password、email、first_name、last_name、以及is_active
- Group表述分组模块,以对用户进行分类
- Permission表述用户或分组标记,并执行特定操作
- 通过发布表单获得用户名和密码
- 利用存储与数据库中的数据对用户进行验证
- 检查用户是否属于活跃状态
- 登录网站并验证会话
首先创建登录表单,在account应用程序的目录中创建forms.py文件,并添加下面代码行
from django import forms
class LoginForm(forms.Form):
username = forms.CharField()
pasword = forms.CharField(widget=forms.PasswordInput)
# 此处使用了PasswordInput微件显示其HTML input元素,同时包含type=“password"属性,以使浏览器可将其当中密码输入
编辑account应用程序中的views.py文件,并向其添加下列代码
from django.shortcuts import render
from django.http import HttpResponse
from django.contrib.auth import authenticate, login
from .form import LoginForm
# Create your views here.
def user_login(request):
if request.method == 'POST':
form = LoginForm(request.POST)# 实例化一个包换提交数据的表单
if form.is_valid():# 检查表单是否有效
cd = form.cleaned_data
user = authenticate(request, username=cd['username'], password=cd['password'])# 有效就进行验证接收request对象,返回User对象
if user is not None:# 检查用户是否验证成功
if user.is_alive:# 验证成功检查是否处于活跃状态
login(request, user)# 处于活跃状态则调用login方法,可在当前会话中设置该用户,并返回登录成功信息
return HttpResponse('Authenticated successfully')
else:
return HttpResponse('Disabled account')# 用户不处于活跃状态
else:
return HttpResponse('Invalid login')# 验证不成功,返回错误提示
else:
form = LoginForm()# get请求,进项创建一个新的登录表单
return render(request, 'account/login.html', {'form': form})
针对视图创建URL路径,对此在account应用程序目录中创建新的urls.py文件,并添加下面的代码
from django.urls import path
from . import views
urlpatterns = [
path('login/',views.user_login,name='login')
]
便捷bookmarks中的urls.py文件中导入include并添加一个account应用程序的url路径
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('account/',include('account.urls'))
]
当前,登录视图可通过url访问,下面针对该视图创建模板。在account应用程序目录中创建下列文件和目录
编辑base.html文件
{% load staticfiles %}
{% block title %}{% endblock %}
Bookmarks
{% block content %}{% endblock %}
login,html继承base.html将其进行修改
{% extends "base.html" %}
{% block title %} Log_in{& endblock %}
{% block content %}
Login-in
Please use the following form to log-in;
{% endblock %}
因为由form表单发送就要制定csrf_token
运行结果
编辑account应用程序中的urls.py文件
from django.urls import path
from django.contrib.auth import views as auth_views
from . import views
urlpatterns = [
# path('login/', views.user_login, name='login'),
path('login/',auth_views.LoginView.as_view(),anme='login'),
path('logout/',auth_views.LogoutView.as_view(),name='logout'),
]
我们使用Django验证框架的LoginView视图。
在account应用程序话的templates目录中生成一个新目录,将其明明为registration。这是DJango身份验证视图所期望的验证末班的默认路径。
DJango.contrib.admin模块中包含了一些用于管理站点的验证模板。我曾将account应用程序置于INSTALLED_APPS设置的开始处,以是DJango用户在默认状态下使用末班,而飞定义于其他应用程序中的验证模板。
在templates/registration目录中创建新文件,将其明明为login.html并添加以下代码
{% extends "base.html" %}
{% block title %} Log-in{% endblock %}
{% block content %}
Login-in
{% if form.errors %}
Your username and password didn't match
Please try again
{% else %}
Please,use the following form to login-in:
{% endif %}
{% endblock %}
加入了隐含的标签,当传递请求中的next参数时,该变量首先由登录表单进行设置。
这路next参数表示为一个URL。若才参数已经被设置,DJango视图将成功登录后将用户重定向至既定的URL处
下面在registration模板目录中创建logged_out.html模板
{% extends "base.html" %}
{% block title %} Logged out {% endblock %}
{% block content %}
Logged out
You have been successfully logged out. You canLog-in again.
{% endblock %}
接下来当用户登录其账号时,我们将创建一个显示视图。对此,打开account应用程序的views.py文件
from django.contrib.auth.decorators import login_required
@login_required
def dashboard(request):
return render(request, 'account/dashboard.html', {'section': 'dashboard'})
这里采用了框架中的验证转授权,当验证成功,执行装饰后的视图,不成功就利用最初请求的url作为参数(名为next)将用户重定向至登录URL。据此,在成功登录后,登录视图将用户重定向至试图访问的URL处,对此,我们在登录模板表单中加入了隐藏输入。
除此之外,我们还定义了section变量,并使用该变量跟踪用户浏览的站点部分。相应地,多个视图可对应于一部分内容。当定义每个视图对应的部分时,这可视为一种简单的方式。
下面针对dashboard视图创建一个模板。对此,在templates/account/目录中创建一个新文件,并将其命名为dashboard.html
{% extends "base.html" %}
{% block title %}
DashBoard
{% endblock %}
{% block content %}
DashBoard
Welcome to you dashboard.
{% endblock %}
添加url
urlpatterns = [
……
path('',views.dashboard,name='dashboard')
]
编辑settings.py文件,添加下面代码
LOGIN_REDIRECT_URL = 'dashboard' LOGIN_URL = 'login' LOGOUT_URL = 'logout'
- LOGIN_REDIRECT_URL:如果请求中未出现next参数没在成功登录后,将通知DJango重定向URL
- LOGIN_URL:用户重定向并实现登录的URL
- LOGOUT_URL:用户重定向并实现注销的url
编辑base.html
{% block title %}{% endblock %}
Bookmarks
{% if request.user.is_authenticated %}
{% endif %}
{% if request.user.is_authenticated %}
Hello {{ request.user.first_name }},
Logout
{% else %}
Log-in
{% endif %}
{% block content %}{% endblock %}
显示出错误就是因为没有加载css,小问题
极致的简约会导致视觉上的扭捏
添加url
path('password_change/',auth_views.PasswordChangeView.as_view(),name='password_change'),
path('password_change/done/',auth_views.PasswordChangeDoneView.as_view(),name='password_change_done'),
创建模板
在应用程序的templates/registrarion中添加新文件,passsword_change_form.html
{% extend "base.html" %}
{% block title %} Change your password {% endblock %}
{% block content %}
Change your password
Use the form blow to change your password
{% endblock %}
上面包含了修改密码的表单,需要重新创建一个文件,将其命名为password_change_done.html
{% extends "base.html" %}
{% block title %}Password changed{% endblock %}
{% block content %}
Password changed
Your password has been successfully changed .
{% endblock %}
进入/account/password_change/显示以下页面,即修改当前登录的用户的密码
针对密码重置行为,可向account应用程序中的urls.py 文件中添加下面的url
path('password_reset/',auth_views.PasswordResetView.as_view(),name='password_reset'),
path('password_reset/done/',auth_views.PasswordResetDoneView.as_view(),name='password_reset_done'),
path('reset///',auth_views.PasswordReset/confirm/iView.as_view(),name='password_reset_/confirm/i'),
path('reset/done/',auth_views.PasswordResetCompleteView.as_view(),name='password_reset_complete')
接下来向应用程序中的templates/registration/目录添加新文件password_rest_form.html
{% extends "base.html" %}
{% block title %}
Reset your password {% endblock %}
{% block content %}
Forgottten your password?
Enter your e-mail address to obtain a new password.
{% endblock %}
创建另一个文件password_reset_email.html
Someone asked for password reset for email {{ email }}.Follow the link blow:
{{ protocol }}://{{ domain }}{% url "password_reset_/confirm/i" uidb64=uidtoken=token %}
Your username,in case you'be forgotten :{{user.get_username}}
上面末班用于显示发送至用户 的有电子邮件,进而对密码进行重置。
再次创建一个文件password_reset_done.html
{% extends "base.html" %}
{% block title %}
Reset your password {% endblock %}
{% block content %}
Reset your password?
{% if validlink %}
Please enter your new password twice:
{% else %}
The password reset link was invalid,possibly because it has already ben used. Please request a new password reset.
{% endif %} {% endblock %}创建一个password_reset_complete.html文件
{% extends "base.html" %}
{% block title %}
Password reset{% endblock %}
{% block content %}
Password set
Your password has ben set. You canLog-inNow
{% endblock %}
向settings文件中添加一个变量
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
点击而进入忘记密码页面
输入邮箱
然后在控制台可点击网站进行修改密码
在account应用程序中的form.py文件中添加下面的代码
from django.contrib.auth.models import User
class UserRegistrationForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password', widget=forms.PasswordInput)
class meta:
model = User
fields = ('Username', 'first_name', 'email')
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError("Passwords don't match.")
return cd['password2']
在应用程序中的views.py文件中添加视图函数
from .form import LoginForm, UserRegistrationForm
def register(request):
if request.method == "POST":
user_form = UserRegistrationForm(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 render(request, 'account/register_don.html', {'new_user': new_user})
else:
user_form = UserRegistrationForm()
return render(request, 'account/register.html', {'user_form': user_form})
绑定url
path('register/',views.register,name='register')
最后在account/templates目录下创建一个新的模板,将其命名为register.html
{% extends "base.html" %}
{% block title %}Create an account {% endblock %}
{% block content %}
Create an account
Please , sign up using the following form:
{% endblock %}
在同一目录下添加模板文件,将其命名为register_done.html
{% extends "base.html" %}
{% block title %}Welcome{% endblock %}
{% block content %}
Welcome
Your account has been successfully created . Now you can Log-in.
{% endblock %}
1.3.2扩展用户模型
便捷account应用程序中的models.py文件
from django.db import models
from django.conf import settings
# Create your models here.
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
date_of_birth = models.DateField(blank=True, null=True)
photo = models.ImageField(upload_to='users/%y/%m/%d', blank=True)
def __str__(self):
return 'Profile for user {}'.format(self.user.username)
安装pillow
pip install pillow
配置settings文件
MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(base_DIR,'media/')
编辑bookmarks的url
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('account/',include('account.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
通过这一方式,DJango开发服务器将复制在开发期间为媒体文件 提供服务(DEBUG设置为TRUE)
然后在命令行输入
python managy.py makemigrations python managy.py migrate
编辑admin.py文件在管理站点注册profile模型
from django.contrib import admin
from .models import Profile
# Register your models here.
@admin.register(Profile)
class ProfileAdmin(admin.ModelAdmin):
list_display = ['user', 'date_of_birth', 'photo']
进入admin后台
添加一个用户
在项目目录下就会创建一个midea文件夹,用来存放用户上传的图片
目录就是根据上传的日期来设置的
用户要是向在站点上编辑配置其配置文件。就要在应用程序中的form.py文件添加语句
form ,models import Profile
class UserEditForm(forms.ModelForm):
class meta:
model = User
fields = ('first_name', 'last_name', 'email')
class ProfileEditForm(forms.ModelForm):
class meta:
model = Profile
fields = ('date_of_birth', 'photo')
编辑应用程序中的views.py文件。导入模块
from .models import Profile
在register视图函数中的new_user.save()下面加上语句
Profile.objects.create(user=new_user)
当用户在站点中注册是,将生成一个与其相关联的空配置文件。对于之前创建的用户
需要通过管理站点并通过手动方式创建一个Profile对象
对于用户配置文件的编辑操作,可向同一文件中添加下面代码:
from .form import LoginForm, UserRegistrationForm,UserEditForm,ProfileEditForm
@login_required
def edit(request):
if request.method=='POST':
user_form = UserEditForm(instance=request.user,data=request.POST)
profile_form = ProfileEditForm(instance=request.user.profile,data=request.POST,files=request.FILES)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
else:
user_form = UserEditForm(instance=request.user)
profile_form = ProfileEditForm(instance=request.user.profile)
return render(request,'account/edit.html',{'user_form':user_form,'profile_form':profile_form})
应用程序中配置url
path('edit/',views.edit,name='edit')
最后在创建一个模板在templates/account目录下命名为edit.html
{% extends "base.html" %}
{% block title %}
Edit account
{% endblock %}
{% block content %}
Edit your account
You can eidt account using the following form.
{% endblock %}
然后就可访问/account/edit网站来进行修改了,但是前提要是在登录状态,不然无法进行访问
当前还可以编辑dashboard页面,同时包含指向配置文件编辑以及密码页面的修改的链接,打卡dashboard.html模板,并查看替换
Welcome to you dashboard.
替换为
You can edit profile or change your password.
至此,用户可访问表单并编辑其配置表单,
You can edit profile or change your password.
1.3.3使用消息框架若用户可与平台进行交互,旺旺需要通知用户其操作结果。对此DJango内置了一个消息框架,位于django.contrib.message中
可通过add_message()方法,或者下列任意一种快捷方式创建新消息
- success():操作完成后成功显示成功消息
- info():显示消息信息
- warning():操作行将失败
- error():操作未成功
- debug():当产品环境中删除或忽略的调试信息
下面将带当前平台中添加消息。介于消息框架以全局方式应用与项目上,因而我们可以在基本模板上为用户显示消息。打开account中的base.html模板,并在带有header ID的div元素和content ID的div元素中间加上下列代码添加下面代码
{% if messages %}
下面修改edit视图并使用消息矿建,对此可便捷account应用程序中的views,py文件
form django.contrib import messages
@login_required
def edit(request):
if request.method == 'POST':
……
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request,'Profile updated successfully')
else:
messages.error(request,'Error updating your profile')
else:
user_form = UserEditForm(instance=request.user)
profile_form = ProfileEditForm(instance=request.user.profile)
return render(request, 'account/edit.html', {'user_form': user_form, 'profile_form': profile_form})
然后访问/account/edit 点击save就能看到更改的消息提示
当传入的日期是错误的时候就会提示错误
1.4.构建自定义后端DJango可对不同的资源进行验证,AUTHENTICATION_BACKENDS设置中也包含了针对项目验证后端列表,默认是,该设置如下所示。
[‘django.contrib.auth.backends.ModelBackend’]
默认的AUTHENTICATION_BACKENDS将采用django.contrib.auth中的用用户模式,并在用户与数据库之间进行验证,这适用于大部分项目场景。然而我们还可以自己创建定义后端,并在用户和其他资源之间进行验证。如LDAP目录和其他系统
当使用django.contrib.auth的authenticate()函数时,Djang将尝试将用户以定义于AUTHENTICATION_BACKENDS中的每一个后端进行逐一验证,直至其中某个后端成功验证了用户。只用全部后端验证均失效时,站点将不会对该用户授权
django提供了一种较为简单的方式定义自己的验证后端。这里验证后端定义为一个累,并可提供以下两种方法:
- authenticate():方法接收request对象以及欧诺个户凭证作为参数,同时需返回一个与此类相匹配的user对象;若为提供至authenticate()中,方法则返回None。对象表示为HttpRequest对象;若为提供至authenticate()中。方法则返回None
- get_user()接收一个用户ID参数并返回一个user对象。
下面定义一个验证后端,并通过电子邮件地址实现站点的用户验证
在应用程序目录中创建一个新文件,其名称为authentication.py并添加下列代码
from django.contrib.auth.models import User
class EmailAuthBackend(object):
def authenticate(self, request, username=None, password=None):
try:
user = User.objects.get(email=username)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
上述代码定义了简单的验证框架,其中authenticate()方法接收一个request对象,以及可选参数username和password。我们可以选择不同的参数,但是要使用username和password来确保亲厚段与验证框架使用直接协同工作
编辑settings.py文件并添加下列设置内容:
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'account.authentication.EmailAuthBackend',
]
这样就可以在登录页面来使用用户名或者邮箱来登录了。前提是用户绑定的邮箱只能绑定一个用户,否则就会get()到不同的用户最后报错
1.5.向站点中添加社交网站验证我们可能通过相关服务,如Facebook,Twitter等向站点中添加社交网站验证。python中的Social Auth模块可减缓向站点中添加社交验证这一处理。
针对不同的python框架,该模块涵盖了相同的身份验证后端,首先要安装该数据包
pip install social-auth-app-django
然后在settings.py文件中设置INSTALLEND_APPS
INSTALLED_APPS = [
……
'social_django',
]
然后应用模块与数据库进行同步
python mangy.py migrate
然后配置bookmarks的路由
path('social-auth/',include('social_django.urls',namespace='social'))
然后配置hosts文件
添加下面的字段
127.0.0.1 mysite.com
这将通知计算机将mysite.com主机名指向自己的计算机。
然后通过mysite.com:8000/account/login来访问
会报错
Django利用ALLOW_HOSTS设置控制主机并为应用程序提供服务,是一种安全措施,避免HTTP主机遭受共计。
可以在settings.py文件中设置ALLOWED_HOST
ALLOWED_HOSTS = ['loaclhost','mysite.com','127.0.0.1']
这样就可以对mysite.com域名来访问django页面了。
2.1构建图像书签网站本节将讨论源自其他为你工作和本站点的图像标签工具以及共享行为。我们需要完成以下任务
- 定义一个模型以共享图片及信息
- 床架一个表单和视图并处理图像上传操作
- 构建一个用户系统,并可以发布源自外部网站的图像
首先创建一个应用程序
python manage.py startapp images
在settings.py文件中添加app
INSTALLED_APPS = [
……
'images.apps.ImagesConfig',
]
2.1.1构建视图模型
编辑images应用程序的models.py文件并向其添加下列代码
from django.db import models
from django.conf import settings
# Create your models here.
class Image(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='images_created', on_delete=models.CASCADE)
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, blank=True)
url = models.URLField()
image = models.ImageField(upload_to='images/%Y/%m/%d')
description = models.TextField(blank=True)
created = models.DateTimeField(auto_now_add=True, db_index=True)
def __str__(self):
return self.title
- user: 表示设定图像书签的User对象,定义为1对多的外键类型,当用户被删除,其所有图像也会全部删除
- title:表示图像的标题
- slug:表示一个简短的标题
- url:表示图像的初始url
- image:表示图像文件
- description:表示可选的图像描述
- created:表示对象在数据库中创建的日期和时间,设定的db_index以使django针对该字段在数据库中生成一个索引
我们将复写Iamge模型的save()方法,并根据title字段值自动生成slug字段,导入slugify()并向Image模型中添加save()方法
from django.utils.text import slugify
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugfy(self.title)
super(Image, self).save(*args, **kwargs)
2.1.2生成多对多关系
这里想Image模型中添加了一个字段,并存储对用户图像感兴趣的用户。此时需要使用到多对多的关系、
对此可向Image模型中添加下列字段
users_like = models.ManyToManyField(settings.AUTH_USER_MODEL,related_name='images_liked',blank=True)
运行创建初始迁移
python manage.py makemigrations images python manage.py migrate images2.1.3在管理站点找那个注册图像模型
在images应用程序下的admin.py下添加下面的代码
from django.contrib import admin
from .models import Image
# Register your models here.
@admin.register(Image)
class ImageAdmin(admin.ModelAdmin):
list_display = ['title', 'slug', 'image', 'create']
list_filter = ['create']
2.2发布其他站点的内容
用户可以对源自外部站点的图像设置书签。相应地,用户将提供该图像URL、标题、以及可选的描述内容。对应应用程序将下载该图像并在书记库中生成新的Image对象。
开始构建一个表单并提交新的图像。对此可以在Image应用程序目录中创建文件forms.py并添加下面的代码
from django import forms
from .models import Image
class ImageCreateForm(forms.ModelForm):
class meta:
model = Image
fields = ('title', 'urls', 'description')
widgets = {'url': forms.HiddenInput}
我们将使用Javascript工具予以提供,并从外部站点中选择一幅图像,对应表单将作为参数接收其URL。
2.2.1清空表单字段为了验证搜提供的图像URL有效,需要检查文件名是否以.jpg或者jrpg扩展名结尾,却仅支持jpeg文件。在上节中曾讨论了django可定义表单的方法,并使用clean_
对此可以向ImageCrateForm中添加下列方法
def clean_url(self):
url = self.cleaned_data['url']
valid_extension = ['jpg', 'jpeg']
extension = url.rsplit('.', 1).lower()
if extension not in valid_extension:
raise forms.ValidationError('The Given url does not match valid image extensions')
上述代码定义了clean_url()方法并清空url字段
- 通过访问表单实例的目录,可获得url字段值
- 解析url并获得扩展名,检查是否为有效扩展名



