一、需求背景
使用zinnia搭建的博客,因为评论系统比较简单,经常被注入垃圾评论,很不爽。一直想给这个博客整合个评论系统,但实在没啥可选的,国内多说已经不行了,国外Disqus访问不稳定。思索再三,还是决定整合django-allauth,把博客设置成登录后才能评论。
二、开发环境
- Python 3.5.1
- Django 1.11.11
- django-allauth 0.35.0
- django-contrib-comments 1.8.0
三、安装django-allauth
把开发环境的内容写入requirements.txt
pip install -r requirements.txt
在INSTALLED_APPS中注册,这里同时注册了account和socialaccount两个应用。provider选了微博、微信、LinkedIn,本文写完时只整合好了LinkedIn。
INSTALLED_APPS = [
...
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.github',
'allauth.socialaccount.providers.weibo',
'allauth.socialaccount.providers.weixin',
'allauth.socialaccount.providers.linkedin_oauth2',
]
AUTHENTICATION_BACKENDS = (
# Needed to login by username in Django admin, regardless of `allauth`
'django.contrib.auth.backends.ModelBackend',
# `allauth` specific authentication methods, such as login by e-mail
'allauth.account.auth_backends.AuthenticationBackend',
)
默认的登录/注销链接,默认比较简陋,可以根据自己的网站进行美化
<a href="{% url 'account_logout' %}">{% trans "Log out" %}</a>
<a href="{% url 'account_login' %}">log in</a>
翻开源码,查到默认的login、logout的模板位置,可以酌情重载
django-allauth/allauth/templates/account/login.html
django-allauth/allauth/templates/account/logout.html
当然也可以重写View函数,比如这样
from allauth.account import views
class SigninView(views.LoginView):
template_name = 'signin/index.html'
def dispatch(self, request, *args, **kwargs):
response = super(SigninView, self).dispatch(request, *args, **kwargs)
return response
def form_valid(self, form):
return super(SigninView, self).form_valid(form)
class SignupView(views.SignupView):
template_name = 'signup/index.html'
def get_context_data(self, **kwargs):
context = super(SignupView, self).get_context_data(**kwargs)
return context
重写模板后,在url中定义一下就可以了
url(r'^signin/?$', views.signin_view),
url(r'^signup/?$', views.signup_view),
这里强制使用邮箱作为登录名,用邮箱来标识人,纯个人爱好,在settings.py中加入以下四行
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = 'email'
最后要记得migrate一下。
四、注册第三方OAuth,使用LinkedIn账户登录
为什么用LinkedIn,因为微信审批要7天,LinkedIn当场直接就可以申请OAuth2.0的应用
申请App网址:https://www.linkedin.com/secure/developer?newapp=
登录注册后得到key 和 secret,并添加callback地址

在Django后台Admin管理中进入Social Account的Social applications添加应用

新建一个App,填入key 和 secret ,红框中的地址因为目前是本地调试,部署后需要根据实际网址调整。

五、与django-contrib-comments整合,登录才能留言
找到zinnia\templates\comments\zinnia\entry\form.html
改之前的代码为这样,匿名用户输入用户名,邮箱即可发言,登录的用户,只显示登录名和发言框。
{% for field in form %}
{% if field.is_hidden %}{{ field }}{% else %}
{% if user.email and field.name in "namemailurl" %}{% else %}
<div{% if field.errors %} class="error"{% endif %}{% ifequal field.name "honeypot" %} style="display:none;"{% endifequal %}>
{{ field.label_tag }}
{% if field.errors %}{{ field.errors }}{% endif %}
{{ field }}
</div>
{% endif %}
{% endif %}
{% endfor %}
<p class="auth">
{% trans "Comment as" %} <strong>{% firstof user.get_full_name user.get_username %}</strong>. <a href="{% url 'account_logout' %}">{% trans "Log out" %}</a>.
</p>
<p class="submit">
<input type="submit" name="submit" class="submit-post" value="{% trans "Post" %}" />
<input type="submit" name="preview" class="submit-preview" value="{% trans "Preview" %}" />
</p>
将这段调整一下,没登录提示请登录,登陆后才能发言:
{% if user.is_authenticated %}
<legend>{% trans "Post your comment" %}</legend>
<input type="hidden" name="next" value="{% url 'zinnia:comment_success' %}"/>
{{ form.comment }}
<div style="display:none;">
{{ form.honeypot }}
</div>
{{ form.content_type }}
{{ form.object_pk }}
{{ form.timestamp }}
{{ form.security_hash }}
<p class="auth">
{% trans "Comment as" %} <strong>{% firstof user.get_full_name user.get_username %}</strong>. <a href="{% url 'account_logout' %}">{% trans "Log out" %}</a>.
</p>
<p class="submit">
<input type="submit" name="submit" class="submit-post" value="{% trans "Post" %}" />
<input type="submit" name="preview" class="submit-preview" value="{% trans "Preview" %}" />
</p>
{% else %}
<p>Please <a href="{% url 'account_login' %}">log in</a> to leave a comment.</p>
{% endif %}
六、看看效果
改版前,未登录用户可以留言

改版后

登录后:

8955 on #
留爪