django 开发网站-(App)user 使用第三方登陆
一个网站的用户系统可谓是核心系统,这里我放在最前面来创建。我们将会用到githu的第三方登陆依赖的还是django的allauth。并添加模板函数,来获取用户的信息,并对前端代码进行处理,作选择判断。
主要还是介绍在win10上面的操作过程
主要用的技术:python3.8;django2
编辑器/ide:vscode、sublime——text、powershell、web
githu项目地址:https://github.com/Freen247/django_blog 老爷们,给个star吧
网站前端的初始化静态文件存在我的github上哦:https://github.com/Freen247/django_blog/bl...
python开发,虚拟环境第一步。
PS F:\demo> .\env\Scripts\activate
(env) PS F:\demo>
django的第三方登陆
Django-allauth,它不仅包含一整套的本地注册、登录、管理的解决方案,还支持GitHub、Twitter、微博、微信甚至百度等几十种第三方登录方式
下载包:
(env) PS F:\demo\django_blog> pip install django-allauth
(env) PS F:\demo\django_blog> pip install django-crispy-forms
在settings中修改注册的app。
注释掉原来的登陆方式
INSTALLED_APPS = [
'django.contrib.admin',
# 'django.contrib.auth',# 原来的登陆方式可以删除了。
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
#apps
'apps.index',
#lib
'imagekit', # 注册 imagekit处理压缩图片
'mdeditor',#django mdeditor富文本编辑器
'uuslug',#将中文转化成拼音 slug 的插件
'markdown',#python自带的md翻译工具
# allauth需要注册的应用
'crispy_forms',
'django.contrib.auth',
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
# github 登陆
'allauth.socialaccount.providers.github',
]
在settings.py中配置登陆的回调路由:
# 在继承user时要重载AUTH_USER_MODEL
AUTH_USER_MODEL = 'user.Ouser'
# 登陆成功后的回调路由
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/'
SOCIAL_AUTH_REDIRECT_IS_HTTPS = True
AUTHENTICATION_BACKENDS = (
# auth 身份验证 与 allauth 无关
'django.contrib.auth.backends.ModelBackend',
# allauth 身份验证
'allauth.account.auth_backends.AuthenticationBackend',
)
# Email setting
# SMTP服务器,我使用的是sendclound的服务
# 是否使用了SSL 或者TLS
#EMAIL_USE_SSL = True
#EMAIL_USE_TLS = True
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.outlook.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'aboyinsky@outlook.com'
EMAIL_HOST_PASSWORD = '1026shenyang'
DEFAULT_FROM_EMAIL = 'aboyinsky@outlook.com'
# 这里是随便写的一个 也可以是 /accounts/logout/ 测试比较随便
LOGIN_REDIRECT_URL = '/'
# 要求用户注册时必须填写email
ACCOUNT_EMAIL_REQUIRED = True
# 注册中邮件验证方法:“强制(mandatory)”,“可选(optional)【默认】”或“否(none)”之一。
# 开启邮箱验证的话,如果邮箱配置不可用会报错,所以默认关闭,根据需要自行开启
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
# 作用于第三方账号的注册
# SOCIALACCOUNT_EMAIL_VERIFICATION = 'optional' | 'mandatory' | 'none'
# 邮件发送后的冷却时间(以秒为单位)
ACCOUNT_EMAIL_CONFIRMATION_COOLDOWN = 10
# # 邮箱确认邮件的截止日期(天数)
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 1
# # 指定要使用的登录方法(用户名、电子邮件地址或两者之一)"username" | "email" | "username_email"
ACCOUNT_AUTHENTICATION_METHOD="username_email"
# # 登录尝试失败的次数
# ACCOUNT_LOGIN_ATTEMPTS_LIMIT(=5)
# # 从上次失败的登录尝试,用户被禁止尝试登录的持续时间
# ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT(=300)
# # 更改为True,用户一旦确认他们的电子邮件地址,就会自动登录
ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = True
# # 更改或设置密码后是否自动退出
# ACCOUNT_LOGOUT_ON_PASSWORD_CHANGE(=False)
# 更改为True,用户将在重置密码后自动登录
修改settings.py中的teplates:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'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',
# allauth 需要 django 提供这个处理器
'django.template.context_processors.request',
],
},
},
]
创建user(app)并进行重构。
创建app,user
python manage.py startapp user
将user文件夹移动到apps中
添加forms.py文件:
from django import forms
from .models import Ouser
class UserForm(forms.Form):
username = forms.CharField(max_length=30)
password = forms.CharField(max_length=50)
password2 = forms.CharField(max_length=50)
email = forms.CharField(max_length=50)
class loginForm(forms.Form):
username = forms.CharField(max_length=30)
password = forms.CharField(max_length=50)
class ProfileForm(forms.ModelForm):
class Meta:
model = Ouser
fields = ['link', 'avatar']
重新继承原始登陆的user类但是进行重构:
models.py:
from django.db import models
from django.contrib.auth.models import AbstractUser
from imagekit.models import ProcessedImageField
from imagekit.processors import ResizeToFill
from django.conf import settings
from django.shortcuts import reverse
from uuslug import slugify
class Ouser(AbstractUser):
# 扩展用户个人网站字段
link = models.URLField('个人网址', blank=True, help_text='提示:网址必须填写以http开头的完整形式')
# contact = models.ManyToManyField(Contacts, verbose_name='通讯录',default='1')
# 扩展用户头像字段
avatar = ProcessedImageField(
upload_to='avatar/%Y%m%d',
default='avatar/default.png',
verbose_name='头像',
processors=[ResizeToFill(80, 80)],
blank=True
)
class Meta:
verbose_name = '用户' # 定义网站管理后台表名
verbose_name_plural = verbose_name
ordering = ['id']
def __str__(self):
return self.username
def save(self, *args, **kwargs):
super(Ouser, self).save(*args, **kwargs)
def db_delete_user(self):
deleteResult = Ouser.objects.filter(username=self.username).delete()
if deleteResult:
return 1
在admin中注册user,admin.py:
from django.contrib import admin
from .models import Ouser
@admin.register(Ouser)
class OuserAdmin(admin.ModelAdmin):
list_display = ('username', 'email', 'is_staff', 'is_active', 'date_joined')
fieldsets = (
('基础信息', {'fields': (('username', 'email'), ('link','contact', 'password'))}),
('权限信息', {'fields': (('is_active', 'is_staff', 'is_superuser'),
'groups', 'user_permissions')}),
('重要日期', {'fields': (('last_login', 'date_joined'),)}),
)
filter_horizontal = ('groups', 'user_permissions',)
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
search_fields = ('username', 'email')
url.py定向于个人信息和修改个人信息界面:
# -*- coding: utf-8 -*-
from django.conf.urls import url
from .views import profile_view, change_profile_view
app_name='accounts'
urlpatterns = [
url(r'^profile/$',profile_view,name='profile'),
url(r'^profile/change/$',change_profile_view,name='change_profile'),
]
迁移数据库:
(env) PS F:\demo\django_blog> python .\manage.py makemigrations
No changes detected
访问127.0.0.1:8000,没问题。
接下来实现在web上的登陆:
首先获取accounts的登陆url,在主urls.py,django/urls.py中添加两条数据:
urlpatterns = [
path('admin/', admin.site.urls),
# index
path('', include('apps.index.urls'), name='index'),
#用户
path('accounts/', include('allauth.urls'), name='accounts'),
path('accounts/', include('apps.user.urls'), name='accounts'),
]
运行项目。打开本地8000端口。我们试着访问登陆的url http://127.0.0.1:8000/accounts/login/?next=/
成功访问,但是还没有界面。
在web上修改前端界面,实现登陆
先对我们原来的最底层的base.html进行代码修改:
头部注册user的标签函数
<!DOCTYPE html>
{% load static user_tags%}
<html lang="en-US">
修改成:
{% if user.is_authenticated %}
<ul class="navbar-nav">
<div class="dropdown for-notification">
<button class="btn btn-secondary dropdown-toggle" type="button" id="notification" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<i class="fa fa-bell"></i>
<span class="count bg-danger">test</span>
</button>
<div class="dropdown-menu dropdown-menu-right mt-0 rounded-0 border-0" aria-labelledby="notification">
<a class="dropdown-item media" href="">
<i class="fa fa-bullhorn mx-1"></i>
<p>未读消息|管理消息</p>
</a>
<a class="dropdown-item media" href="">
<i class="fa fa-warning"></i>
<p>{{ each.create_p }}回复你:{{ each.comment.content|truncatechars:15|safe }}
</p>
</a>
</div>
</div>
<div class="dropdown for-message">
<button class="btn btn-secondary dropdown-toggle" type="button" id="message" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<i class="fa fa-envelope"></i>
<span class="count bg-danger">3</span>
</button>
<div class="dropdown-menu dropdown-menu-right mt-0 rounded-0 border-0" aria-labelledby="message">
<p class="red">You have 3 Mails</p><a class="dropdown-item media" href="#">
<span class="photo media-left"><img alt="avatar" src="#" alt="。"></span>
<div class="message media-body">
<span class="name float-left">Jonathan Smith</span>
<span class="time float-right">Just now</span>
<p>Hello, this is an example msg</p>
</div>
</a>
<a class="dropdown-item media" href="#">
<span class="photo media-left"><img alt="avatar" src="#"></span>
<div class="message media-body">
<span class="name float-left">Jack Sanders</span>
<span class="time float-right">5 minutes ago</span>
<p>Lorem ipsum dolor sit amet, consectetur</p>
</div>
</a>
<a class="dropdown-item media" href="#">
<span class="photo media-left"><img alt="avatar" src="#" alt="。"></span>
<div class="message media-body">
<span class="name float-left">Cheryl Wheeler</span>
<span class="time float-right">10 minutes ago</span>
<p>Hello, this is an example msg</p>
</div>
</a>
</div>
</div>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false" title="{{ user },欢迎回来!">
<img class="avatar" src="{{ user.avatar.url }}" alt="Freen247">
</a>
<div class="dropdown-menu dropdown-menu-right mt-0 rounded-0 border-0" aria-labelledby="navbarDropdown">
<a class="dropdown-item pl-3" href="/accounts/profile/"><i
class="fa fa-fw fa-user text-info mr-2"></i>个人资料</a>
<a class="dropdown-item pl-3" href="/accounts/logout/"><i
class="fa fa-fw fa-sign-out text-info mr-2"></i>退出</a>
</div>
</li>
</ul>
{% else %}
<ul class="navbar-nav">
<li class="nav-item mr-2">
<a class="nav-link py-md-3" href="/accounts/login/?next=/">登录</a>
</li>
<li class="nav-item">
<a class="nav-link py-md-3" href="/accounts/signup/?next=/">注册</a>
</li>
</ul>
{% endif %}
我们打开env\Lib\site-packages\allauth\templates\account中的所有这些文件移动到user/templates中:
对其中base.html进行重构:
注意下面中所继承的base.html就是继承的index中的base.html。请不要弄混了。
{% extends "base.html" %}
{% load static user_tags %}
{% block metas %}
<meta name="description" content="用户账号管理,使用django-allauth社交用户系统,支持微博、Github等社交账号登录,加入{{ site_end_title }},查看更多信息。">
<meta name="keywords" content="django-allauth,社交用户系统,OAuth 2.0">
{% endblock %}
{% block top_file %}
<link href="{% static 'account/account.css' %}?v=20171229.019906" rel="stylesheet">
{% endblock %}
<div class="freen-author-box freen-widget">
{% block mdeditor_contain %}
<div class="container">
<div class="row">
<div class="col-12 col-sm-8 col-md-6 offset-sm-2 offset-md-3 px-xl-5">
<div class="card rounded-0 px-3 px-lg-4">
<div class="card-header text-center bg-white py-2">
<h3 class="my-1 text-info">{% block user_title %}账号管理{% endblock %}</h3>
</div>
<div class="card-body card-login">{% block content %}{% endblock %}</div>
<div class="text-center mb-5" id="social-login">
<div class="login-title">
<span>快速登录</span>
</div>
<div class="login-link">
{% get_request_param request 'next' as next_url %}
<a class="mx-4" href="/accounts/github/login/?next={{ next_url }}" title="社交账号登录有点慢,请耐心等候!"><i class="fa fa-github fa-2x"></i></a>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
</div>
{% block end_file %}
{% block extra_body %}
{% endblock %}
{% endblock %}
前端加载用户头像
修改settings中的配置文件,添加:
# 媒体文件地址
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
MEDIA_ROOT和MEDIA_URL是用户上传文件保存、访问的位置:
-
upload_to。有了这个参数,文件上传后将自动保存到项目根目录的media文件夹中。 os.path.join(MEDIA_ROOT, 'media/')指定了media文件夹的位置。
-
MEDIA_URL代表用户通过URL来访问这个本地地址的URL。设置好这个参数后,用户就可以通过解析url,很方便的获取文件的地址。这样做的好处是避免的硬编码,让代码更容易维护。
Django框架擅长的是对逻辑的处理,而对图片这类文件的处理则非常的耗时。因此在实际的生产环境中(即产品上线之后),通常是有专门的Web服务器来处理文件的访问。
而在开发阶段我们不会在意效率问题,所以Django也提供了方法,让开发服务器能够处理图片。
与此我们已经将用户的头像添加到了指定的文件中,但是还没法访问。
在django_blog/urls.py中添加这行:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
这样子前端通过调用用户的avatar属性就可以调用到用户的头像url。
创建文件夹templatetags,编写获取user信息的tags文件user_tags.py,
在上面的base文件中已经进行载入:
# 创建了新的tags标签文件后必须重启服务器
from django import template
from ..models import Ouser
from django.db.models.aggregates import Count
register = template.Library()
@register.simple_tag
def get_user_avatar_tag(user):
'''返回用户的头像,是一个img标签'''
return {'user':user}
@register.simple_tag
def get_users_list():
'''返回全部用户字典'''
return Ouser.objects.all()
@register.simple_tag
def get_users_num():
'''返回全部用户的数量'''
return Ouser.objects.count()
@register.simple_tag
def get_users_bynameid(the_name,the_id):
'''按照昵称和id获取用户'''
return Ouser.objects.filter(username=the_name,id=the_id)
@register.simple_tag
def get_request_param(request, param, default=None):
"""获取请求的参数"""
return request.POST.get(param) or request.GET.get(param, default)
我们访问网站,http://127.0.0.1:8000/accounts/login/?next=/
顺利的登陆,
因为刚才在settings中添加的配置文件中,表示登陆的用户需要邮箱验证,所有会发送一封邮件。
邮件的内容可以在password_reset_key_message.txt中进行修改:
到这里我们就实现了对django中user的重构。
加载github第三方登陆。
另外需要注意的是django-allauth所注册的账号与django内置的本地账号是通用的,也就是说通过内置User创建的账号,是可以通过django-allauth登录的。
有了django-allauth,
在settings中我们需要在入app,注意哦,在之前的操作中我们已经载入了。
# github 登陆
'allauth.socialaccount.providers.github',
我们需要在github中申请key
注册登陆的api,https://github.com/settings/applications/n...。
callbackd地址:http://127.0.0.1:8000/accounts/github/logi...
The flow to authorize users for your app is:
- Users are redirected to request their GitHub identity
- Users are redirected back to your site by GitHub
- Your app accesses the API with the user's access token
点击确认后,获取KEY
Client ID
ce721====78bf
Client Secret
971687ce3c2381=====15e9d514935d0b6862
进入后台界面,添加site:
添加 social application
尝试第三方登陆
成功:
其实第三方登陆和api一样不是很难,只需要key和url定向就可以实现,微博、微信的登录方式大致都遵循这个流程;本章虽然加载了微博的接口,但是限于篇幅并没有配置,请读者查阅官方文档去实现。
用户登陆退出消息提醒
<!--消息块-->
{% if messages %}
<div class="container">
{% for message in messages %}
<div class="alert {% if message.tags %}alert-{{ message.tags }}{% else %}alert-secondary{% endif %} alert-dismissible rounded-0 fade show"
role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endfor %}
</div>
{% endif %}
原址:https://boywithacoin.cn/
github:https://github.com/Freen247/django_blog
本作品采用《CC 协议》,转载必须注明作者和本文链接