" name="sm-site-verification"/>
侧边栏壁纸
博主头像
PySuper博主等级

千里之行,始于足下

  • 累计撰写 203 篇文章
  • 累计创建 14 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录
Web

cookiecutter 火速创建 Django项目

PySuper
2021-03-09 / 0 评论 / 0 点赞 / 9 阅读 / 18747 字
温馨提示:
所有牛逼的人都有一段苦逼的岁月。 但是你只要像SB一样去坚持,终将牛逼!!! ✊✊✊

Cookiecutter

效果

下面是使用Cookiecutter创建的项目文件目录

cookiecutter文件目录

安装

# 使用pip安装

pip install cookiecutter

# 下载cookiecutter-django

git clone https://github.com/pydanny/cookiecutter-django.git

使用

创建模板

# 开始创建模板

cookiecutter cookiecutter-django

配置模板

project_name [My Awesome Project]: # 项目名称
project_slug [web_name]: slug(默认是项目名)
description [Behold My Awesome Project!]: # 项目介绍
author_name [Daniel Roy Greenfeld]: # 作者名
domain_name [example.com]: # 部署的域名
email [zheng@example.com]: # 邮箱
version [0.1.0]: # 当前版本号,默认为0.1.0
Select open_source_license: 
1 - MIT
2 - BSD
3 - GPLv3
4 - Apache Software License 2.0
5 - Not open source
Choose from 1, 2, 3, 4, 5 [1]: 5 # 选择项目License
timezone [UTC]: Asia/Shanghai # Django settings中的TIME_ZONE
windows [n]: # 是否是Windows环境
use_pycharm [n]: y # 是否使用Pycharm开发
use_docker [n]:  # 是否使用Docker容器
Select postgresql_version:
1 - 12.3
2 - 11.8
3 - 10.8
4 - 9.6
5 - 9.5
Choose from 1, 2, 3, 4, 5 [1]: # 选择Postgres数据库版本,cookiecutter-django默认只支持Postgres
Select js_task_runner:
1 - None
2 - Gulp
Choose from 1, 2 [1]: # js运行方式
Select cloud_provider:
1 - AWS
2 - GCP
3 - None
Choose from 1, 2, 3 [1]: 3
Select mail_service:
1 - Mailgun
2 - Amazon SES
3 - Mailjet
4 - Mandrill
5 - Postmark
6 - Sendgrid
7 - SendinBlue
8 - SparkPost
9 - Other SMTP
Choose from 1, 2, 3, 4, 5, 6, 7, 8, 9 [1]: 9 # 选择发送邮件的服务器
use_async [n]: y # 是否使用async异步
use_drf [n]: y	# 使用使用django-rest-framework
custom_bootstrap_compilation [n]: # 是否自定义bootstrap压缩
use_compressor [n]: y # 是否使用压缩
use_celery [n]: y # 是否使用celery,一个异步任务队列
use_mailhog [n]:  # 是否使用mailhog,Django项目中发送邮件的,也可以使用Mailgun代替
use_sentry [n]:  # 是否使用错误日志日志监控,sentry也是不错的开源python项目
use_whitenoise [n]: y # 是否使用whitenoise
use_heroku [n]:  # 是否使用heroku,heroku是国外著名的云服务厂商之一,提供PaaS
Select ci_tool: 
1 - None
2 - Travis
3 - Gitlab
4 - Github
Choose from 1, 2, 3, 4 [1]: 4 # 是否使用travisci,类似于jekins,用于DevOps中的持续集成与发布
keep_local_envs_in_vcs [y]:  # 对于本地环境变量使用版本控制
debug [n]: y # 是否开启debug模式,settings中配置

# 配置完成后显示
[SUCCESS]: Project initialized, keep up the good work!

配置项目

base.py
from utils.log_theme import *
import environ

ROOT_DIR = environ.Path(__file__) - 3
APPS_DIR = ROOT_DIR.path("wp")

env = environ.Env()

READ_DOT_ENV_FILE = env.bool("DJANGO_READ_DOT_ENV_FILE", default=True)
if READ_DOT_ENV_FILE:
    env.read_env(str(ROOT_DIR.path(".env")))

DEBUG = env.bool("DJANGO_DEBUG", False)

TIME_ZONE = "Asia/Shanghai"
LANGUAGE_CODE = "zh-Hans"
SITE_ID = 1
USE_I18N = True
USE_L10N = True
USE_TZ = True
LOCALE_PATHS = [str(ROOT_DIR.path("locale"))]

# 数据库连接
DATABASES = {"default": env.db("DATABASE_URL", default="postgres:///zanhu")}

# 是否将HTTP请求中对数据库的操作封装成事务
DATABASES["default"]["ATOMIC_REQUESTS"] = True

ROOT_URLCONF = "config.urls"
WSGI_APPLICATION = "config.wsgi.application"

# Django自己的APP
DJANGO_APPS = [
    "simpleui",  # 配置后台站点
    'django.contrib.admin',
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.sites",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    # 'django.contrib.humanize',  # 友好的标签模板
    'django.forms',  # 用于后面重写django内置的widget模板
]

# 第三方应用的APP
THIRD_PARTY_APPS = [
    "crispy_forms",
    "allauth",
    "allauth.account",
    "allauth.socialaccount",
    "allauth.socialaccount.providers.github",  # github登录
    # "allauth.socialaccount.providers.weibo",  # weibo登录
    # "allauth.socialaccount.providers.weixin",  # weixin登录
    # "allauth.socialaccount.providers.baidu",  # baidu登录
    # "django_celery_beat",
    "rest_framework",
    # "rest_framework.authtoken",
    "corsheaders",
    "sorl.thumbnail",
    "taggit",
]

# 本地应用的APP
LOCAL_APPS = [
    "users.apps.UsersConfig",
    "news.apps.NewsConfig",
    "articles.apps.ArticlesConfig",
    "qa.apps.QaConfig",
    "messager.apps.MessagerConfig",
    "notifications.apps.NotificationsConfig",
    "search.apps.SearchConfig"

]

# 将上面三个APP相加
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS

# 更改查找组件模板的顺序,先自定义的模板,然后是系统默认的模板
FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'

MIGRATION_MODULES = {"sites": "zanhu.contrib.sites.migrations"}

# 认证功能
AUTHENTICATION_BACKENDS = [
    "django.contrib.auth.backends.ModelBackend",
    "allauth.account.auth_backends.AuthenticationBackend",
]

# 用户登录
AUTH_USER_MODEL = "users.User"
LOGIN_REDIRECT_URL = "news:list"
LOGIN_URL = "news:list"

# 用户登录的session缓存
# SESSION_ENGINE = "django.contrib.sessions.backends.db"  # 默认使用的是保存到数据库
# SESSION_ENGINE = "django.contrib.sessions.backends.cache"  # 使用cache
SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"  # 使用redis数据库

# 加密算法
PASSWORD_HASHERS = [
    "django.contrib.auth.hashers.Argon2PasswordHasher",
    "django.contrib.auth.hashers.PBKDF2PasswordHasher",
    "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
    "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
]

# 密码校验
AUTH_PASSWORD_VALIDATORS = [
    {"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"},
    {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
    {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
    {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
]

# 中间件
MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "corsheaders.middleware.CorsMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.locale.LocaleMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.common.BrokenLinkEmailsMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

# 配置redis缓存
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": env("REDIS_URL"),
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "IGNORE_EXCEPTIONS": True,
        },
    }
}

# 静态文件配置
STATIC_ROOT = str(ROOT_DIR("static"))
STATIC_URL = "/static/"
STATICFILES_DIRS = [str(APPS_DIR("staticfiles"))]
STATICFILES_FINDERS = [
    "django.contrib.staticfiles.finders.FileSystemFinder",
    "django.contrib.staticfiles.finders.AppDirectoriesFinder",
]

MEDIA_ROOT = str(APPS_DIR("media"))
MEDIA_URL = "/media/"

# 模板文件的配置
TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [str(APPS_DIR("templates"))],
        "OPTIONS": {
            "loaders": [
                "django.template.loaders.filesystem.Loader",
                "django.template.loaders.app_directories.Loader",
            ],
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.template.context_processors.i18n",
                "django.template.context_processors.media",
                "django.template.context_processors.static",
                "django.template.context_processors.tz",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    }
]

# FORM_RENDERER = "django.forms.renderers.TemplatesSetting"

CRISPY_TEMPLATE_PACK = "bootstrap4"

FIXTURE_DIRS = (str(APPS_DIR.path("fixtures")),)

# 安全配置
SESSION_COOKIE_HTTPONLY = True  # 防止点击劫持
CSRF_COOKIE_HTTPONLY = False  # 是否允许HTTP获取CSRFToken
SECURE_BROWSER_XSS_FILTER = True  # 防止XSS攻击
X_FRAME_OPTIONS = "DENY"

# Email==> env()--在.env文件中定义
EMAIL_BACKEND = env("DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.smtp.EmailBackend")
EMAIL_HOST = env("DJANGO_EMAIL_HOST")
EMAIL_USE_SSL = env("DJANGO_EMAIL_USE_SSL", default=True)
EMAIL_PORT = env("DJANGO_EMAIL_PORT", default=465)
EMAIL_HOST_USER = env("DJANGO_EMAIL_HOST_USER")
EMAIL_HOST_PASSWORD = env("DJANGO_EMAIL_HOST_PASSWORD")
DEFAULT_FROM_EMAIL = env("DJANGO_DEFAULT_FROM_EMAIL")
EMAIL_TIMEOUT = 5

# Admin
ADMIN_URL = "admin/"
ADMINS = [("""__zheng__""", "__zheng__@example.com")]
MANAGERS = ADMINS

# Log
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,  # 是否禁用已经存在的日志器
    'formatters': {  # 日志信息显示的格式
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
        },
        'simple': {
            'format': '[%(levelname)s] %(message)s'
        },
    },
    'filters': {  # 对日志进行过滤
        'require_debug_true': {  # django在debug模式下才输出日志
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {  # 日志处理方法
        'console': {  # 向终端中输出日志
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
    },
    'loggers': {  # 日志器
        'django': {  # 定义了一个名为django的日志器
            'handlers': ['console'],  # 可以同时向终端与文件中输出日志
            'propagate': True,  # 是否继续传递日志信息
            'level': 'INFO',  # 日志器接收的最低日志级别
        },
    }
}

# Celery
# INSTALLED_APPS += ['zanhu.tas kapp.celery.CeleryAppConfig']
if USE_TZ:
    CELERY_TIMEZONE = TIME_ZONE
CELERY_BROKER_URL = env("CELERY_BROKER_URL")
CELERY_RESULT_BACKEND = env("CELERY_RESULT_BACKEND")
CELERY_ACCEPT_CONTENT = ["json", "msgpack"]  # msgpack-> celery序列化和反序列化的数据格式
CELERY_TASK_SERIALIZER = "msgpack"  # 序列化和反序列化的数据格式,二进制的json序列化方案
CELERY_RESULT_SERIALIZER = "json"  # 读取任务结果,一般性能不高,所以使用可读性更好的json
CELERY_TASK_TIME_LIMIT = 5 * 60  # 单个任务最大运行时间
CELERY_TASK_SOFT_TIME_LIMIT = 60  # 任务的软时间限制,超时后SoftTimeLimitExceeded异常会被抛出
# CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler"

# django-allauth
ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", True)  # 是否允许用户注册
ACCOUNT_AUTHENTICATION_METHOD = "username"  # 用户使用什么登录, email/user_email
ACCOUNT_EMAIL_REQUIRED = True  # 是否要求用户输入邮箱信息
ACCOUNT_EMAIL_VERIFICATION = "none"  # 是否验证邮件, none-不验证, mandatory-强制验证, optional-可选项
ACCOUNT_ADAPTER = "wp.users.adapters.AccountAdapter"
SOCIALACCOUNT_ADAPTER = "wp.users.adapters.SocialAccountAdapter"

# django-compressor
INSTALLED_APPS += ["compressor"]
STATICFILES_FINDERS += ["compressor.finders.CompressorFinder"]

# rest-framework
# REST_FRAMEWORK = {
#     "DEFAULT_AUTHENTICATION_CLASSES": (
#         "rest_framework.authentication.SessionAuthentication",
#         "rest_framework.authentication.TokenAuthentication",
#     ),
#     "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
# }

CORS_URLS_REGEX = r"^/api/.*$"

MARKDOWNX_MEDIA_PATH = "markdownx/"  # markdownx文件保存的路径
MARKDOWNX_SERVER_CALL_LATENCY = 1000  # 特殊情况特殊调节
MARKDOWNX_UPLOAD_MAX_SIZE = 5 * 1024 * 1024  # Markdown最大上传的图片大小5M
MARKDOWNX_IMAGE_MAX_SIZE = {'size': (1000, 1000), 'quality': 100}  # Markdown的图片质量:1000(图片不压缩)

.env
# MySQL
DATABASE_URL=mysql://wp:123456@127.0.0.1/wp
        
# Redis
REDIS_URL=redis://127.0.0.1:6379

# Django
DJANGO_DEBUG=True
DJANGO_SECRET_KEY=fp2#2%p3z-(g+f--k&5vlc3wfdrkr*d6wp^y6l3n_v0gutlah8
 
# Email
DJANGO_EMAIL_USE_SSL=True
DJANGO_EMAIL_HOST='smtp.qq.com'
DJANGO_EMAIL_PORT=25
DJANGO_EMAIL_HOST_USER=''
DJANGO_EMAIL_HOST_PASSWORD=''
DJANGO_DEFAULT_FROM_EMAIL=EMAIL_HOST_USER

# Celery
CELERY_BROKER_URL=redis://127.0.0.1:6379/1
CELERY_RESULT_BACKEND=redis://127.0.0.1:6379/2
log_theme
import logging


def add_coloring_to_emit_windows(fn):
    def _out_handle(self):
        import ctypes
        return ctypes.windll.kernel32.GetStdHandle(self.STD_OUTPUT_HANDLE)

    out_handle = property(_out_handle)

    def _set_color(self, code):
        import ctypes

        self.STD_OUTPUT_HANDLE = -11
        hdl = ctypes.windll.kernel32.GetStdHandle(self.STD_OUTPUT_HANDLE)
        ctypes.windll.kernel32.SetConsoleTextAttribute(hdl, code)

    setattr(logging.StreamHandler, '_set_color', _set_color)

    def new(*args):
        FOREGROUND_BLUE = 0x0001  # text color contains blue.
        FOREGROUND_GREEN = 0x0002  # text color contains green.
        FOREGROUND_RED = 0x0004  # text color contains red.
        FOREGROUND_INTENSITY = 0x0008  # text color is intensified.
        FOREGROUND_WHITE = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED

        # winbase.h
        STD_INPUT_HANDLE = -10
        STD_OUTPUT_HANDLE = -11
        STD_ERROR_HANDLE = -12

        # wincon.h
        FOREGROUND_BLACK = 0x0000
        FOREGROUND_BLUE = 0x0001
        FOREGROUND_GREEN = 0x0002
        FOREGROUND_CYAN = 0x0003
        FOREGROUND_RED = 0x0004
        FOREGROUND_MAGENTA = 0x0005
        FOREGROUND_YELLOW = 0x0006
        FOREGROUND_GREY = 0x0007
        FOREGROUND_INTENSITY = 0x0008  # foreground color is intensified.

        BACKGROUND_BLACK = 0x0000
        BACKGROUND_BLUE = 0x0010
        BACKGROUND_GREEN = 0x0020
        BACKGROUND_CYAN = 0x0030
        BACKGROUND_RED = 0x0040
        BACKGROUND_MAGENTA = 0x0050
        BACKGROUND_YELLOW = 0x0060
        BACKGROUND_GREY = 0x0070
        BACKGROUND_INTENSITY = 0x0080  # background color is intensified.

        levelno = args[1].levelno
        if (levelno >= 50):
            color = BACKGROUND_YELLOW | FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY
        elif (levelno >= 40):
            color = FOREGROUND_RED | FOREGROUND_INTENSITY
        elif (levelno >= 30):
            color = FOREGROUND_YELLOW | FOREGROUND_INTENSITY
        elif (levelno >= 20):
            color = FOREGROUND_GREEN
        elif (levelno >= 10):
            color = FOREGROUND_MAGENTA
        else:
            color = FOREGROUND_WHITE
        args[0]._set_color(color)

        ret = fn(*args)
        args[0]._set_color(FOREGROUND_WHITE)
        # print "after"
        return ret

    return new


def add_coloring_to_emit_ansi(fn):
    def new(*args):
        levelno = args[1].levelno
        if (levelno >= 50):
            color = '\x1b[31m'  # red
        elif (levelno >= 40):
            color = '\x1b[31m'  # red
        elif (levelno >= 30):
            color = '\x1b[33m'  # yellow
        elif (levelno >= 20):
            color = '\x1b[32m'  # green
        elif (levelno >= 10):
            color = '\x1b[35m'  # pink
        else:
            color = '\x1b[0m'  # normal
        try:
            args[1].msg = color + args[1].msg + '\x1b[0m'  # normal
        except Exception as e:
            pass
        return fn(*args)

    return new


import platform

if platform.system() == 'Windows':
    logging.StreamHandler.emit = add_coloring_to_emit_windows(logging.StreamHandler.emit)
else:
    logging.StreamHandler.emit = add_coloring_to_emit_ansi(logging.StreamHandler.emit)


class Color:
    Black = 0
    Red = 1
    Green = 2
    Yellow = 3
    Blue = 4
    Magenta = 5
    Cyan = 6
    White = 7


class Mode:
    Foreground = 30
    Background = 40
    ForegroundBright = 90
    BackgroundBright = 100


def tcolor(c, m=Mode.Foreground):
    return '\033[{}m'.format(m + c)


def treset():
    return '\033[0m'


if __name__ == '__main__':
    import os

    os.system('')

    # usage
    print(tcolor(Color.Red) + 'hello' + treset())
    print(tcolor(Color.Green, Mode.Background) + 'color' + treset())
    print()

    COLOR_NAMES = ['Black', 'Red', 'Green', 'Yellow', 'Blue', 'Magenta', 'Cyan', 'White']
    MODE_NAMES = ['Foreground', 'Background', 'ForegroundBright', 'BackgroundBright']

    fmt = '{:11}' * len(COLOR_NAMES)
    print(' ' * 20 + fmt.format(*COLOR_NAMES))

    for mode_name in MODE_NAMES:
        print('{:20}'.format(mode_name), end='')
        for color_name in COLOR_NAMES:
            mode = getattr(Mode, mode_name)
            color = getattr(Color, color_name)
            print(tcolor(color, mode) + 'HelloColor' + treset(), end=' ')
        print()

使用 pipenv

环境

  • 真实环境
  • virtualenv
  • pipenv

使用

# 安装指定文件
pipenv install -r requirements --skip-lock

# 运行python文件
pipenv run python managre.py makemigrations
pipenv run python managre.py migrate

Options:
pipenv  --where # 显示项目文件所在路径
pipenv --venv # 显示虚拟环境实际文件所在路径
pipenv --py # 显示虚拟环境 Python解释器所在路径
pipenv --envs # 显示虚拟环境的选项变量
pipenv --rm # 删除虚拟环境
pipenv --bare # 最小化输出
pipenv --completion # 完整输出
pipenv --man # 显示帮助页面
pipenv-three/-two # 使用 Python3/2创建虚拟环境(注意已安装的 Python版本)
pipenv -python # TEXT指定某 Python版本作为虚拟环境的安装源
pipenv --site-packages # 附带安装原 ython解释器中的第三方库
pipenv --jumbotron An easter ego. effectively.
pipenv --version # 版本信息
pipenv -h, --help # 帮助信息

pipenv check # 检查安全漏洞
pipenv graph # 显示当前依赖关系图信息
pipenv instal11 # 安装虚拟环境或者第三方库
pipenv lock # 锁定并生成 Pipfile1ock文件
pipenv open # 在编辑器中查看一个库
pipenv run # 在虚拟环境中运行命令
pipenv shell # 进入虚拟环境
pipenv uninsta11 # 卸载一个库

参考:

CookieCutter安装与使用

Cookiecutter安装和使用

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区