day13订单管理平台项目【知识点总结】

【day13】#

自增与主键#

在django中定义表时会自动生成id列,其字段类型如下

settings.py文件中的最后一行是DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField',其定义的就是id的字段类型。其中Auto表示自增,其中参数primary_key默认为True(设置id为主键)

image

如果不希望使用django内置提供的这个id,也是可以自定义的,方式如下

image

抽象类【逻辑删除】#

逻辑删除:为了防止敏感数据丢失,使用逻辑删除。定义抽象类ActiveBaseModel,定义字段active为1或0来表示数据状态(存在/已删除),其他类继承该抽象类,继承active字段,后续操作根据active字段即可。例:删除时只需将active更新为0;查找时加上filter(active=1)即可查找已存在数据等

订单表【注意】#

在生成订单记录的时候,多写一个price记录价格,而不用商品价格表的price,以防止以后更改商品价格造成的订单记录中价格的更改

image

索引【优化】#

db_index#

索引

对于需要频繁查询的字段,给字段加上索引,可以增加查询速度。

image

实现:会给加索引的该字段生成一个文件,这个文件会按照指定算法(哈希,B+Tree)存储该字段。这种存储方式增加了查询速度。

image

不能给所有字段都加索引,生成文件太多...

unique#

唯一索引

功能:查询速度快+唯一约束

image

DecimalField#

十进制小数,解决小数不精准

像金额类小数建议用DecimalField字段(十进制小数)存储,完全精准。

image

浮点数不精准原因:0.1 0.2小数在计算机中是以二进制存储的0.0001100110011... 0.001100110011...
计算机内存有限,无法存储无限位的二进制数,只能截取一定的位数来近似表示

详细

计算机浮点数不精准主要是由其存储和运算机制导致的,以下以 0.1 + 0.2 为例进行讲解:

  • 十进制小数转二进制的限制:十进制的0.1和0.2转换为二进制时,会得到无限循环的二进制数。0.1转换为二进制是0.0001100110011...(循环节是1100),0.2转换为二进制是0.001100110011...(循环节也是1100)。但计算机内存有限,无法存储无限位的二进制数,只能截取一定的位数来近似表示,这就产生了误差。
  • 浮点数运算过程中的误差积累:在计算0.1 + 0.2时,计算机先将0.1和0.2的近似二进制数进行加法运算,得到的结果也是一个二进制数。由于之前的近似表示已经存在误差,在加法运算过程中,这些误差可能会进一步积累。
  • 结果的舍入误差:得到的二进制结果再转换回十进制进行显示时,也可能存在舍入误差。最终,0.1 + 0.2 的计算结果在计算机中不是精确的0.3,而是 0.30000000000000004 等类似的近似值。

级联删除#

on_delete=models.CASCADE

image

Django之Model操作:https://www.cnblogs.com/wupeiqi/articles/6216618.html

PostiveIntegerField & help_text参数#

image

分库分表#

有同学问:老师我数据库中的表应该有多少列?
老师:不建议太多。在设定表结构时,尽量把经常去查询的放到一张表里面,不经常查询的通过OneToOne的机制可以给它拆到另外一张表,这就是为什么数据库里边会有那个叫分库分表

分为

  • 垂直分表
  • 水平分表:防止过多的列降低查询速度

比如说我们呃,这个垂直方向的就相当于你表里边有300万条数据或500万条数据太多了,对吧?那你说我再把这个表分成两张表。一个是一个放100万对吧?另外一个放200万就这样,其实是可以的。也可以在水平方向,比如说你的表列太多了,你查询的时候速度肯定比较慢。刚才我们说比如说有60多个列。你想想,如果你有60多列,比如说你在进行查询的时候,它会把这60多列的数据全拿到。

水平分表示例

image

案例

image

缓存和Session#

django缓存默认为本机缓存,需重写CACHE变量为redis的缓存配置
Session默认存储是数据库SESSION_ENGINE = "django.contrib.sessions.backends.db",需该为SESSION_ENGINE = "django.contrib.sessions.backends.cache"

global_settings.py文件

############
# SESSIONS #
############

# Cache to store session data if using the cache session backend.
SESSION_CACHE_ALIAS = "default"
# Cookie name. This can be whatever you want.
SESSION_COOKIE_NAME = "sessionid"
# Age of cookie, in seconds (default: 2 weeks).
SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2
# A string like "example.com", or None for standard domain cookie.
SESSION_COOKIE_DOMAIN = None
# Whether the session cookie should be secure (https:// only).
SESSION_COOKIE_SECURE = False
# The path of the session cookie.
SESSION_COOKIE_PATH = "/"
# Whether to use the HttpOnly flag.
SESSION_COOKIE_HTTPONLY = True
# Whether to set the flag restricting cookie leaks on cross-site requests.
# This can be 'Lax', 'Strict', 'None', or False to disable the flag.
SESSION_COOKIE_SAMESITE = "Lax"
# Whether to save the session data on every request.
SESSION_SAVE_EVERY_REQUEST = False
# Whether a user's session cookie expires when the web browser is closed.
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
# The module to store session data
SESSION_ENGINE = "django.contrib.sessions.backends.db"
# Directory to store session files if using the file session module. If None,
# the backend will use a sensible default.
SESSION_FILE_PATH = None
# class to serialize session data
SESSION_SERIALIZER = "django.contrib.sessions.serializers.JSONSerializer"


#########
# CACHE #
#########

# The cache backends to use.
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
    }
}
CACHE_MIDDLEWARE_KEY_PREFIX = ""
CACHE_MIDDLEWARE_SECONDS = 600
CACHE_MIDDLEWARE_ALIAS = "default"

默认情况下django引擎不支持连接redis,需下载django-redis这个第三方模块

1.下载django-redis模块

pip install django-redis

2.配置缓存

settings.py中更改django缓存为redis并配置redis(以下写代码会覆盖django默认的CACHES变量,所以复制以下代码就可以更改并配置)

#########
# CACHE #
#########
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {"max_connections": 100},
            "PASSWORD": "qwe123",
            # 'MAX_ENTRIES': 300,  # 最大缓存个数(默认300)
            # 'CULL_FREQUENCY': 3,  # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
        }
    }
}

3.配置Session

############
# SESSIONS #
############
# Session存储在哪里?
# SESSION_ENGINE = "django.contrib.sessions.backends.db"

# 如果存储到文件中,文件的路径。
# SESSION_ENGINE = "django.contrib.sessions.backends.file"
# SESSION_FILE_PATH = None

# 存储到缓存
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"

4.测试

此时也可以手动操作,将数据保存到redis中:

from django_redis import get_redis_connection

conn = get_redis_connection("default")
conn.set("xx","123123")
conn.get("xx")

动态菜单#

介绍:动态菜单指的是不同用户登录进入后看到的是不同的菜单界面
实现思路

  • v1:写两套html,一套是管理员,一套是用户,通过if判断
  • v2:在settings.py配置文件中定义动态菜单,对于html只需更换局部菜单名称和菜单url(采用)
  • v3:将动态菜单的定义放入数据库中,这样不需要重启(停止)项目,就可以修改动态菜单
动态菜单-思路
    人话:不同类型的用户登录,看到不同的菜单。
    类型:管理员、客户
    菜单:
        - v1版本(管理员,客户分开写)
            <html>
                {% if "管理员"%}
                    <a href="/xxx/x">用户管理</a>
                    <a href="/xxx/x">级别管理</a>
                    <a href="/xxx/x">级别管理</a>
                    ...
                {% else %}
                    <a href="/xxx/x">xxx管理</a>
                    <a href="/xxx/x">级别管理</a>
                {% endif %}
            </html>

        - v2版本【项目】(本次项目使用)
            - 在settings.py配置文件中定义客户和管理员对应菜单
                ADMIN = [
                    {
                        "title":"客户管理",
                        'children':[
                            {"title":"用户管理", ,name="x1"},,
                            {"title":"订单中心", ,name="x2"},
                            {"title":"交易管理", ,name="x3"},,
                        ]
                    },
                    {
                        "title":"客户管理",
                        'children':[
                            {"title":"用户管理", ,name="x1"},,
                            {"title":"订单管理", ,name="x2"},
                            {"title":"交易管理", ,name="x3"},,
                        ]
                    }

                ]

                CUSTOMER = [
                    ...
                ]
            - 页面读取+循环展示

        - v3版本(将菜单转换为表存到数据库中,不需要重启项目,可以动态修改菜单)
            - 数据库表 -> 转换成字典结构
            - 页面读取+循环展示

            好处:动态的修改菜单,不需要重启生效。

    默认选中+默认展开的问题:
        在生成标签时,判断当前访问的是那个地址?与那个菜单可以对应上 class="active" => 蓝色边框。
            <a href="/xxx/x">用户管理</a>
            <a href="/xxx/x" class="active">级别管理</a>
            <a href="/xxx/x">级别管理</a>
        展示默认携带定义的样式。

        如何判断?
            - 当用户访问某个 /my/info/ 网址,先做路由匹配  -> request.match_resolver.name = "x3"
            - 循环配置文件生成HTML标签
                {"title":"用户管理", ,name="x1"},,   <a href="/xxx/x">xxx管理</a>
                {"title":"用户管理", ,name="x2"},,   <a href="/xxx/x">xxx管理</a>
                {"title":"用户管理", ,name="x3"},,   <a href="/xxx/x" class='active'>xxx管理</a>
                ...

分离配置文件#

settings.py通用配置 + local_settings.py(区分本地和线上配置)

分离配置文件local_settings.py
    - settings.py
        - 本地开发,连接本地开发数据库 or 缓存。
        - 线上部署,将代码上传至服务器 + 线上服务器IP密码等。

    - settings.py  + local_settings.py模块
        - 本地开发,settings.py通用配置 + local_settings.py本地配置。
        - 线上部署,将剔除local_settings.py代码上传至服务器settings.py通用配置  + local_settings.py线上配置。
                   git + .gitignore文件
#############
# 引入本地配置 #
#############
try:
    from .local_settings import *
except ImportError:
    print("引入本地配置出错")

.gitignore文件#

  • 在.gitignore文件中写local_settings.py,会将项目中所有路径下的local_settings.py文件都忽略,包括管理目录下的文件夹中的同名文件。
  • 如果只想忽略特定的一个可以使用 相对路径/绝对路径 等方法指定该文件路径
# Byte-compiled / optimized / DLL files

# pycharm
.idea/
.DS_Store
offline-script/
media/

# database migrations
*/migrations/*.py
!*/migrations/__init__.py


__pycache__/
*.py[cod]
*$py.class

# Django stuff:
*.log
local_settings.py
#*.sqlite3


# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
!mdeditor/static/mdeditor/editormd/lib
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot


# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

git版本控制#

git init
git config --global user.name 'Violet_ZK' 
git config --global user.email '2694551335@qq.com'
git remote origin https://gitee.com/tencent-village---beijing-g_0/order_management_platform.git
git add .
git commit -m "这里是描述信息"
git push origin master

git clone 远程仓库地址  # 克隆
git pull origin 分支  # 更新

可以用git bash执行git命令,pycharm终端也可以执行git命令(前提配置git环境变量)

密码登录#

登录函数流程:

post进来之后

  • 表单验证
  • 数据库验证:先判读角色是用户还是管理员
  • 保存session
  • 跳转到家目录

md5加密

函数定义

"""
hashlib 模块与 MD5 哈希简介
hashlib 是 Python 内置的用于处理各种哈希算法的标准库模块,哈希算法可以将任意长度的数据转换为固定长度的哈希值,
常用于数据完整性验证、密码存储等场景。MD5 是一种较为常用的哈希算法(不过由于其安全性方面的一些局限,现在多在非安全敏感的场景使用),
它会对输入的数据生成一个 128 位(16 字节)的哈希值,通常以十六进制字符串的形式表示。
"""

import hashlib


def md5_string(data_string):
    # 创建md5对象
    obj = hashlib.md5("2983ghf3gq879hfas9fadsg".encode("utf-8"))
    # 传入data_string进行md5加密
    obj.update(data_string.encode("utf-8"))
    # 返回加密后结果
    return obj.hexdigest()


if __name__ == '__main__':
    res = md5_string("qwe123")
    print(res)  # 0d29e0c6da821315a85477c77a8471d7

钩子函数中使用

    def clean_password(self):
        old = self.cleaned_data['password']
        return md5_string(old)

短信登录#

正则使用

from django.core.validators import RegexValidator

class SmsLogin(forms.Form):
    role = forms.ChoiceField(
        label="角色",
        choices=(("2", "客户"), ("1", "管理员"))
    )
    mobile = forms.CharField(
        label="电话号",
        validators=[RegexValidator(r'^1[3579]\d{9}$', '手机号格式错误')],
        widget=forms.TextInput
    )
    code = forms.CharField(
        label="验证码",
        widget=forms.TextInput
    )

作者:cloud-2-jane

出处:https://www.cnblogs.com/cloud-2-jane/p/18653747

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   一只大学生  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示