最近使用Django+Nginx+UWSGI的方式,实现了一个简单的个人博客项目。
主要功能包括注册、登录、发表博客、发表评论、博客列表及博客搜索、博客主页显示等等。
本文介绍首先实现的功能,也就是最基本的登录和注册功能。
修改settings.py文件
INSTALLED_APPS = [
# 添加验证码
'captcha',
]
DATABASES = {
# 数据库使用的是Mysql
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'blog_ex',
'USER': 'root',
'PASSWORD': '123456',
'HOST': '127.0.0.1',
'PORT': 3306,
}
}
# 设置静态资源路径
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
# 图形验证码设置
# 格式
CAPTCHA_OUTPUT_FORMAT = u'%(text_field)s %(image)s %(hidden_field)s'
# 干扰项设置
CAPTCHA_NOISE_FUNCTIONS = (
'captcha.helpers.noise_null',
'captcha.helpers.noise_arcs',
'captcha.helpers.noise_dots',
)
# 图片样式
CAPTCHA_IMAGE_SIZE = (100, 30)
CAPTCHA_BACKGROUND_COLOR = '#ffffff'
# 使用随机字符
CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.random_char_challenge'
# 字符个数
CAPTCHA_LENGTH = 4
CAPTCHA_TIMEOUT = 1
还有几个注意事项:
修改models.py文件,创建类,每个类对应数据库中的一张表。
from django.contrib.auth.models import AbstractUser
from django.db import models
# 用户信息
class UserRe(AbstractUser):
phones = models.CharField(max_length=20, null=True)
email = models.EmailField(null=True)
gender = models.CharField(max_length=10)
class Meta(AbstractUser.Meta):
db_table = 'user_re'
# 博客分类
class BlogCategory(models.Model):
cid = models.IntegerField(primary_key=True)
cname = models.CharField(max_length=60)
blogcount = models.IntegerField(default=0)
class Meta:
db_table = 'blog_category'
# 博客信息
class BlogPost(models.Model):
id = models.IntegerField(primary_key=True)
author = models.CharField(max_length=60)
title = models.CharField(max_length=600)
content = models.CharField(max_length=600)
classname = models.CharField(max_length=60)
replycount = models.IntegerField(default=0)
addtime = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'blog_post'
# 回复信息
class BlogReply(models.Model):
id = models.IntegerField(primary_key=True)
bid = models.IntegerField()
author = models.CharField(max_length=60)
content = models.CharField(max_length=600)
addtime = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'blog_reply'
创建完毕后,需要进行数据库迁移,才能在数据库中生成对应的表。
python manage.py makemigrations
python manage.py migrate
如效果图所示,注册和登录界面都依赖表单来完成,用户相当于是在填写表单信息。如果填写的信息符合相关规范,提交就能通过,否则提示对应的错误信息。
添加forms.py文件,用于自定义实现登录表单和注册表单。
import re
from captcha.fields import CaptchaField
from django import forms
from django.core.exceptions import ValidationError
from App01.models import UserRe
# 验证密码是否符合规范
def check_password(pwd):
if pwd.isdigit():
raise ValidationError('密码不能只包含数字')
# 验证是否是合法手机号
def check_phone(phone_num):
if not re.match(r'^(13[0-9]|14[156789]|15[0-3,5-9]|166|17[0135678]|18[0-9]|19[89])\d{4}\d{4}$', phone_num, re.I):
raise ValidationError('无效的手机号')
# 自定义注册表单
class RegisterForm(forms.Form):
username = forms.CharField(min_length=6, required=True, error_messages={
'required': '用户名不能为空',
'min_length': '用户名至少由6位字符组成'
})
password = forms.CharField(min_length=6,
max_length=12,
required=True,
validators=[check_password],
error_messages={
'required': '密码不能为空',
'min_length': '密码至少由6位字符组成',
'max_length': '密码至多由12位字符组成',
})
confirm_password = forms.CharField(min_length=6,
max_length=12,
required=True,
error_messages={
'required': '密码不能为空',
'min_length': '密码至少由6位字符组成',
'max_length': '密码至多由12位字符组成',
})
email = forms.EmailField(error_messages={'invalid': '无效的邮箱格式'})
phone = forms.CharField(required=True, validators=[check_phone])
captcha = CaptchaField()
def clean_username(self):
username = self.cleaned_data.get('username')
if UserRe.objects.filter(username=username).first():
raise ValidationError('用户名重复')
return username
def clean(self):
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
if password != confirm_password:
raise ValidationError({'confirm_password': ['两次密码输入不匹配']})
return self.cleaned_data
# 自定义登录表单
class LoginForm(forms.Form):
username = forms.CharField(required=True, error_messages={'required': '用户名不能为空'})
password = forms.CharField(required=True, error_messages={'required': '密码不能为空'})
captcha = CaptchaField()
修改urls.py文件,此处只列出注册和登录部分使用的路由信息。
from django.urls import path
from App01 import views
app_name = 'App01'
urlpatterns = [
# 登录
path('login/', views.user_login, name='login'),
# 注册
path('register/', views.user_register, name='register'),
# 登出
path('logout/', views.user_logout, name='logout'),
]
修改views.py文件。我在项目中使用的是FBV(function base views)的方式,使用函数处理请求。还有另一种方式是CBV(class base views),使用类处理请求。
# 用户登录
def user_login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
# 使用自定义登录表单
form = LoginForm(request.POST)
user = authenticate(request, username=username, password=password)
# 判断用户是否存在
if user:
# 判断登录信息是否符合规范
if form.is_valid():
login(request, user)
return redirect(reverse('App01:index'))
else:
return render(request, 'blog/login.html', locals())
else:
login_errors = '用户名或密码错误'
return render(request, 'blog/login.html', locals())
form = LoginForm()
return render(request, 'blog/login.html', locals())
# 用户注册
def user_register(request):
if request.method == 'POST':
# 使用自定义注册表单
form = RegisterForm(request.POST)
gender = request.POST.get('gender')
# 判断表单验证是否通过
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
email = form.cleaned_data.get('email')
phones = form.cleaned_data.get('phone')
# 创建用户对象,存入数据库
user = UserRe.objects.create_user(username=username, password=password, email=email, phones=phones, gender=gender)
login(request, user)
return redirect(reverse('App01:index'))
else:
return render(request, 'blog/register.html', locals())
form = RegisterForm()
return render(request, 'blog/register.html', locals())
# 用户注销登录
def user_logout(request):
logout(request)
return redirect(reverse('App01:index'))
修改register.html,完成注册页面(此处只展示表单部分代码)
<form class="form-horizontal" action="{% url 'App01:register' %}" method="post">
{% csrf_token %}
<div class="control-group">
<div class="controls">
<h4>Register</h4>
</div>
</div>
<div class="control-group">
<label for="inputEmail" class="control-label">Username </label>
<div class="controls">
<input id="inputEmail" type="text" placeholder="Username" name="username" ><br>
<span>
{# 出错时显示错误信息 #}
{% for error in form.username.errors %}
<span>{{ error }}</span><br>
{% endfor %}
</span> <br>
</div>
</div>
{# 密码、邮箱、手机号写法同用户名类似,此处省略 #}
<div class="control-group">
<label for="inputCapcha" class="control-label">Captcha </label>
<div class="controls">
{{ form.captcha }}<span>{{ form.captcha.errors.0 }}</span><br>
</div>
</div>
<div class="control-group">
<div class="controls">
<input type="submit" value="Register">
</div>
</div>
</form>
至此,个人博客的用户注册和登录界面就完成了。整个过程最重要的两部分就是创建模型和创建自定义表单类。这两步完成之后,剩下的就是在视图函数中进行调用了,如果对相关原理比较熟悉的话,实现起来还是很容易的。