当前位置: 首页 > news >正文

【Django】Django 的员工信息系统

目录

一、登录验证

三、增删改数据

四、登录检测和拦截

五、总结


码云地址在文末,blog:https://fabian4.gitee.io/47578.html

功能实现:

  • 登录权限验证
  • 登录状态检测
  • 员工信息分页查询显示
  • 多条件联合查询
  • 增删改数据


一、登录验证


1. 创建管理员模型和用户模型

# user\models.py
from django.db import models


class User(models.Model):
    """用户类"""

    id = models.AutoField(primary_key=True, db_column='id', verbose_name='编号')
    name = models.CharField(max_length=20, db_column='name', verbose_name='名字')
    gender = models.CharField(max_length=20, db_column='gender', verbose_name='性别')
    age = models.CharField(max_length=20, db_column='age', verbose_name='年龄')
    address = models.CharField(max_length=20, db_column='address', verbose_name='籍贯')
    qq = models.CharField(max_length=20, db_column='qq', verbose_name='QQ')
    email = models.CharField(max_length=20, db_column='email', verbose_name='邮箱')

    class Meta:
        db_table = 'user'


class Admin(models.Model):
    """管理员"""

    id = models.AutoField(primary_key=True, db_column='id', verbose_name='编号')
    username = models.CharField(max_length=20, db_column='username', verbose_name='用户名')
    password = models.CharField(max_length=20, db_column='password', verbose_name='密码')

    class Meta:
        db_table = 'manager'


2. 配置MySQL数据库


参考上一篇博客

https://blog.csdn.net/bandaoyu/article/details/105968112

3. 迁移数据模型


# 迁移 Django 内置的管理数据表
(venv)$ python manage.py migrate
# 生成我们的数据迁移文件
(venv)$ python manage.py makemigrations user
# 迁移我们的数据表
(venv)$ python manage.py migrate
3. 映射 URL

# UserSystem\urls.py
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('user.urls')),
]

# user\urls.py
urlpatterns = [
    # 登录的url
    path('login/', views.login, name='login'),
    # 获取图片验证码
    path('get_captcha/', views.get_captcha, name='get_captcha'),
]


4. 配置全局静态文件

# UserSystem\settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]


5. 配置全局默认基本 url

# user\context_processors.py
from UserSystem import settings

def base_url(request):
    if settings.DEBUG:
        return {'BASE_URL': 'http://localhost:8000/'}

# 注册到 UserSystem\settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        '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',
                # 注册我们自己配置的文件
                'user.context_processors.base_url'
            ],
        },
    },
]


6. 关闭 xss token

这是 Django 中为了避免存在跨站脚本攻击漏洞而对网页表单的强制要求,我们在开发过程中可以先将这个模块注释掉MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 注释 网页表单验证组件
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]


7. 编写前端页面

<!-- templates\login.html -->
<div class="container" style="width: 400px;">
          <h3 style="text-align: center;">管理员登录</h3>
        <form action="/login/" method="post">
          <div class="form-group">
            <label for="username">用户名:</label>
            <input type="text" name="username" class="form-control" id="username" placeholder="请输入用户名"/>
          </div>
          
          <div class="form-group">
            <label for="password">密码:</label>
            <input type="password" name="password" class="form-control" id="password" placeholder="请输入密码"/>
          </div>
          
          <div class="form-inline">
            <label for="vcode">验证码:</label>
            <input type="text" name="verifycode" class="form-control" id="verifycode" placeholder="请输入验证码" style="width: 120px;"/>
            <a href="javascript:refreshCode()">
                <img src="{{pageContext.request.contextPath}}/get_captcha/" title="看不清点击刷新" id="vcode"/></a>
          </div>
          <hr/>
          <div class="form-group" style="text-align: center;">
            <input class="btn btn btn-primary" type="submit" value="登录">
           </div>
          </form>
        
        <!-- 出错显示的信息框 -->
        {% if request.session.error %}
        <div class="alert alert-warning alert-dismissible" role="alert">
            <button type="button" class="close" data-dismiss="alert" >
              <span>&times;</span></button>
            <strong>{{request.session.error}}</strong>
        </div>
        {% endif %}
    </div>


8. 编写验证码生成

# user\captcha.py
import os
import random

from io import BytesIO

from PIL import Image
from PIL import ImageFilter
from PIL.ImageDraw import Draw
from PIL.ImageFont import truetype

from UserSystem.settings import BASE_DIR


class Bezier(object):
    """贝塞尔曲线"""

    def __init__(self):
        self.tsequence = tuple([t / 20.0 for t in range(21)])
        self.beziers = {}

    def make_bezier(self, n):
        """绘制贝塞尔曲线"""
        try:
            return self.beziers[n]
        except KeyError:
            combinations = pascal_row(n - 1)
            result = []
            for t in self.tsequence:
                tpowers = (t ** i for i in range(n))
                upowers = ((1 - t) ** i for i in range(n - 1, -1, -1))
                coefs = [c * a * b for c, a, b in zip(combinations,
                                                      tpowers, upowers)]
                result.append(coefs)
            self.beziers[n] = result
            return result


class Captcha(object):
    """验证码"""

    def __init__(self, width, height, fonts=None, color=None):
        self._image = None
        self._fonts = fonts if fonts else \
            [os.path.join(BASE_DIR, 'static/fonts', font).replace('\\', '/')
             for font in ['Sujeta.ttf', 'Sewer Sys.ttf']]
        self._color = color if color else random_color(0, 200, random.randint(220, 255))
        self._width, self._height = width, height

    @classmethod
    def instance(cls, width=200, height=75):
        prop_name = f'_instance_{width}_{height}'
        if not hasattr(cls, prop_name):
            setattr(cls, prop_name, cls(width, height))
        return getattr(cls, prop_name)

    def background(self):
        """绘制背景"""
        Draw(self._image).rectangle([(0, 0), self._image.size],
                                    fill=random_color(230, 255))

    def smooth(self):
        """平滑图像"""
        return self._image.filter(ImageFilter.SMOOTH)

    def curve(self, width=4, number=6, color=None):
        """绘制曲线"""
        dx, height = self._image.size
        dx /= number
        path = [(dx * i, random.randint(0, height))
                for i in range(1, number)]
        bcoefs = Bezier().make_bezier(number - 1)
        points = []
        for coefs in bcoefs:
            points.append(tuple(sum([coef * p for coef, p in zip(coefs, ps)])
                                for ps in zip(*path)))
        Draw(self._image).line(points, fill=color if color else self._color, width=width)

    def noise(self, number=50, level=2, color=None):
        """绘制扰码"""
        width, height = self._image.size
        dx, dy = width / 10, height / 10
        width, height = width - dx, height - dy
        draw = Draw(self._image)
        for i in range(number):
            x = int(random.uniform(dx, width))
            y = int(random.uniform(dy, height))
            draw.line(((x, y), (x + level, y)),
                      fill=color if color else self._color, width=level)

    def text(self, captcha_text, fonts, font_sizes=None, drawings=None, squeeze_factor=0.75, color=None):
        """绘制文本"""
        color = color if color else self._color
        fonts = tuple([truetype(name, size)
                       for name in fonts
                       for size in font_sizes or (65, 70, 75)])
        draw = Draw(self._image)
        char_images = []
        for c in captcha_text:
            font = random.choice(fonts)
            c_width, c_height = draw.textsize(c, font=font)
            char_image = Image.new('RGB', (c_width, c_height), (0, 0, 0))
            char_draw = Draw(char_image)
            char_draw.text((0, 0), c, font=font, fill=color)
            char_image = char_image.crop(char_image.getbbox())
            for drawing in drawings:
                d = getattr(self, drawing)
                char_image = d(char_image)
            char_images.append(char_image)
        width, height = self._image.size
        offset = int((width - sum(int(i.size[0] * squeeze_factor)
                                  for i in char_images[:-1]) -
                      char_images[-1].size[0]) / 2)
        for char_image in char_images:
            c_width, c_height = char_image.size
            mask = char_image.convert('L').point(lambda i: i * 1.97)
            self._image.paste(char_image,
                              (offset, int((height - c_height) / 2)),
                              mask)
            offset += int(c_width * squeeze_factor)

    @staticmethod
    def warp(image, dx_factor=0.3, dy_factor=0.3):
        """图像扭曲"""
        width, height = image.size
        dx = width * dx_factor
        dy = height * dy_factor
        x1 = int(random.uniform(-dx, dx))
        y1 = int(random.uniform(-dy, dy))
        x2 = int(random.uniform(-dx, dx))
        y2 = int(random.uniform(-dy, dy))
        warp_image = Image.new(
            'RGB',
            (width + abs(x1) + abs(x2), height + abs(y1) + abs(y2)))
        warp_image.paste(image, (abs(x1), abs(y1)))
        width2, height2 = warp_image.size
        return warp_image.transform(
            (width, height),
            Image.QUAD,
            (x1, y1, -x1, height2 - y2, width2 + x2, height2 + y2, width2 - x2, -y1))

    @staticmethod
    def offset(image, dx_factor=0.1, dy_factor=0.2):
        """图像偏移"""
        width, height = image.size
        dx = int(random.random() * width * dx_factor)
        dy = int(random.random() * height * dy_factor)
        offset_image = Image.new('RGB', (width + dx, height + dy))
        offset_image.paste(image, (dx, dy))
        return offset_image

    @staticmethod
    def rotate(image, angle=25):
        """图像旋转"""
        return image.rotate(random.uniform(-angle, angle),
                            Image.BILINEAR, expand=1)

    def generate(self, captcha_text='', fmt='PNG'):
        """生成验证码(文字和图片)"""
        self._image = Image.new('RGB', (self._width, self._height), (255, 255, 255))
        self.background()
        self.text(captcha_text, self._fonts,
                  drawings=['warp', 'rotate', 'offset'])
        self.curve()
        self.noise()
        self.smooth()
        image_bytes = BytesIO()
        self._image.save(image_bytes, format=fmt)
        return image_bytes.getvalue()


def pascal_row(n=0):
    """生成Pascal三角第n行"""
    result = [1]
    x, numerator = 1, n
    for denominator in range(1, n // 2 + 1):
        x *= numerator
        x /= denominator
        result.append(x)
        numerator -= 1
    if n & 1 == 0:
        result.extend(reversed(result[:-1]))
    else:
        result.extend(reversed(result))
    return result
def random_color(start=0, end=255, opacity=255):
    """获得随机颜色"""
    red = random.randint(start, end)
    green = random.randint(start, end)
    blue = random.randint(start, end)
    if opacity is None:
        return red, green, blue
    return red, green, blue, opacity


9. 编写视图函数
# user\views.py
# 登录函数

def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    if request.method == 'POST':
        verifycode = request.POST.get('verifycode')
        if verifycode == request.session.get('captcha'):
            username = request.POST.get('username')
            password = request.POST.get('password')
            try:
                login_user = models.Admin.objects.get(username=username, password=password)
                request.session['login_user'] = login_user.username
                return render(request, 'index.html')
            except ObjectDoesNotExist:
                request.session['error'] = '账号或密码错误'
                return render(request, 'login.html')
        else:
            request.session['error'] = '验证码错误'
            return render(request, 'login.html')


ALL_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

# 获取验证码文本

def get_captcha_text(length=4):
    selected_chars = random.choices(ALL_CHARS, k=length)
    return ''.join(selected_chars)# 返回验证码文件
def get_captcha(request):
    """验证码"""
    captcha_text = get_captcha_text()
    request.session['captcha'] = captcha_text
    image_data = Captcha.instance().generate(captcha_text)
    print(captcha_text)
    return HttpResponse(image_data, content_type='image/png')


二、分页查询和多条件查询
1.前端页面

<div>{{request.session.login_user}}欢迎您</div>
<div class="container">
    <h3 style="text-align: center">用户信息列表</h3>
    <div style="float: left;">
        <form class="form-inline" action="/find_all/?currentPage=1" method="post">
            <div class="form-group">
                <label for="exampleInputName2">姓名</label>
                <input type="text" name="name" value="{{ page_info.name|default_if_none:"" }}" class="form-control" id="exampleInputName2" >
            </div>
            <div class="form-group">
                <label for="exampleInputName3">籍贯</label>
                <input type="text" name="address" value="{{ page_info.address|default_if_none:"" }}" class="form-control" id="exampleInputName3" >
            </div>

            <div class="form-group">
                <label for="exampleInputEmail2">邮箱</label>
                <input type="text" name="email" value="{{ page_info.email|default_if_none:"" }}" class="form-control" id="exampleInputEmail2"  >
            </div>
            <button type="submit" class="btn btn-default">查询</button>
        </form>
    </div>
    <div style="float: right; margin: 5px">
        <td colspan="8" align="center"><a class="btn btn-primary" href="{{ RequestContext.BASE_URL }}/add/">添加联系人</a></td>
        <td colspan="8" align="center"><a class="btn btn-primary" href="javascript:void(0);" id="delSelected">删除选中</a></td>
    </div>
    <form id="form" action="/delSelected/" method="post">
        <table border="1" class="table table-bordered table-hover">
            <tr class="success">
                <th><input type="checkbox" id="firstCb"></th>
                <th>编号</th>
                <th>姓名</th>
                <th>性别</th>
                <th>年龄</th>
                <th>籍贯</th>
                <th>QQ</th>
                <th>邮箱</th>
                <th>操作</th>
            </tr>
            {% for user in user_list %}
                <tr>
                    <th><input type="checkbox" name="uid" value="{{ user.pk }}"></th>
                    <td>{{ forloop.counter }}</td>
                    <td>{{ user.fields.name }}</td>
                    <td>{{ user.fields.gender }}</td>
                    <td>{{ user.fields.age }}</td>
                    <td>{{ user.fields.address }}</td>
                    <td>{{ user.fields.qq }}</td>
                    <td>{{ user.fields.email }}</td>
                    <td><a class="btn btn-default btn-sm" href="{{ RequestContext.BASE_URL }}/findUserById/?id={{ user.pk }}">修改</a>&nbsp;
                        <a class="btn btn-default btn-sm" href="javascript:deleteUser({{ user.pk }});">删除</a></td>
                </tr>
            {% endfor %}
        </table>
    </form>
    <div>
        <nav aria-label="Page navigation">
            <ul class="pagination">
                <li>
                    <a href="{{ RequestContext.BASE_URL }}/find_all/?currentPage={{ page_info.currentPage|add:-1 }}&name={{ page_info.name }}&address={{ page_info.address }}&email={{ page_info.email }}" aria-label="Previous">
                        <span aria-hidden="true">&laquo;</span>
                    </a>
                </li>
                {% for i in page_info.pages %}
                    {% if i == page_info.currentPage %}
                        <li class="active"><a href="{{ RequestContext.BASE_URL }}/find_all/?currentPage={{ i }}&name={{ page_info.name }}&address={{ page_info.address }}&email={{ page_info.email }}">{{ i }}</a></li>
                    {% endif %}
                    {% if i != page_info.currentPage %}
                        <li><a href="{{ RequestContext.BASE_URL }}/find_all/?currentPage={{ i }}&name={{ page_info.name }}&address={{ page_info.address }}&email={{ page_info.email }}">{{ i }}</a></li>
                    {% endif %}
                {% endfor %}
                <li>
                    <a href="{{ RequestContext.BASE_URL }}/find_all/?currentPage={{ page_info.currentPage|add:1 }}&name={{ page_info.name }}&address={{ page_info.address }}&email={{ page_info.email }}" aria-label="Next">
                        <span aria-hidden="true">&raquo;</span>
                    </a>
                </li>
                <span style="font-size: 25px;margin-left: 5px;">
                    共{{ page_info.total }}条记录,共{{ page_info.totalPage }}页
                </span>

            </ul>
        </nav>
    </div>
</div>


2. 分页展示

这里我们采用一个 django 的 Paginator 类来实现自动的分页结果显示# 查询所有并返回序列化队列
# 将查询条件封装到一个字典作为参数传入查询方法
user_list = serializers.serialize("json", models.User.objects.filter(**search_dict))
# 将队列反序列化以便渲染到页面上
user_list = json.loads(user_list)
# 每10个为1页
p = Paginator(user_list, 10)
# 以字典格式返回给 list.html 进行渲染
return render(request, "list.html", {'user_list': p.page(current_page).object_list, 'page_info': page_info})


3. 前端参数获取

# 如果是通过 get 方法
if request.method == 'GET':
    name = request.GET.get("name", default='')
    address = request.GET.get("address", default='')
    email = request.GET.get("email", default='')
    current_page = int(request.GET.get("currentPage", default=1))
# 如果是通过 post 方法
if request.method == 'POST':
    name = request.POST.get("name", default='')
    address = request.POST.get("address", default='')
    email = request.POST.get("email", default='')
    current_page = int(request.POST.get("currentPage", default=1))


4. 参数处理封装和返回
# 将查询条件封装为字典

search_dict = dict()
    # 判空防止误传
    if name:
        search_dict['name'] = name
    if address:
        search_dict['address'] = address
    if email:
        search_dict['email'] = email
    user_list = serializers.serialize("json", models.User.objects.filter(**search_dict))
    user_list = json.loads(user_list)
    p = Paginator(user_list, 10)
    # 防止出现参数超出范围的情况
    if current_page < 1:
        current_page = 1
    if current_page > p.num_pages:
        current_page = p.num_pages
    # 将页码封装到一个列表
    pages = []
    i = 1
    while i <= p.num_pages:
        pages.append(i)
        i += 1
    # 将所有信息封装为字典返回给前端
    page_info = {"total": len(user_list),
                 "totalPage": p.num_pages,
                 "currentPage": current_page,
                 "name": name,
                 "address": address,
                 "email": email,
                 "pages": pages
                 }
    return render(request, "list.html", {'user_list': p.page(current_page).object_list, 'page_info': page_info})


三、增删改数据


1. 配置 url 路径

# user\urls.py
urlpatterns = [
    path('login/', views.login, name='login'),
    path('get_captcha/', views.get_captcha, name='get_captcha'),
    path('find_all/', views.find_all, name='find_all'),
    path('add/', views.add, name='add'),
    path('findUserById/', views.findUserById, name='findUserById'),
    path('update/', views.update, name='update'),
    path('delUser/', views.delUser, name='delUser'),
    path('delSelected/', views.delSelected, name='delSelected'),
]


2. 前端界面

<!-- add.html -->
<div>{{ loginUser.name }}欢迎您</div>
<div class="container">
    <center><h3>添加联系人页面</h3></center>
    <form action="{{ RequestContext.BASE_URL }}/add/" method="post">
        <div class="form-group">
            <label for="name">姓名:</label>
            <input type="text" class="form-control" id="name" name="name" placeholder="请输入姓名">
        </div>

        <div class="form-group">
            <label>性别:</label>
            <input type="radio" name="gender" value="男" checked="checked"/>男
            <input type="radio" name="gender" value="女"/>女
        </div>

        <div class="form-group">
            <label for="age">年龄:</label>
            <input type="text" class="form-control" id="age" name="age" placeholder="请输入年龄">
        </div>

        <div class="form-group">
            <label for="address">籍贯:</label>
            <input type="text" class="form-control" id="address" name="address" placeholder="请输入籍贯">
        </div>

        <div class="form-group">
            <label for="qq">QQ:</label>
            <input type="text" class="form-control" id="qq" name="qq" placeholder="请输入QQ号码"/>
        </div>

        <div class="form-group">
            <label for="email">Email:</label>
            <input type="text" class="form-control" id="email" name="email" placeholder="请输入邮箱地址"/>
        </div>        <div class="form-group" style="text-align: center">
            <input class="btn btn-primary" type="submit" value="提交" />
            <input class="btn btn-default" type="reset" value="重置" />
            <a class="btn btn-default" href="list.jsp" role="button">返回</a>
        </div>
    </form>
</div>
<!-- update.html -->
<div>{{request.session.login_user}}欢迎您</div>
        <div class="container" style="width: 400px;">
        <h3 style="text-align: center;">修改联系人</h3>
        <form action="{{ RequestContext.BASE_URL }}/update/" method="post">
            <!--  隐藏域 提交id-->
            <input type="hidden" name="id" value="{{ u.pk }}">
          <div class="form-group">
            <label for="name">姓名:</label>
            <input type="text" class="form-control" id="name" name="name" value="{{ u.fields.name }}" placeholder="请输入姓名" />
          </div>

          <div class="form-group">
            <label>性别:</label>
              {% if u.fields.gender == '男' %}
                    <input type="radio" name="gender" value="男" checked />男
                    <input type="radio" name="gender" value="女"/>女
              {% endif %}
              {% if u.fields.gender == '女' %}
                    <input type="radio" name="gender" value="男"/>男
                    <input type="radio" name="gender" value="女" checked />女
              {% endif %}
          </div>

          <div class="form-group">
            <label for="age">年龄:</label>
            <input type="text" class="form-control" id="age" value="{{ u.fields.age }}" name="age" placeholder="请输入年龄" />
          </div>

          <div class="form-group">
            <label for="address">籍贯:</label>
              <input type="text" class="form-control" id="address" name="address" value="{{ u.fields.address }}" placeholder="请输入籍贯" />
            </select>
          </div>

          <div class="form-group">
            <label for="qq">QQ:</label>
            <input type="text" class="form-control" id="qq" value="{{ u.fields.qq }}" name="qq" placeholder="请输入QQ号码"/>
          </div>

          <div class="form-group">
            <label for="email">Email:</label>
            <input type="text" class="form-control" id="email" value="{{ u.fields.email }}" name="email" placeholder="请输入邮箱地址"/>
          </div>             <div class="form-group" style="text-align: center">
                <input class="btn btn-primary" type="submit" value="提交" />
                <input class="btn btn-default" type="reset" value="重置" />
                 <a class="btn btn-default" href="{{ RequestContext.BASE_URL }}/find_all/?currentPage=1" role="button">返回</a>
             </div>
        </form>
        </div>
    </body>


3. 后端响应

# user\views.py
def add(request):
    if request.method == 'GET':
        return render(request, "add.html")
    if request.method == 'POST':
        models.User.objects.create(name=request.POST.get('name'),
                                   gender=request.POST.get('gender'),
                                   age=request.POST.get('age'),
                                   address=request.POST.get('address'),
                                   qq=request.POST.get('qq'),
                                   email=request.POST.get('email'))
        return redirect("find_all")


def findUserById(request):
    no = request.GET.get("id")
    user = serializers.serialize("json", models.User.objects.all().filter(id=no))
    user = json.loads(user)
    return render(request, 'update.html', {'u': user[0]})


def update(request):
    no = request.POST.get("id")
    models.User.objects.filter(id=no).update(name=request.POST.get('name'),
                                             gender=request.POST.get('gender'),
                                             age=request.POST.get('age'),
                                             address=request.POST.get('address'),
                                             qq=request.POST.get('qq'),
                                             email=request.POST.get('email'))
    return redirect("find_all")


def delUser(request):
    no = request.GET.get("id")
    models.User.objects.filter(id=no).delete()
    return redirect("find_all")
def delSelected(request):
    no = request.POST.getlist("uid")
    for n in no:
        models.User.objects.filter(id=n).delete()
    return redirect("find_all")


四、登录检测和拦截


1. 编写拦截中间件

# user\middleware.py
from django.shortcuts import HttpResponseRedirect

try:
    from django.utils.deprecation import MiddlewareMixin
except ImportError:
    MiddlewareMixin = object


class SimpleMiddleware(MiddlewareMixin):
    @staticmethod
    def process_request(request):
        # 只对两个路径放行
        if request.path != '/login/' and request.path != '/get_captcha/':
            if request.session.get('user', None):
                pass
            else:
                return HttpResponseRedirect('/login/')


2. 注册中间件

# UserSystem\settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    # 注册自己编写的中间件
    'user.middleware.SimpleMiddleware'
]


五、总结


基于 Django 框架搭建的后台还是具有很多鲜明的特色的
注意 Django自带的引擎模板的语法,或者也可以更换其他模板引擎
Django 模板引擎中过滤器的使用
Django中间件的自定义和注册
源码已上传码云
原文链接:https://blog.csdn.net/qq_43733805/article/details/105964031

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • [Django ]Django 的数据库操作
  • 【boost】Windows下VS2017下boost库安装配置
  • 【mySQL】C++操作mySql数据库(Mysql connector c++)
  • [多线程]多线程编程需要注意的问题|多进程
  • 【开发者手册】开发者手册
  • 【C++11】C++11 多线程编程
  • 【多线程】c++11多线程编程(一)——初识
  • 【C++11】C++11 中的std::function和std::bind
  • 【多线程】c++11多线程编程(二)——理解线程类的构造函数
  • 【函数式编程】什么是函数式编程? C语言为何不是函数式语言?
  • 【多线程】c++11多线程编程(三)——竞争条件与互斥锁
  • 【多线程】c++11多线程编程(四)——死锁(Dead Lock)
  • 【多线程】c++11多线程编程(六)——条件变量(Condition Variable)
  • 【多线程】c++11多线程编程(五)——unique_lock和lock_guard
  • 【C/C++】内存和字符操作整理
  • 【个人向】《HTTP图解》阅后小结
  • 10个确保微服务与容器安全的最佳实践
  • android 一些 utils
  • DataBase in Android
  • GraphQL学习过程应该是这样的
  • node-sass 安装卡在 node scripts/install.js 解决办法
  • 分布式事物理论与实践
  • 给新手的新浪微博 SDK 集成教程【一】
  • 技术胖1-4季视频复习— (看视频笔记)
  • 实战|智能家居行业移动应用性能分析
  • 用Python写一份独特的元宵节祝福
  • zabbix3.2监控linux磁盘IO
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • ​DB-Engines 11月数据库排名:PostgreSQL坐稳同期涨幅榜冠军宝座
  • ​Java并发新构件之Exchanger
  • #APPINVENTOR学习记录
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (24)(24.1) FPV和仿真的机载OSD(三)
  • (3) cmake编译多个cpp文件
  • (java)关于Thread的挂起和恢复
  • (Python) SOAP Web Service (HTTP POST)
  • (Qt) 默认QtWidget应用包含什么?
  • (分享)自己整理的一些简单awk实用语句
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • (转)fock函数详解
  • (转)socket Aio demo
  • (自适应手机端)行业协会机构网站模板
  • .a文件和.so文件
  • .describe() python_Python-Win32com-Excel
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例
  • .NET 命令行参数包含应用程序路径吗?
  • .NET 项目中发送电子邮件异步处理和错误机制的解决方案
  • .Net 应用中使用dot trace进行性能诊断
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .NET_WebForm_layui控件使用及与webform联合使用
  • .Net程序猿乐Android发展---(10)框架布局FrameLayout
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理