Django新建项目流程

1 命令行创建工程

1.1 先cd到要创建工程的目录下:

cd E:\Code Learning\Python\6.django

1.2 虚拟环境下django-admin.exe的位置 + startproject + 项目名称:

"C:\Users\ZQ\.conda\envs\pytorch\Scripts\django-admin.exe" startproject project_02

自动创建下面的包和模块

2 命令行创建app

2.1 cd project_02 到当前工程路径下:

2.2 创建app指令:

python manage.py startapp app01

自动创建下面的包和模块

3 注册app

3.1 找到工程目录下的settings模块注册创建好的app:

app名称.apps.app的类名

 

4 连接MySQL数据库

4.1 django没有创建database的功能,需要先登录mysql数据库创建:

CREATE DATABASE db02 DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

USE  db02;

4.2 继续在工程目录下的setting模块修改数据库配置:

5 配置URL路由并定义视图函数

5.1 找到工程目录下的urls模块配置路由:

url路径名+视图函数名

5.2 找到app目录下的views模块定义操作函数(用户访问url时发送请求,编写对应函数对该请求做出响应):

6 启动Django项目

6.1 命令行启动

python manage.py runserver

 出现以下界面

6.2 pycharm配置启动

点击进入浏览器,在地址栏添加要访问的url路径:

服务器地址+资源rul路径:http://127.0.0.1:8000/index/

出现以下代表访问成功:

7创建目录(可选)

为使项目结构更清晰,建议创建如下结构目录:

7.1 middleware模块为中间件模块,用来做登录校验等。

  • 定义的中间件类需要继承MiddlewareMixin类,并且需要定义一个请求处理函数process_request和一个响应处理函数process_response。
  • 如果 process_request 方法中没有返回值(其实是返回None),继续向后走
    若有返回值(HttpResponse/render/redirect),执行该中间件开始及之前的响应处理函数

下面给出一个登录校验中间件:

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect, render

class AuthMiddleware(MiddlewareMixin):
    """登录校验中间件"""

    def process_request(self, request):
        # 0.排除不需要登录就能访问的页面
        if request.path_info in ["/login/", "/image/code/"]:
            return
        # 1.读取当前访问用户的session信息,若能读取到代表已经登录
        info_dict = request.session.get("info")
        if info_dict:
            return
        # 2.此时未获取到登录信息,代表未登录
        return redirect("/login/")

    def process_response(self, request, response):

        return response

定义的中间件需要在settings模块中的 MIDDLEWARE 中添加:

7.2 migrations模块为执行数据库迁移时自动生成的文件。

7.3 static模块下存储页面相关的资源,如css样式、font字体文件、imgs图片、js脚本、pluguns插件等。

7.4 templates下存储需要展示的html页面。

7.5 utils下存储常用工具包。

bs_modelform包中存储表单的初始化类,一个多继承modelform,另一个多继承form:

from django import forms


class BaseForm:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环ModelForm中的所有字段,给每个字段的插件设置
        for _, field in self.fields.items():
            # 字段中有属性,保留原来的属性,没有属性,才增加
            if field.widget.attrs:
                field.widget.attrs["class"] = "form-control"
            else:
                field.widget.attrs = {
                    "class": "form-control",
                }


class BootStrapModelForm(BaseForm, forms.ModelForm):
    pass


class BootStrapForm(BaseForm, forms.Form):
    pass

encrypt包中存储密码加密的md5函数:

import hashlib
from django.conf import settings


def md5(data_str):
    salt = settings.SECRET_KEY.encode("utf-8")
    obj = hashlib.md5(salt)
    obj.update(data_str.encode("utf-8"))
    return obj.hexdigest()

form中存储需要提交表单时的的表单类,可以自定义数据库中没有的字段,自定义提交的字段,自定义表单输入框样式,自定义对应的钩子方法(clean_字段名):

class AdminModelForm(BootStrapModelForm):
    confirm_pwd = forms.CharField(
        label="确认密码", min_length=3, widget=forms.PasswordInput(render_value=True)
    )  # 不想让输入密码错误后清空:render_value=True

    class Meta:
        model = Admin
        fields = ["name", "password", "confirm_pwd"]
        widgets = {
            "password": forms.PasswordInput(render_value=True),
            # "confirm_pwd": forms.PasswordInput(attrs={"class": "form-control"})
        }

    def clean_password(self):
        pwd = self.cleaned_data.get("password")
        return md5(pwd)

    def clean_confirm_pwd(self):
        # form.cleaned_data:验证通过后的数据以字典形式返回
        pwd = self.cleaned_data.get("password")  # 此时已经是md5加密完的密码
        confirm_pwd = md5(self.cleaned_data.get("confirm_pwd"))
        print(pwd, confirm_pwd)
        if pwd != confirm_pwd:
            raise ValidationError("两次输入的密码不一致,请重新输入")
        return confirm_pwd

pagination存储自定义的分页组件

"""
自定义的分页组件

"""

from django.utils.safestring import mark_safe
import copy


class Pagination(object):
    def __init__(self, request, queryset, page_size=10, page_param="page", page_show=5):
        """
        :param request: 请求的对象
        :param queryset: 符合条件的数据(根据此数据进行分页处理)
        :param page_size: 每页显示多少条数据
        :param page_param: 获取在URL中传递的分页参数, 例如: /pretty/list/?page=21
        :param page_show: 页码显示前几页后几页
        """

        # 防止搜索出结果进行翻页时,URL参数没有了搜索参数
        query_dict = copy.deepcopy(request.GET)
        query_dict._mutable = True
        self.query_dict = query_dict

        self.page_param = page_param

        page = int(request.GET.get(page_param, 1))

        # 如果不是整数
        if type(page) != int:
            # 强制让页码为1
            page = 1

        self.page = page

        self.start = (page - 1) * page_size
        self.end = page * page_size

        # 每页展示的数据行数
        self.page_queryset = queryset[self.start:self.end]

        total_data_count = queryset.count()     # 数据行数
        total_page_count, div = divmod(total_data_count, page_size)
        if div:
            total_page_count += 1
        self.total_page_count = total_page_count    # 总页码数量
        self.page_show = page_show  # 当前页前后展示的页码数量
        self.request = request

    def html(self):
        # 如果总页码数量大于 11
        if self.total_page_count > self.page_show * 2 + 1:
            # 如果当前页面页码位置小于等于5
            if self.page <= 5:
                start_page = 1
                end_page = self.page_show * 2 + 2
            # 否则,当前页面页码位置大于5时
            else:
                # 防止页码超出范围
                if self.page >= self.total_page_count - self.page_show:
                    start_page = self.total_page_count - self.page_show * 2
                    end_page = self.total_page_count + 1
                else:
                    # 计算出当前页的前5页和后5页
                    start_page = self.page - self.page_show
                    end_page = self.page + self.page_show + 1

        else:
            start_page = 1
            end_page = self.total_page_count + 1

        ######## 创建页码 ########
        # 页码
        page_str_list = []

        # self.query_dict.setlist(self.page_param, [1])
        # page_str_list.append('<li><a href="?page={}">{}</a></li>'.format(self.query_dict.urlencode()))

        # 跳到首页
        self.query_dict.setlist(self.page_param, [1])
        self.head_page = '<li><a href="?{}" aria-label="Previous"><span aria-hidden="true">首页</span></a></li>'.format(self.query_dict.urlencode())
        page_str_list.append(self.head_page)

        # 跳到上10页
        # 如果当前页面小于 11, 防止超过最小页数
        if self.page < self.page_show * 2 + 1:
            self.query_dict.setlist(self.page_param, [1])
            prev = '<li><a href="?{}">{}</a></li>'.format(
                self.query_dict.urlencode(), "<<")
            page_str_list.append(prev)
        else:
            self.query_dict.setlist(self.page_param, [self.page - 10])
            prev = '<li><a href="?{}">{}</a></li>'.format(
                self.query_dict.urlencode(), "<<")
            page_str_list.append(prev)

        for i in range(start_page, end_page):
            # 如果是当前页,高亮显示页码颜色
            if self.page == i:
                self.query_dict.setlist(self.page_param, [i])
                ele = '<li class="active"><a href="?{}">{}</a></li>'.format(
                    self.query_dict.urlencode(), i)
            else:
                self.query_dict.setlist(self.page_param, [i])
                ele = '<li><a href="?{}">{}</a></li>'.format(
                    self.query_dict.urlencode(), i)
            page_str_list.append(ele)

        # 跳到下10页
        # 如果当前页面页数 大于 最大页面数量减去(page_show*2+1),则直接跳到最后一页,防止超过最大页数
        if self.page >= self.total_page_count - self.page_show * 2 + 1:
            self.query_dict.setlist(self.page_param, [self.total_page_count])
            next = '<li><a href="?{}">{}</a></li>'.format(
                self.query_dict.urlencode(), ">>")
            page_str_list.append(next)
        else:
            self.query_dict.setlist(self.page_param, [self.page + 10])
            next = '<li><a href="?page={}">{}</a></li>'.format(
                self.query_dict.urlencode(), ">>")
            page_str_list.append(next)

        # 跳到尾页
        self.query_dict.setlist(self.page_param, [self.total_page_count])
        self.end_page = '<li><a href="?{}" aria-label="Next"><span aria-hidden="true">尾页</span></a></li>'.format(self.query_dict.urlencode())
        page_str_list.append(self.end_page)

        self.page_string = mark_safe("".join(page_str_list))

valid_code存储自定义验证码组件:

from PIL import Image, ImageDraw, ImageFilter, ImageFont
import random


def check_code(width=100, height=40, char_length=4, font_file='app01/static/font/Monaco.ttf', font_size=28):
    code = []
    img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))
    draw = ImageDraw.Draw(img, mode='RGB')

    def rndChar():
        """
        生成随机字母
        :return:
        """
        # return chr(random.randint(65, 90))
        return str(random.randint(0, 9))   #生成随机数字

    def rndColor():
        """
        生成随机颜色
        :return:
        """
        return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255))

    # 写文字
    font = ImageFont.truetype(font_file, font_size)
    for i in range(char_length):
        char = rndChar()
        code.append(char)
        h = random.randint(0, 4)
        draw.text([i * width / char_length, h], char, font=font, fill=rndColor())

    # 写干扰点
    for i in range(40):
        draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())

    # 写干扰圆圈
    for i in range(40):
        draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
        x = random.randint(0, width)
        y = random.randint(0, height)
        draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor())

    # 画干扰线
    for i in range(5):
        x1 = random.randint(0, width)
        y1 = random.randint(0, height)
        x2 = random.randint(0, width)
        y2 = random.randint(0, height)

        draw.line((x1, y1, x2, y2), fill=rndColor())

    img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
    return img, ''.join(code)


if __name__ == '__main__':
    img, code_str = check_code()
    print(code_str)

    with open('code.png', 'wb') as f:
        img.save(f, format='png')

7.6 views下存储视图函数,用于定义页面前后端的交互操作。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值