项目地址

项目主要模块

模块 功能
注册 图形验证、短信验证
登录 状态保持、Cookie、Session
个人中心 图片上传、更新数据
发布博客 数据入库
博客首页 数据分页
博客详情 博客详情数据展示、评论功能

项目环境:

python 3.6 Django 3.2.9

创建项目:

  1. django-admin startproject djangoBlong

配置mysql

  1. pip install PyMySQL

settings.py

  1. DATABASES = {
  2. 'default': {
  3. 'ENGINE': 'django.db.backends.mysql', # 数据库引擎
  4. 'HOST': '127.0.0.1', # 数据库主机
  5. 'PORT': 3306, # 数据库端口
  6. 'USER': 'root', # 数据库用户名
  7. 'PASSWORD': '123456', # 数据库用户密码
  8. 'NAME': 'blog' # 数据库名字
  9. },
  10. }

init.py文件中,添加如下代码

  1. import pymysql
  2. pymysql.install_as_MySQLdb()

image.png

配置Redis

  1. pip install django-redis

settings.py文件末尾添加

  1. CACHES = {
  2. "default": { # 默认
  3. "BACKEND": "django_redis.cache.RedisCache",
  4. "LOCATION": "redis://127.0.0.1:6379/0",
  5. "OPTIONS": {
  6. "CLIENT_CLASS": "django_redis.client.DefaultClient",
  7. }
  8. },
  9. "session": { # session
  10. "BACKEND": "django_redis.cache.RedisCache",
  11. "LOCATION": "redis://127.0.0.1:6379/1",
  12. "OPTIONS": {
  13. "CLIENT_CLASS": "django_redis.client.DefaultClient",
  14. }
  15. },
  16. }
  17. SESSION_ENGINE = "django.contrib.sessions.backends.cache"
  18. SESSION_CACHE_ALIAS = "session"

default:

  • 默认的Redis配置项,采用0号Redis库。

session:

  • 状态保持的Redis配置项,采用1号Redis库。

SESSION_ENGINE

  • 修改session存储机制使用Redis保存。

SESSION_CACHE_ALIAS:

  • 使用名为”session”的Redis配置项存储session数据。

    配置日志

    settings.py文件末尾添加

    1. import os
    2. LOGGING = {
    3. 'version': 1,
    4. 'disable_existing_loggers': False, # 是否禁用已经存在的日志器
    5. 'formatters': { # 日志信息显示的格式
    6. 'verbose': {
    7. 'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
    8. },
    9. 'simple': {
    10. 'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
    11. },
    12. },
    13. 'filters': { # 对日志进行过滤
    14. 'require_debug_true': { # django在debug模式下才输出日志
    15. '()': 'django.utils.log.RequireDebugTrue',
    16. },
    17. },
    18. 'handlers': { # 日志处理方法
    19. 'console': { # 向终端中输出日志
    20. 'level': 'INFO',
    21. 'filters': ['require_debug_true'],
    22. 'class': 'logging.StreamHandler',
    23. 'formatter': 'simple'
    24. },
    25. 'file': { # 向文件中输出日志
    26. 'level': 'INFO',
    27. 'class': 'logging.handlers.RotatingFileHandler',
    28. 'filename': os.path.join(BASE_DIR, 'logs/blog.log'), # 日志文件的位置
    29. 'maxBytes': 300 * 1024 * 1024,
    30. 'backupCount': 10,
    31. 'formatter': 'verbose'
    32. },
    33. },
    34. 'loggers': { # 日志器
    35. 'django': { # 定义了一个名为django的日志器
    36. 'handlers': ['console', 'file'], # 可以同时向终端与文件中输出日志
    37. 'propagate': True, # 是否继续传递日志信息
    38. 'level': 'INFO', # 日志器接收的最低日志级别
    39. },
    40. }
    41. }

    创建日志目录:
    image.png
    日志记录器的使用
    不同的应用程序所定义的日志等级可能会有所差别,分的详细点的会包含以下几个等级:

  • FATAL/CRITICAL = 重大的,危险的

  • ERROR = 错误
  • WARNING = 警告
  • INFO = 信息
  • DEBUG = 调试
  • NOTSET = 没有设置 ```python import logging

创建日志记录器

logger = logging.getLogger(‘django’)

输出日志

logger.debug(‘测试logging模块debug’) logger.info(‘测试logging模块info’) logger.error(‘测试logging模块error’)

  1. <a name="koQ9u"></a>
  2. ## 静态资源文件
  3. 项目根目录创建static文件。<br />指定静态文件加载路径
  4. ```python
  5. STATIC_URL = '/static/'
  6. # 配置静态文件加载路径
  7. STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]

配置模板

image.png

一、功能-注册

创建用户模块应用

  1. python manage.py startapp users

注册用户模块

  1. #主应用中的settings.py
  2. INSTALLED_APPS = [
  3. ...
  4. 'users.apps.UsersConfig',
  5. ]

创建模型

1.Django默认用户认证系统

  • Django自带用户认证系统
    • 它处理用户账号、组、权限以及基于cookie的用户会话。
  • Django认证系统位置
    • django.contrib.auth包含认证框架的核心和默认的模型。
  • Django认证系统同时处理认证和授权
    • 认证:验证一个用户是否它声称的那个人,可用于账号登录。
    • 授权:授权决定一个通过了认证的用户被允许做什么。
  • Django认证系统包含的内容

    • 用户:用户模型类、用户认证。
    • 权限:标识一个用户是否可以做一个特定的任务,MIS系统常用到。
    • 组:对多个具有相同权限的用户进行统一管理,MIS系统常用到。
    • 密码:一个可配置的密码哈希系统,设置密码、密码校验。

      2. Django默认用户模型类

  • Django认证系统中提供了用户模型类User保存用户的数据。

    • User对象是认证系统的核心。
  • Django认证系统用户模型类位置

    • django.contrib.auth.models.User

      image.png
      父类AbstractUser介绍

  • User对象基本属性

    • 创建用户必选:username、password
    • 创建用户可选:email、first_name、last_name、last_login、date_joined、is_active 、is_staff、is_superuse
    • 判断用户是否通过认证:is_authenticated
    • USERNAME_FIELD:可以修改用户名认证字段
  • 创建用户的方法

    1. user = User.objects.create_user(username, password, **extra_fields)
  • 用户认证的方法

  1. from django.contrib.auth import authenticate
  2. user = authenticate(username=username, password=password, **kwargs)
  • 处理密码的方法

    • 设置密码:set_password(raw_password)
    • 校验密码:check_password(raw_password)

      3. 自定义用户模型类

      如何自定义用户模型类?
  • 继承自AbstractUser(可通过阅读Django默认用户模型类的源码得知) 。

  • 新增手机号字段,头像字段和简介字段。 ```python from django.db import models from django.contrib.auth.models import AbstractUser

用户信息

class User(AbstractUser):

  1. # 电话号码字段
  2. # unique 为唯一性字段
  3. mobile = models.CharField(max_length=20, unique=True, blank=True)
  4. # 头像
  5. # upload_to为保存到响应的子目录中
  6. avatar = models.ImageField(upload_to='avatar/%Y%m%d/', blank=True)
  7. # 个人简介
  8. user_desc = models.TextField(max_length=500, blank=True)
  9. # 修改认证的字段
  10. USERNAME_FIELD = 'mobile'
  11. # 创建超级管理员的需要必须输入的字段
  12. REQUIRED_FIELDS = ['username', 'email']
  13. # 内部类 class Meta 用于给 model 定义元数据
  14. class Meta:
  15. db_table = 'tb_user' # 修改默认的表名
  16. verbose_name = '用户信息' # Admin后台显示
  17. verbose_name_plural = verbose_name # Admin后台显示
  18. def __str__(self):
  19. return self.mobile
<a name="i7AXb"></a>
### 4. 指定用户模型类
> 思考:为什么Django默认用户模型类是User?
> - 阅读源代码:'django.conf.global_settings’
>          - AUTH_USER_MODEL = 'auth.User' 
> 
结论:
> - Django用户模型类是通过全局配置项
>    - **AUTH_USER_MODEL**决定的
> 
配置规则:
> AUTH_USER_MODEL = '应用名.模型类名'

配置文件中指定本项目用户模型类 
```python
AUTH_USER_MODEL = 'users.User'

5.迁移用户模型类

#创建迁移文件
python manage.py makemigrations
#执行迁移文件
python manage.py migrate

创建视图

在users.views.py文件中定义视图

from django.views import View

class RegisterView(View):
    """用户注册"""

    def get(self, request):
        """
        提供注册界面
        :param request: 请求对象
        :return: 注册界面
        """
        return render(request, 'register.html')

图形验证码

1.准备captcha包(该包用于生成图形验证码)
image.png
2.安装Python处理图片的库

pip install Pillow

3.图形验证码实现

from django.http import HttpResponseBadRequest,HttpResponse
from libs.captcha.captcha import captcha
from django_redis import get_redis_connection

class ImageCodeView(View):

    def get(self,request):
        #获取前端传递过来的参数
        uuid=request.GET.get('uuid')
        #判断参数是否为None
        if uuid is None:
            return HttpResponseBadRequest('请求参数错误')
        # 获取验证码内容和验证码图片二进制数据
        text, image = captcha.generate_captcha()
        # 将图片验内容保存到redis中,并设置过期时间
        redis_conn = get_redis_connection('default')
        redis_conn.setex('img:%s' % uuid, 300, text)
        # 返回响应,将生成的图片以content_type为image/jpeg的形式返回给请求
        return HttpResponse(image, content_type='image/jpeg')

4.配置路由

from django.urls import path
from users.views import ImageCodeView

urlpatterns = [
    # 参数1:路由
    # 参数2:视图函数
    # 参数3:路由名,方便通过reverse来获取路由
    path('imagecode/', ImageCodeView.as_view(),name='imagecode'),
]

定义用户注册路由

1.在主工程的urls.py配置子应用的访问路由。

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

urlpatterns = [
    path('admin/', admin.site.urls),
    # include 参数1要设置为元组(urlconf_module, app_name)
    # namespace 设置命名空间
    path('', include(('users.urls', 'users'), namespace='users')),
]

2.在子应用中创建urls.py文件,在其添加自己的访问路由信息

from django.urls import path
from users.views import RegisterView

urlpatterns = [
    # 参数1:路由
    # 参数2:视图函数
    # 参数3:路由名,方便通过reverse来获取路由
    path('register/',RegisterView.as_view(),name='register'),
]

创建首页子应用

注册成功,重定向到首页

python manage.py startapp home

image.png

定义首页视图

from django.views import View

class IndexView(View):
    """首页广告"""

    def get(self, request):
        """提供首页广告界面"""
        return render(request, 'index.html')

配置首页路由

在home子应用中创建urls.py文件,并定义子路由

from django.urls import path
from home.views import IndexView
urlpatterns = [
    path('', IndexView.as_view(),name='index'),
]

在主工程的urls.py总路由中添加子应用路由引导

from django.urls import path, include

urlpatterns = [

    path('', include(('home.urls','home'),namespace='home')),
]

二、登录

用户名登录

1.在users.views.py文件中定义视图

from django.contrib.auth import login
from django.contrib.auth import authenticate


class LoginView(View):

    def get(self, request):
        return render(request, 'login.html')

    def post(self, request):
        # 接受参数
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        remember = request.POST.get('remember')

        # 校验参数
        # 判断参数是否齐全
        if not all([mobile, password]):
            return HttpResponseBadRequest('缺少必传参数')

        # 判断手机号是否正确
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return HttpResponseBadRequest('请输入正确的手机号')

        # 判断密码是否是8-20个数字
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return HttpResponseBadRequest('密码最少8位,最长20位')

        # 认证登录用户
        """
            默认的认证方法中是对username进行认证。我们需要修改认证的字段为mobile。所以我们需要在User的模型中修改
            USERNAME_FIELD='mobile'才能实现手机号的认证
        """
        user = authenticate(mobile=mobile, password=password)

        if user is None:
            return HttpResponseBadRequest('用户名或密码错误')

        # 实现状态保持
        # Django用户认证系统提供了login()方法 封装了写入session的操作,帮助我们快速实现状态保持
        login(request, user)

        # 响应登录结果
        next = request.GET.get('next')
        if next:
            response = redirect(next)
        else:
            # 重定向到首页 未登录
            response = redirect(reverse('home:index'))

        # 设置状态保持的周期
        if remember != 'on':
            # 没有记住用户:浏览器会话结束就过期
            request.session.set_expiry(0)
            # 设置cookie
            response.set_cookie('is_login', True)
            response.set_cookie('username', user.username, max_age=30 * 24 * 3600)
        else:
            # 记住用户:None表示两周后过期
            request.session.set_expiry(None)
            # 设置cookie
            response.set_cookie('is_login', True, max_age=14 * 24 * 3600)
            response.set_cookie('username', user.username, max_age=30 * 24 * 3600)
        # 返回响应
        return response

2.在users.urls.py文件中定义路由

from users.views import LoginView
urlpatterns = [
    # 参数1:路由
    # 参数2:视图函数
    # 参数3:路由名,方便通过reverse来获取路由
    path('login/', LoginView.as_view(),name='login'),
]

注意:
默认的认证方法中是对username进行认证。我们需要修改认证的字段为mobile。所以我们需要在User的模型中修改。
USERNAME_FIELD=’mobile’才能实现手机号的认证

登录状态

1. login()方法介绍

  1. 状态保持:
    • 将通过认证的用户的唯一标识信息(比如:用户ID)写入到当前session会话中
  2. login()方法:
    • Django用户认证系统提供了login()方法
    • 封装了写入session的操作,帮助我们快速实现状态保持
  3. login()位置:
    • django.contrib.auth.init.py文件中
    • login(request, user)

      2. login()方法使用

      ```python

      保存注册数据

      try: user=User.objects.create_user(username=mobile,mobile=mobile, password=password) except DatabaseError: return HttpResponseBadRequest(‘注册失败’)

实现状态保持

login(request, user)

响应注册结果

跳转到首页

response = redirect(reverse(‘home:index’))

设置cookie

登录状态,会话结束后自动过期

response.set_cookie(‘is_login’,True)

设置用户名有效期一个月

response.set_cookie(‘username’,user.username,max_age=30243600)

return response

<a name="Y110F"></a>
## 退出
<a name="k77qT"></a>
### logout()方法介绍

   1. 退出登录:
      - 回顾登录:将通过认证的用户的唯一标识信息,写入到当前session会话中
      - 退出登录:正好和登录相反(清理session会话信息)
   2. logout()方法:
      - Django用户认证系统提供了logout()方法
      - 封装了清理session的操作,帮助我们快速实现登出一个用户
   3. logout()位置:
      - django.contrib.auth.__init__.py文件中

logout(request)
```python
# 退出
class LogoutView(View):

    def get(self, request):
        # 清理session
        logout(request)
        # 退出登录,重定向到登录页
        response = redirect(reverse('home:index'))
        # 退出登录时清除cookie中的登录状态
        response.delete_cookie('is_login')

        return response

三、忘记密码

1.在users.views.py文件中定义视图

# 忘记密码
class ForgetPasswordView(View):

    def get(self, request):

        return render(request, 'forget_password.html')

    def post(self, request):
        # 接收参数
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        smscode = request.POST.get('sms_code')

        # 判断参数是否齐全
        if not all([mobile, password, password2, smscode]):
            return HttpResponseBadRequest('缺少必传参数')

        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return HttpResponseBadRequest('请输入正确的手机号码')

        # 判断密码是否是8-20个数字
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return HttpResponseBadRequest('请输入8-20位的密码')

        # 判断两次密码是否一致
        if password != password2:
            return HttpResponseBadRequest('两次输入的密码不一致')

        # 验证短信验证码
        redis_conn = get_redis_connection('default')
        sms_code_server = redis_conn.get('sms:%s' % mobile)
        if sms_code_server is None:
            return HttpResponseBadRequest('短信验证码已过期')
        if smscode != sms_code_server.decode():
            return HttpResponseBadRequest('短信验证码错误')

        # 根据手机号查询数据
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 如果该手机号不存在,则注册个新用户
            try:
                User.objects.create_user(username=mobile, mobile=mobile, password=password)
            except Exception:
                return HttpResponseBadRequest('修改失败,请稍后再试')
        else:
            # 修改用户密码
            user.set_password(password)
            user.save()

        # 跳转到登录页面
        response = redirect(reverse('users:login'))

        return response

2.在users.urls.py文件中定义路由

from users.views import ForgetPasswordView
urlpatterns = [
    # 参数1:路由
    # 参数2:视图函数
    # 参数3:路由名,方便通过reverse来获取路由
    path('forgetpassword/', ForgetPasswordView.as_view(),name='forgetpassword'),
]

四、用户中心

个人中心展示

1.在users.views.py文件中定义视图

"""
Django用户认证系统提供了方法
    request.user.is_authenticated()来判断用户是否登录。如果通过登录验证则返回True。反之,返回False。
    LoginRequiredMixin封装了判断用户是否登录的操作。
"""


# 用户中心展示
class UserCenterView(LoginRequiredMixin, View):
    #查询
    def get(self, request):
        # 获取用户信息
        user = request.user
        # 组织模板渲染数据
        context = {
            'username': user.username,
            'mobile': user.mobile,
            'avatar': user.avatar.url if user.avatar else None,
            'user_desc': user.user_desc
        }
        return render(request, 'center.html', context=context)

    #修改
    def post(self, request):
        # 接收数据
        user = request.user
        avatar = request.FILES.get('avatar')
        username = request.POST.get('username', user.username)
        user_desc = request.POST.get('desc', user.user_desc)
        # 修改数据库数据
        try:
            user.username = username
            user.user_desc = user_desc
            if avatar:
                user.avatar = avatar
            user.save()
        except Exception as e:
            logger.error(e)
            return HttpResponseBadRequest('更新失败,请稍后再试')
        # 返回响应,刷新页面
        response = redirect(reverse('users:center'))
        ##更新cookie信息
        response.set_cookie('username', user.username, max_age=30 * 24 * 3600)
        return response

2.在users.urls.py文件中定义路由

from users.views import UserCenterView
urlpatterns = [
    # 参数1:路由
    # 参数2:视图函数
    # 参数3:路由名,方便通过reverse来获取路由
    path('center/', UserCenterView.as_view(),name='center'),
]

注意:判断用户是否登录
Django用户认证系统提供了方法

  • request.user.is_authenticated()来判断用户是否登录。如果通过登录验证则返回True。反之,返回False
  • LoginRequiredMixin封装了判断用户是否登录的操作。

1.用户中心使用LoginRequiredMixin

from django.views import View
from django.contrib.auth.mixins import LoginRequiredMixin

class UserCenterView(LoginRequiredMixin,View):

    def get(self,request):

        return render(request,'center.html')

2.设置未登录用户跳转的路由

#在工程的settings.py文件中,添加以下配置。
LOGIN_URL = '/login/'

3.根据登录的next参数设置登录跳转路由

# 实现状态保持
login(request, user)

# 响应登录结果
next = request.GET.get('next')
if next:
    response= redirect(next)
else:
    response =  redirect(reverse('home:index'))

个人中心修改

用户中心头像的上传和展示
1.在settings.py文件中设置图片上传的路径并新建文件夹media

MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')

2.重新上传之后发现无法访问
image.png
解决方案:
第一步:设置图片的统一url都以media开头。在settings.py文件中设置

# 图片的统一路由
MEDIA_URL = '/media/'
 第二步:设置路由匹配规则。在主工程的urls.py文件中设置
from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    # include 参数1要设置为元组(urlconf_module, app_name)
    # namespace 设置命名空间
    path('', include(('users.urls', 'users'), namespace='users')),
    path('', include(('home.urls','home'),namespace='home')),
]
#以下代码为设置图片访问路由规则
from django.conf import settings
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

五、后台管理

网站的管理员负责查看、添加、修改、删除数据

image.png

  • 使用Django的管理模块, 需要按照如下步骤操作 :

    • 1.管理界面本地化
    • 2.创建管理员
    • 3.注册模型类
    • 4.发布内容到数据库

      1.管理界面本地化

  • 本地化是将显示的语言、时间等使用本地的习惯,这里的本地化就是进行中国化.

  • 中国大陆地区使用简体中文, 时区使用亚洲/上海时区, 注意这里不使用北京时区. ```python LANGUAGE_CODE = ‘zh-Hans’ #原配置信息为’en-us’

TIME_ZONE = ‘Asia/Shanghai’#原配置信息为’UTC’

<a name="WxTRS"></a>
## 2.创建管理员
**1.我们需要在自定义User模型中设置 REQUIRED_FIELDS**
```python
#创建超级管理员的需要必须输入的字段
REQUIRED_FIELDS = ['username','email']

2.在终端创建超级管理员
创建管理员的命令 :

 python manage.py createsuperuser
  • 重置密码
    python manager.py changepassword 用户名
    
    3.将各个模型注册到后台管理
    在应用的admin.py文件中注册模型类
    image.png