python web 社交网站

项目元素:

用户身份验证系统:注册。登录,编辑个人信息,修改或重置密码功能

关注系统,共享任意位置的网站并显示共享图像,活动流:用户可查看所关注用户上传的内容

目录

登录模块

创建项目

使用djiango身份认证框架

登录和注销视图

修改密码视图

重置密码视图

用户注册和用户个人信息

用户注册

拓展用户模型

​编辑使用消息框架

创建自定义身份认证


登录模块

创建项目

cmd

   >mkdir env

   > python -m venv env/bookmarks
#激活系统
.\env\bookmarks\Scripts\activate

激活虚拟环境并且创建项目:

.\env\bookmarks\Scripts\activate

>django-admin startproject bookmarks

并且切换到下一个目录中,创建一个app:

(bookmarks) PS D:\工作\bookmarks> cd bookmarks
(bookmarks) PS D:\工作\bookmarks\bookmarks> django-admin startapp account

并且在setting.py的INSTALLED_APPS中添加该应用:

INSTALLED_APPS = [
     'account',#身份认证模板放首位
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    ]

并且进行模型同步:

 python3 manage.py migrate

使用djiango身份认证框架

框架位置djnago.contrib.auth;与之前做的项目不同,这次加了个中间件,在请求或响应阶段以全局方式进行。

并且在account app中创建新的forms.py文件,在里面添加代码:

from django import forms


#该表单用于用户和数据库之间的身份认证
class LoginForm(forms.Form):
	username =forms.CharField()#
	password =forms.CharField(widget =forms.PasswordInput)
#在HTML中包含password,以便使浏览器将其视为密码输入
	

编辑该app的views.py:

from django.shortcuts import render
from django.shortcuts import HttpResponse
from django.contrib.aut import authenticate,login  #身份验证框架
from .forms import LoginForm

def user_login(request):
	if request.method =='POST':
		form =LoginForm(request.POST)#当user_login被调用时,将实例化form =LoginForm
		if form.is_valid():
			cd =form.cleaned_data#如果表单无效,将提醒用户哪个没写完整
			user =authenticate(request,username =cd['username'],password=cd['password'])#在数据库进行身份验证
		if user is not None:#验证成功,那么将检查是否处于活动状态
			if user.is_active:#如果用户处于未活动状态,则返回包含认证失败的信息
				Login(request,user)
				return HttpResponse('认证成功')
			else:
				return HttpResponse('认证失败')

		else:
			return  HttpResponse('无效登录')
	else :
		form =LoginForm()
	return render(request,'account/login.html',{'form':form})

注意事项:authenticcate()和login()差别,authenticcate()检查用户证书,如正确则返回一个User对象,login()则在当前会话中设置用户。

在account app中创建urls.py文件,设置路由:

from django.urls import path
from . import views

urlpatterns =[
    path('login/',views.user_login,name = 'login'),

]

并且在bookmarks的urls.py中,导入include,并且添加account的路由:

from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('account/',include('account.urls')),
]

在account下创建以下文件和文件夹,挡住那个是base.html:

base.html:

{% load static %}
<!DOCTYPE html>
<html>
<head>
	<title>{% block title %}{% endblock %}</title>
	<link href="{% static 'css/base.css' %}" rel="stylesheet">

</head>
<body>
	<div id="header">
		<span class="logo">Bookmarks</span>

	</div>
	<div id="content">
		{% block content %}
		{%  endblock %}
	</div>

</body>

login.html

{% extends "base.html" %}
{% block title %}Log-in{% endblock %}
{% block content %}

<h1>Log-in</h1>
<p>请进行登录</p>
<form method="post">
	{{form.as_p}}
	{% csrf_token %}
	<p><input type='submit' value="Log in"></p>
</form>

		{%  endblock %}

控制台再次再次输入:

python manage.py makemigrations

ython manage.py migrate

python manage.py createsuperuser

然后运行:

python manage.py runserver

没有设置首页,直接进入后台

进行添加:

填写:

Django提供基于类的视图以处理身份验证:

LoginView:处理表单和用户日志

LogoutView:注销用户

密码修改视图:

PasswordChange View:处理表单并修改用户密码

PasswordChangeDoneView:在成功修改密码后用户被重定向的成功视图

密码重置视图:

PasswoResetView:允许用户重置密码,并生成一个带有令牌的一次性使用链接,将其发送到用户的电子邮箱当中

PasswordResetDoneView:通知用户向其发送一封电子邮件,其中包含一个重置密码链接

PasswordResetConfirmView:允许用户设置新密码

PasswordResetCompleteView:在成功重置密码后用户被重定向的成功视图

登录和注销视图

修改accoun的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'),
	#登录和注销url
	path('login/',auth_views.LoginView.auth_views(),name='login'),
	path('logout/',auth_views.LoginView.auth_views(),name='logout'),

]

在templates中创建一个registration并且创建login.html:

{% extends "base.html" %}
{% block title %}Log-in{% endblock %}
{% block content %}
<h1>Log-in</h1>
{% if form.errors %}
<p>
	你的用户名和密码并不匹配
	请重新输入
</p>
{% else %}
<p>
	请使用下面的表格进行登录
</p>
{% endif %}
<div class="login-form">
	<form action="{% url 'login' %}" method="post">
		{{form.as_p}}
		{% csrf_token %}
		<input type="hidden" name="next" value="{{next}}" />
		<p><input type="submit" value="Log-in" ></p>

	</form>
		

</div>
{% enblock %}

在registration中创建logged_out.html模板:

在用户注销后,django将显示该模板

{% extends "base.html" %}
{% block title %}Logged out{% endblock %}
{% block content %}

<h1>Logged out</h1>
<p>
	成功注销
	你可以再次进行<a href="{% url 'login' %}">登录</a>。
</p>
{% endblock %}

在account的views.py进行添加:

from django.contrib.auth.decorators import login_required#当前用户是否被认证

#用来检查当前用户身份被认证,如果经过认证,则执行装饰视图,否则重定向到登录URL
@login_required
def dashboard(request):
	return render(request,'account/dashboard.html',{'section':dashboard})

templates的account添加dashboard.html:

{% extends "base.html" %}
{% block title %}Logged out{% endblock %}
{% block content %}
<h1>Dashboard</h1>
<p>欢迎来到你的操作台</p>
{% endblock %}

并且在urls.py添加路由:

path('',views.dashboard,name='dashboard'),

编辑项目的setting文件,添加:

LOGIN_REDIRECT_URL ='dashboard'
LOGIN_URL='login'
LOGOUT_URL='logout'

以上代码总结:添加了登录和注销视图。建立了玩家登录之后的操作台,添加了默认状态下使用这些ur

在base.html代码中添加以下代码,用来做登录和注销链接:

<head>
	<title>{% block title %}{% endblock %}</title>
	<link href="{% static 'css/base.css' %}" rel="stylesheet">

</head>
<body>
	<div id="header">
		<span class="logo">Bookmarks</span>
		{% if request.user.is_authenticated %}
		<ul class="menu">
			<li {% if section =="dashboard" %} class="selected" {% endif %}><a href="{% url "dashboard" %}">我的操作台</a></li>
			<li {% if section =="images" %} class="selected" {% endif %} ><a href="#">图片</a></li>
			<li {% if section =="people" %} class="selected" {% endif %} ><a href="#">形态</a></li>
			</ul>
		{% endif %}
		<span class="user">
			{% if request.user.is_authenticated %}
			Hello {{ request.user.first_name | default:request.user.username}},
			<a href="{% url "login" %}">注销</a>
			{% else %}
			<a href="{% url "logout" %}">登录</a>
			{% endif %}

		 </span>

	</div>

运行:

修改密码视图

在account的urls中:

 	#修改密码的视图,PasswordChangeView将处理表单以修改密码,PassChangeDoneView将在用户更改密码成功后添加一道信息
    path('password-change/',auth_views.PasswordChangeView.as_view(),name='password_change'),
    path('password-change/done/',auth_views.PasswordChangeDoneView.as_view(),name='password_change_done'),
    

并且在registration中创建password_change_form.html:

{% extends "base.html" %}
{% block title %}修改你的密码{% endblock %}
{% block content %}

<h1>修改你的密码</h1>
<p>
使用下面的表格更改您的密码
</p>
<form method="post">{{form.as_p}}
	<p><input type="submit" value="Change"></p>
	{% csrf_token %}
</form>
{% endblock %}

并在同一目录下创建另一个文件,password_change_done.html:

{% extends "base.html" %}
{% block title %}修改你的密码{% endblock %}
{% block content %}

<h1>修改你的密码</h1>
<p>
密码修改成功
</p>
{% endblock %}

打开网页:http://127.0.0.1:8000/account/password-change

重置密码视图

编辑account的urls.py文件,并且添加代码:

 	#修改密码的视图,PasswordChangeView将处理表单以修改密码,PassChangeDoneView将在用户更改密码成功后添加一道信息
。。。。。。。。。。。。。
    #重置密码操作
    path('password-reset/',auth_views.PasswordResetView.as_view(),name='password_reset'),
    path('password-reset/done/',auth_views.PasswordResetDoneView.as_view(),name='password_reset_confirm'),
    path('password-reset/complete/',auth_views.PasswordResetCompleteView.as_view(),name='password_reset_complete'),

并且在registration中添加新文件:password-reset_form.html:

{% extends "base.html" %}
{% block title %}重置你的密码{% endblock %}
{% block content %}

<h1>忘记密码</h1>
<p>输入你的邮箱来验证更改密码
</p>
<form method="post">
	{{form.as_p}}
	<p><input type="submit" value="Send e-mail"></p>
	{% csrf_token %}
</form>
{% endblock %}

同一目录下创建另外一个文件,password_reset_email.html,并且去添加以下代码:

Some asked for password reset for email {{email}}.Follow the link link below:
{{protocol}}://{{domain}}{% url "password_reset_confirm" uidb64=uid token=token %}
Your username,in case you've forgotten:{{user.get_username}}

<!--该html用来渲染发送至用户的电子邮箱,并且重置密码,其中含有视图生成的重置令牌 -->



进行添加文件password_reset_done.html:

{% extends "base.html" %}
{% block title %}重置你的密码{% endblock %}
{% block content %}

<h1>重置密码</h1>
<p>输入你的邮箱来验证更改密码</p>
<p>我们已将密码说明发送到您的邮箱</p>
<p>如果没有收到,请确定您输入注册时使用的地址</p>
{% endblock %}

再创建一个模板为password_reset_confirm.html:

{% extends "base.html" %}
{% block title %}重置你的密码{% endblock %}
{% block content %}

<h1>重置密码</h1>

{% if validlink %}
	<p>请输入新的密码</p>
	<form method="post">
		{{form.as_p}}
		{% csrf_token %}
		<p><input type="submit" value="Change my password"> </p>

	</form>
		{ % else % }
		<p>这个密码使用过了,请重新设置</p>


{% endblock %}

再添加password_reset_complete.html:

{% extends "base.html" %}
{% block title %}密码重置{% endblock %}
{% block content %}

<h1>密码设置</h1>
<p>您已经设置好你的密码了,你可以<a href="{% url "login" %}">进行登录</a></p>

{% endblock %}

在registration/login.html添加以下代码:

<div class="login-form">
	<form action="{% url 'login' %}" method="post">
		{{form.as_p}}
		{% csrf_token %}
		<input type="hidden" name="next" value="{{next}}" />
		<p><input type="submit" value="Log-in" ></p>

	</form>
		<p>
			<a href="{% url "password_reset" %}">忘记密码</a>


		</p>

</div>
{% endblock %}

并且在setting进行添加邮件发送类:

EMAIL_BACKEMD ="django.core.mail.backends.console.EmailBackend"
#设置邮箱发送类

运行:

注释掉url,用于自己的视图:

from django.urls import path,include
from django.contrib.auth import views as auth_views
from . import views

urlpatterns =[
    #path('login/',views.user_login,name = 'login'),
	#登录和注销url
	#path('login/',auth_views.LoginView.as_view(),name='login'),
	#path('logout/',auth_views.LogoutView.as_view(),name='logout'),

 	#修改密码的视图,PasswordChangeView将处理表单以修改密码,PassChangeDoneView将在用户更改密码成功后添加一道信息
    #path('password-change/',auth_views.PasswordChangeView.as_view(),name='password_change'),
    #path('password-change/done/',auth_views.PasswordChangeDoneView.as_view(),name='password_change_done'),
    
    #重置密码操作
    #path('password-reset/',auth_views.PasswordResetView.as_view(),name='password_reset'),
    #path('password-reset/confirm/<uidb64>/<token>/',auth_views.PasswordResetDoneView.as_view(),name='password_reset_confirm'),
    #path('password-reset/complete/',auth_views.PasswordResetCompleteView.as_view(),name='password_reset_complete'),

    path('',include('django.contrib.auth.urls')),
	path('',views.dashboard,name='dashboard'),


]

用户注册和用户个人信息

用户注册

创建一个简单的视图以使用户在网站上注册,初始状态下,我们需要创建一个表单,以使用户输入用户名,姓名和密码。

编辑account的forms.py,并且添加以下代码:

from  django.contrib.auth.models import User

class UserRegistrationForm(forms.ModelForm):
	password =forms.CharField(label='Password',widget=forms.PasswordInput)
	password2 =forms.CharField(label='Repeat Password',widget=forms.PasswordInput)

	class Meta:
		models =User
		fields=['username','first_name','email']

	#字段验证操作,验证密码是否相同
	def clean_password2(self):
		cd=self.clean_data
		if cd['password'] != cd['password2']:
			raise forms.ValidationError('密码不匹配')
		return cd['password2']

编辑account的views:

from .forms 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_done.html',{'new_user':new_user})

	else:
		user_form=UserRegistrationForm()
	return render(request,'account/register.html',{'user_form':user_form})

编辑account的urls.py文件:

path('register/',views.register,name='register')

在templates的account添加两个文件:register.html、register_done.html

register.html

{% extends "base.html" %}
{% block title %}创建一个用户{% endblock %}

{% block content %}

<h1>创建一个用户</h1>
<p>请对以下表单进行输入</p>
<form method="post">
	{{user_form.as_p}}
	{% csrf_token %}
	<p><input type='submit' value="Cretae ny account"></p>
</form>

		{%  endblock %}

register_done.html

{% extends "base.html" %}
{% block title %}欢迎{% endblock %}

{% block content %}

<h1>欢迎{{ new_user.first_name}}!</h1>
<p>请对以下表单进行输入</p>
<p>
	你的账号已成功注册。
	现在你可以进行<a href="{% url "login" %}">登录</a>


</p>

		{%  endblock %}

并且在registration的login.html添加:

<p>
	请使用下面的表格进行登录
	如果你没有账号,请进行<a href="{% url "register" %}">注册</a>
</p>

拓展用户模型

我们使用的User模型包含有限的字段集,使用我们需要对其进行拓展:创建一个资料模型。他包含与django模型的一对一广西,以及任何附加字段,一对一的关系类似于带yunique=true参数的ForeignKey字段,隐性的一对一关系,而不是多个元素管理器。

编辑account的models.py:

from django.db import models
from django.conf import settings

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 f'Profile of {self.user.username}'

安装Pillow并处理媒体文件

 pip install Pillow

编辑setting.py:

#用于处理用户上传的媒体文件
EMDIA_URL='media/'
MEDIA_ROOT=BASE_DIR / 'media'#路径

以及根目录的urls.py:

from django.contrib import admin
from django.urls import path,include
from django.conf import setting
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('account/',include('account.urls')),

]

#添加static帮助函数并利用开发服务器处理媒体文件
if settings.DEBUG:
    urlpatterns +=static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)

然后进行模型迁移;

python manage.py makemigrations

python manage.py migrate

然后在account的admin文件中添加注册模型:

from django.contrib import admin
#向管理网站中注册模型
from .models import Profile

@admin.register(Profile)
class ProfileAdmin(admin.ModelAdmin):
	list_display =['user','date_of_birth','photo']
	raw_id_fields=['user']

再运行网站

针对每个用户以手动的方式创建一个Profile对象,令其在网站上编辑资料,编辑account的forms.py文件:

from .models import Profile


#允许用户编辑其姓名和电子邮件
class UserEditForm(forms.ModelForm):
	class Meta:
		model =User
		fields ={'first_name','last_name','email'}

#允许用户编辑Profile的资料数据
class ProfileEditForm(forms.ModelForm):
	class Meta:
		model =Profile
		fields =['date_of_birth','photo']

并且编辑account的views.py文件:

from .models import Profile


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()
			#注册时,创建用户profile与其关联
			Profile.objects.create(user=new_user)
			return render(request,'account/register_done.html',{'new_user':new_user})

	else:
		user_form=UserRegistrationForm()
	return render(request,'account/register.html',{'user_form':user_form})


在这个文件中,编辑用户个人资料:

from .forms 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,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})

并且在urls添加上路由:

path('edit/',views.edit,name='edit'),

然后在templates/account中创建edit.html:

{% extends "base.html" %}

{% block title %}Edit your account{% endblock %}

{% block content %}
  <h1>Edit your account</h1>
  <p>You can edit your account using the following form:</p>
  <form method="post" enctype="multipart/form-data">
    {{ user_form.as_p }}
    {{ profile_form.as_p }}
    {% csrf_token %}
    <p><input type="submit" value="Save changes"></p>
  </form>
{% endblock %}

然后在bashboard.html添加一下路由:

{% extends "base.html" %}
{% block title %}Logged out{% endblock %}
{% block content %}
<h1>Dashboard</h1>

<p>欢迎来到你的操作台。
	你可以进行修改你的<a href="{% url "edit" %}" >信息</a>或者<a href="{% url "password_change" %}">修改你的密码</a></p>
{% endblock %}

使用消息框架

当用户和平台交互的时候,可能需要通知他们与特定的动作结果相关信息。django的框架可允许我们向用户显示单次通知。

我们将在base.html中添加以下代码实现全局通知:


	</div>
	{% if messages %}
	<ul class="messages">
		{% for message in messages %}
		<li class="{{ message.tags  }}">
			{{ message|safe}}
			<a href="#" class="close">x</a>
		</li>
		{% endfor %}
	</ul>
	{% endif %}
	<div id="content">
		{% block content %}
		{%  endblock %}
	</div>

打开account的views.py,添加以下代码:

from django.contrib import message


@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,files=request.FILES)


		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 updatingh your profile')

	else:
。。。。。。。。。。。。。。

创建自定义身份认证

在account app中创建一个新的文件,authentication.py:

#身份认证后端
from django.contrib.auth.models import User


class EmailAuthBackend:
    """
    Authenticate using an e-mail address.
    """
    def authenticate(self, request, username=None, password=None):#协同工作
        try:
            user = User.objects.get(email=username)
            if user.check_password(password):
                return user
            return None
        except (User.DoesNotExist, User.MultipleObjectsReturned):
            return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)#primary key,对与数据库每一条记录,是唯一标识符
        except User.DoesNotExist:
            return None

在setting中添加:

#用户证书通过ModelBackend被检查,如果未返回用户,证书则通过EmailAuthBackend被检查
AUTHENTICATION_BACKENDS =[
    'django.contrib.auth.backends.ModelBackend',
    'account.authentication.EmailAuthBackend',
    ]

为了防止多个用户用同一个邮箱地址注册,我们需要在forms.py文件UserRegistrationForm类中添加以下代码:

	#否则多个用户用同一个邮箱地址注册
	def clean_email(self):
		data=self.cleaned_data['email']
		if User.objects.filter(email=data).exists():
			raise forms.ValidationError('这个邮箱已被注册')
		return data

我们还需要把用户修改信息部分进行设置,防止用户修改为其他用户的邮箱,在UserEditForm中添加代码:

	#防止用户修改为其他用户的邮箱
	def clean_email(self):
		data=self.cleaned_data['email']
		qs =User.objects.exclude(id=self.instance.id)+.filter(email=data)
		if qs.ex():
			raise forms.ValidationError('这个邮箱已被注册')
		return data

实现社交身份验证

我们将利用Facebook,Twitter和Google,qq向网站中添加社交身份验证

将使用OAuth2.0进行身份认证,OAuth代表开发授权。

pip install git+https://github.com/python-social-auth/social-app-django.git

在setting的INSTALLED_APPS添加:'social_django'

然后继续数据库同步:

python manage.py migrate

然后在bookmarks的urls.py中添加:

path('social-auth/',include('social_django.urls',namespace='social'))

然后在这里继续进行添加:C:\Windows\System32\drivers\etc的host文件中:

127.0.0.1 mysite.com

进行社交认证

然后在这个网页中会看到这样:

我们可以通过编辑setting.py,调整ALLOWED_HOSTS设置项:

ALLOWED_HOSTS = ['mysite.com','localhost','127.0.0.1']

通过HTTPS运行开发服务器

通过安装以下协议,让TLS设置该服务器为安全服务器

pip install django-extensions

pip install werkzeug

pip install pyOpenSSL

然后在setting中INSTALLED_APPS添加:

'django_extensions',

然后我们使用以下代码运行服务器:

python manage.py runserver_plus --cert-file cert.crt

注意,我们使用的是https;//而不是http://:

 会出现这个错误

这是正常的,打开高级进行访问就可以了

利用QQ进行身份认证

在setting.py的AUTHENTICATION_BACKENDS设置代码行:

'social_core.backends.facebook.FacebookOAuth2',

我们需要一个QQ开发者账号,且需要一个新的QQ应用程序,打开QQ开发平台进行注册

需要等待,暂时跳过

共享网站内容

待续。。。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值