作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Arjaan Buijk的头像

Arjaan Buijk

Arjaan是一名高级工程师和数据科学家,他为国际银行和保险公司创建了专注于Rasa的关键任务云解决方案. 他设计并教授大规模Kubernetes解决方案.

Expertise

Previously At

Rasa
Share

这是关于在基于django的项目中利用pydantic的系列文章的第二部分. 在本系列的第一部分中,我们重点介绍了pydantic对Python类型提示的使用 简化Django设置管理.

开发者可能是他们自己最大的敌人. 我见过无数工程师在与生产环境不匹配的系统上进行开发的例子. 这种不协调导致了额外的工作,并且直到开发过程的后期才捕捉到系统错误. 调整这些设置最终将简化持续部署. With this in mind, 我们将在Django开发环境中创建一个示例应用程序, 通过Docker简化, pydantic, and conda.

一个典型的开发环境使用:

  • A local repository.
  • 基于docker的PostgreSQL数据库.
  • conda环境(用于管理Python依赖项).

Pydantic和Django适用于简单和复杂的项目. 下面的步骤展示了一个简单的解决方案,强调了如何镜像我们的环境.

Git存储库配置

在开始编写代码或安装开发系统之前,让我们先创建一个本地Git存储库:

mkdir hello-visitor
cd hello-visitor

git init

We’ll start with a basic Python .gitignore file in the repository root. 在本教程中,我们将在添加不希望Git跟踪的文件之前添加该文件.

使用Docker配置Django PostgreSQL

Django需要一个关系数据库,默认情况下使用SQLite. 对于关键任务数据存储,我们通常避免使用SQLite,因为它不能很好地处理并发用户访问. 大多数开发人员选择更典型的生产数据库,如PostgreSQL. 无论如何,我们应该在开发和生产中使用相同的数据库. 这个架构任务是 The Twelve-factor App.

幸运的是,操作本地PostgreSQL实例 Docker and Docker Compose is a breeze.

为了避免污染根目录,我们将把与docker相关的文件放在单独的子目录中. 我们将从创建一个Docker Compose文件来部署PostgreSQL开始:

# docker-services / docker-compose.yml
version: "3.9"

services:
  db:
    image: "postgres:13.4"
    env_file: .env
    volumes:
      - hello-visitor-postgres: / var / lib / postgresql /数据
    ports:
      - ${POSTGRES_PORT}:5432

volumes:
  hello-visitor-postgres:

Next, we’ll create a docker-compose 环境文件来配置PostgreSQL容器:

# docker-services/.env

POSTGRES_USER=postgres
POSTGRES_PASSWORD = MyDBPassword123

#维护数据库
POSTGRES_DB=postgres

#向localhost公开的端口
POSTGRES_PORT=5432

现在已经定义和配置了数据库服务器. 让我们在后台启动容器:

——项目目录docker-services/ up

重要的是要注意在前面的命令中使用了sudo. 这是必须的,除非 specific steps 在我们的开发环境中是遵循的吗.

Database Creation

让我们使用一个标准的工具套件连接和配置PostgreSQL。 pgAdmin4. 我们将使用与前面在环境变量中配置的相同的登录凭据.

现在让我们创建一个名为 hello_visitor:

浏览器中的pgAdmin4屏幕,在Create Database对话框中显示General选项卡. 数据库文本字段包含值hello_visitor, owner字段显示postgres用户, 注释字段是空白的.

数据库就绪后,我们就可以安装编程环境了.

通过Miniconda进行Python环境管理

我们现在需要建立一个隔离 Python 环境和所需的依赖项. 为了简化设置和维护,我们选择 Miniconda.

让我们创建并激活conda环境:

Conda create——name hello-visitor python=3.9
请激活你好,访客

现在,我们要创建一个文件, hello-visitor /需求.txt,枚举我们的Python依赖项:

django
# PostgreSQL数据库适配器
psycopg2
# Pushes .将键值对放入环境变量中:
python-dotenv
pydantic
#实用程序库读取数据库连接信息:
dj-database-url
# Static file caching:
whitenoise
# Python WSGI HTTP Server
gunicorn

接下来,我们将要求Python安装这些依赖项:

cd hello-visitor

PIP安装-r要求.txt

现在应该安装依赖项,为应用程序开发工作做准备.

Django Scaffolding

我们将通过第一次运行脚手架我们的项目和应用程序 django-admin,然后运行它生成的文件, manage.py:

#从' hello-visitor '目录
mkdir src
cd src

为Django项目生成启动代码.
Django-admin启动项目hello_visitor .

为我们的Django应用生成启动代码.
python manage.py startapp homepage

接下来,我们需要配置Django来加载我们的项目. The settings.py 文件要求对 INSTALLED_APPS 数组来注册我们新创建的 homepage app:

# src / hello_visitor /设置.py

# ...

INSTALLED_APPS = [
    "homepage.apps.HomepageConfig",
    "django.contrib.admin",
    # ...
]

# ...

应用设置配置

使用pydantic和Django设置方法 the first installment,我们需要为开发系统创建一个环境变量文件. 我们将把当前设置移到这个文件中,如下所示:

  1. Create the file src/.env 保持我们的开发环境设置.
  2. Copy the settings from src / hello_visitor /设置.py and add them to src/.env.
  3. 中删除那些复制的行 settings.py file.
  4. 确保数据库连接字符串使用我们之前配置的相同凭据.

Our environment file, src/.env, should look like this:

DATABASE_URL = postgres: / / postgres: MyDBPassword123@localhost: 5432 / hello_visitor
DATABASE_SSL=False

SECRET_KEY = " django-insecure-sackl&7(1hc3+%#*4e=)^q3qiw!hnnui*-^($o8t@2^^qqs=%i"
DEBUG=True
DEBUG_TEMPLATES=True
USE_SSL=False
ALLOWED_HOSTS='[
    "localhost",
    "127.0.0.1",
    "0.0.0.0"
]'

我们将使用pydantic配置Django从环境变量中读取设置, with this code snippet:

# src / hello_visitor /设置.py
import os
from pathlib import Path
from pydantic import (
    BaseSettings,
    PostgresDsn,
    EmailStr,
    HttpUrl,
)
import dj_database_url

#在项目内部构建路径:BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

类SettingsFromEnvironment (BaseSettings):
    定义环境变量及其类型和可选默认值"""

    # PostgreSQL
    DATABASE_URL: PostgresDsn
    DATABASE_SSL: bool = True

    # Django
    SECRET_KEY: str
    DEBUG: bool = False
    DEBUG_TEMPLATES: bool = False
    USE_SSL: bool = False
    ALLOWED_HOSTS: list

    class Config:
        定义pypytic环境加载的配置

        env_file = str(BASE_DIR / ".env")
        case_sensitive = True

config = SettingsFromEnvironment()

os.environ["DATABASE_URL"] = config . conf.DATABASE_URL
DATABASES = {
    “默认”:dj_database_url.配置(conn_max_age = 600, ssl_require =配置.DATABASE_SSL)
}

SECRET_KEY = config.SECRET_KEY
DEBUG = config.DEBUG
DEBUG_TEMPLATES = config.DEBUG_TEMPLATES
USE_SSL = config.USE_SSL
ALLOWED_HOSTS = config.ALLOWED_HOSTS

# ...

如果您在完成之前的编辑后遇到任何问题,请比较我们的制作 settings.py file with the 源代码存储库中的版本.

Model Creation

我们的应用程序跟踪并显示主页访问者计数. We need a model 来保持计数,然后使用 Django的对象关系映射器 (ORM)通过数据迁移初始化单个数据库行.

First, we’ll create our VisitCounter model:

# hello-visitor / src /网页/模型.py
"""定义模型"""
from django.db import models


类VisitCounter(模型.Model):
    """访问柜台的ORM """

    count = models.IntegerField()

    @staticmethod
    def insert_visit_counter ():
        """用一个访问计数器填充数据库. 从数据迁移调用."""
        visit_counter = VisitCounter(count=0)
        visit_counter.save()

    def __str__(self):
        访问次数:{self.count}"

接下来,我们将触发迁移来创建我们的数据库表:

# in the `src` folder
python manage.py makemigrations
python manage.py migrate

To verify that the homepage_visitcounter 表存在时,我们可以在pgAdmin4中查看数据库.

接下来,我们需要将初始值放入 homepage_visitcounter table. 让我们用Django脚手架创建一个单独的迁移文件来完成:

#从'src'目录
python manage.Py makemigration——空主页

我们将调整创建的迁移文件以使用 VisitCounter.insert_visit_counter 方法,我们在本节开头定义:

# src /网页/迁移/ 0002 _auto _-------_----.py 
#注意:破折号依赖于执行时间.
from django.db import migrations
from ..模型导入VisitCounter

Def insert_default_items(apps, _schema_editor):
    """用一个访问计数器填充数据库."""
    #要了解应用程序,请参阅:
    # http://docs.djangoproject.com/en/3.2 /主题/迁移/ #数据迁移
    VisitCounter.insert_visit_counter()


类迁移(迁移.Migration):
    """Runs a data migration."""

    dependencies = [
        (“主页”、“0001 _initial”),
    ]

    operations = [
        migrations.RunPython (insert_default_items),
    ]

现在我们已经准备好执行这个修改后的迁移 homepage app:

#从'src'目录
python manage.py migrate homepage

让我们通过查看表的内容来验证迁移是否正确执行:

浏览器中的pgAdmin4屏幕,显示查询“SELECT * FROM public”.homepage_visitcounter ORDER BY id ASC". Data Output选项卡显示该表中有一行. 代理键id字段值为1,count字段值为0.

We see that our homepage_visitcounter 表已经存在,并且已经用初始访问计数0填充. 处理好数据库之后,我们将专注于创建UI.

创建和配置视图

我们需要实现UI的两个主要部分:视图和模板.

We create the homepage 视图以增加访问者计数, save it to the database, 并将该计数传递给模板以显示:

# src/homepage/views.py
from django.快捷方式导入get_object_or_404,渲染
from .模型导入VisitCounter

def index(request):
    """查看为应用程序主页面."""
    VisitCounter = get_object_or_404(VisitCounter, pk=1)

    visit_counter.count += 1
    visit_counter.save()

    Context = {"visit_counter": visit_counter}
    返回渲染请求,“主页/索引”.html", context)

我们的Django应用程序需要监听目标为 homepage. 为了配置这个设置,我们将添加这个文件:

# src/homepage/urls.py
"""Defines urls"""
from django.urls import path

from . import views

#应用的URLconf的命名空间
App_name = "主页" # pylint: disable=invalid-name

urlpatterns = [
    path("", views.index, name="index"),
]

For our homepage 申请要送达,我们必须在不同的地方注册 urls.py file:

# src/hello_visitor/urls.py
from django.contrib import admin
from django.url导入包括,路径

urlpatterns = [
    路径(" ",包括(“主页.urls")),
    path("admin/", admin.site.urls),
]

我们项目的基本HTML模板将保存在一个新文件中, src /模板/布局/基地.html:


{% load static %}


  
    
    
    

    
    

    Hello, visitor!
    
  
  
  
    {% block main %}{% endblock %}

    
    

  

我们将扩展基本模板 homepage app in a new file, src /模板/网页/索引.html:

{% extends "layouts/base.html" %}

{% block main %}
  

Hello, visitor {{ visit_counter.count }}!

{% endblock %}

创建UI的最后一步是告诉Django在哪里可以找到这些模板. Let’s add a TEMPLATES['DIRS'] dictionary item to our settings.py file:

# src / hello_visitor /设置.py
TEMPLATES = [
    {
        ...
        'DIRS': [BASE_DIR / 'templates'],
        ...
    },
]

我们的用户界面现在已经实现,我们几乎准备好测试应用程序的功能了. Before we do our testing, 我们需要准备好环境的最后一部分:静态内容缓存.

我们的静态内容配置

避免在我们的开发系统上走架构上的捷径, 我们将配置静态内容缓存来反映我们的生产环境.

我们将把项目的所有静态文件保存在一个目录中, src/static,并指示Django在部署前收集这些文件.

我们将在应用程序中使用Toptal的徽标 favicon and store it as src/static/favicon.ico:

# from `src` folder
mkdir static
cd static
wget http://frontier-assets.likethemoviesband.com/83b2f6e0d02cdb3d951a75bd07ee4058.png
83 mv b2f6e0d02cdb3d951a75bd07ee4058.png favicon.ico

接下来,我们将配置Django来收集静态文件:

# src / hello_visitor /设置.py
#静态文件(CSS, JavaScript,图像)
# a la http://docs.djangoproject.com/en/3.2/howto/static-files/
#
我们将存储静态文件的源位置
STATICFILES_DIRS = [BASE_DIR / "static"]
#构建Django收集所有静态文件的输出位置
STATIC_ROOT = BASE_DIR / "staticfiles"
STATIC_ROOT.mkdir(exist_ok=True)

引用位于STATIC_ROOT中的静态文件时使用的# URL.
STATIC_URL = "/static/"

STATICFILES_STORAGE = "白噪声.storage.CompressedManifestStaticFilesStorage”

We only want to store our original static files in the source code repository; we do not want to store the production-optimized versions. 让我们把后者加到 .gitignore with this simple line:

staticfiles

我们的源代码库正确地存储了所需的文件, 现在我们需要配置缓存系统来处理这些静态文件.

Static File Caching

在生产环境中(因此在开发环境中也是如此),我们将使用 WhiteNoise 更有效地为Django应用程序的静态文件提供服务.

我们将WhiteNoise注册为中间件,方法是向我们的 src / hello_visitor /设置.py file. 注册顺序有严格的定义,并且 WhiteNoiseMiddleware 必须紧接在 SecurityMiddleware:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    # ...
]

STATICFILES_STORAGE = '白噪声.storage.CompressedManifestStaticFilesStorage”

现在应该在我们的开发环境中配置静态文件缓存, 使我们能够运行应用程序.

运行我们的开发服务器

我们已经编写了一个完整的应用程序,现在可以用下面的命令启动Django的嵌入式开发web服务器:

# in the `src` folder
python manage.py runserver

When we navigate to http://localhost:8000,每次刷新页面,计数都会增加:

一个浏览器窗口,显示pydantic Django应用程序的主屏幕, which says, "Hello, visitor!一行是“1”,下一行是“1”.

现在,我们有了一个可以工作的应用程序,当我们刷新页面时,它将增加其访问计数.

Ready To Deploy

本教程涵盖了在美观的环境中创建工作应用程序所需的所有步骤 Django 与生产相匹配的开发环境. 在第3部分中,我们将介绍将应用程序部署到其生产环境. 我们的额外练习也值得探索一下,这些练习突出了Django和pydantic的优点:它们包含在 code-complete repository 对于这个pydantic教程.


Toptal Engineering博客向 Stephen Davidson 为了检查和测试本文中提供的代码示例.

Understanding the basics

  • How fast is pydantic?

    pydantic开箱即用,比其他验证库更快. 官方pydantic文档中提供了已发布的基准测试.

  • 我可以在Django中使用pydantic吗?

    Yes. Pydantic是一个普通的Python包,可以简单地通过pip安装它来与Django一起使用.

  • 哪种环境最适合Django?

    我们将“环境”定义为开发或托管应用程序的系统. In this case, 最好的开发环境被定义为与生产中使用的环境相匹配.

  • 为什么要有独立的开发和生产环境?

    面向用户的网站应该始终运行在一个安全的环境中,只有在新代码经过广泛测试后才会更新新代码. 新代码是在单独的开发环境中创建的,并且在将其部署到生产环境之前,通常在一个或多个登台环境中进行测试.

聘请Toptal这方面的专家.
Hire Now
Arjaan Buijk的头像
Arjaan Buijk

Located in 普利茅斯,密歇根州,美国

Member since June 4, 2018

About the author

Arjaan是一名高级工程师和数据科学家,他为国际银行和保险公司创建了专注于Rasa的关键任务云解决方案. 他设计并教授大规模Kubernetes解决方案.

Toptal作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

Expertise

Previously At

Rasa

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

Toptal Developers

Join the Toptal® community.

\n\n \n\n\n\n

我们将扩展基本模板 homepage app in a new file, src /模板/网页/索引.html:

\n\n
{% extends \"layouts/base.html\" %}\n\n{% block main %}\n  
\n
\n
\n
\n

Hello, visitor {{ visit_counter.count }}!

\n
\n
\n
\n
\n{% endblock %}\n
\n\n

创建UI的最后一步是告诉Django在哪里可以找到这些模板. Let’s add a TEMPLATES['DIRS'] dictionary item to our settings.py file:

\n\n
# src / hello_visitor /设置.py\nTEMPLATES = [\n    {\n        ...\n        'DIRS': [BASE_DIR / 'templates'],\n        ...\n    },\n]\n
\n\n

我们的用户界面现在已经实现,我们几乎准备好测试应用程序的功能了. Before we do our testing, 我们需要准备好环境的最后一部分:静态内容缓存.

\n\n

我们的静态内容配置

\n\n

避免在我们的开发系统上走架构上的捷径, 我们将配置静态内容缓存来反映我们的生产环境.

\n\n

我们将把项目的所有静态文件保存在一个目录中, src/static,并指示Django在部署前收集这些文件.

\n\n

我们将在应用程序中使用Toptal的徽标 favicon and store it as src/static/favicon.ico:

\n\n
# from `src` folder\nmkdir static\ncd static\nwget http://frontier-assets.likethemoviesband.com/83b2f6e0d02cdb3d951a75bd07ee4058.png\n83 mv b2f6e0d02cdb3d951a75bd07ee4058.png favicon.ico\n
\n\n

接下来,我们将配置Django来收集静态文件:

\n\n
# src / hello_visitor /设置.py\n#静态文件(CSS, JavaScript,图像)\n# a la http://docs.djangoproject.com/en/3.2/howto/static-files/\n#\n我们将存储静态文件的源位置\nSTATICFILES_DIRS = [BASE_DIR / \"static\"]\n#构建Django收集所有静态文件的输出位置\nSTATIC_ROOT = BASE_DIR / \"staticfiles\"\nSTATIC_ROOT.mkdir(exist_ok=True)\n\n引用位于STATIC_ROOT中的静态文件时使用的# URL.\nSTATIC_URL = \"/static/\"\n\nSTATICFILES_STORAGE = \"whitenoise.storage.CompressedManifestStaticFilesStorage\"\n
\n\n

We only want to store our original static files in the source code repository; we do not want to store the production-optimized versions. 让我们把后者加到 .gitignore with this simple line:

\n\n
staticfiles\n
\n\n

我们的源代码库正确地存储了所需的文件, 现在我们需要配置缓存系统来处理这些静态文件.

\n\n

Static File Caching

\n\n

在生产环境中(因此在开发环境中也是如此),我们将使用 WhiteNoise 更有效地为Django应用程序的静态文件提供服务.

\n\n

我们将WhiteNoise注册为中间件,方法是向我们的 src / hello_visitor /设置.py file. 注册顺序有严格的定义,并且 WhiteNoiseMiddleware 必须紧接在 SecurityMiddleware:

\n\n
MIDDLEWARE = [\n    'django.middleware.security.SecurityMiddleware',\n    'whitenoise.middleware.WhiteNoiseMiddleware',\n    # ...\n]\n\nSTATICFILES_STORAGE = '白噪声.storage.CompressedManifestStaticFilesStorage”\n
\n\n

现在应该在我们的开发环境中配置静态文件缓存, 使我们能够运行应用程序.

\n\n

运行我们的开发服务器

\n\n

我们已经编写了一个完整的应用程序,现在可以用下面的命令启动Django的嵌入式开发web服务器:

\n\n
# in the `src` folder\npython manage.py runserver\n
\n\n

When we navigate to http://localhost:8000,每次刷新页面,计数都会增加:

\n\n

一个浏览器窗口,显示pydantic Django应用程序的主屏幕, which says, \"Hello, visitor!\" on one line and \"1\" on the next.

\n\n

现在,我们有了一个可以工作的应用程序,当我们刷新页面时,它将增加其访问计数.

\n\n

Ready To Deploy

\n\n

本教程涵盖了在美观的环境中创建工作应用程序所需的所有步骤 Django 与生产相匹配的开发环境. 在第3部分中,我们将介绍将应用程序部署到其生产环境. 我们的额外练习也值得探索一下,这些练习突出了Django和pydantic的优点:它们包含在 code-complete repository 对于这个pydantic教程.

\n\n
\n\n

Toptal Engineering博客向 Stephen Davidson 为了检查和测试本文中提供的代码示例.

\n","as":"div","isContentFit":true,"sharingWidget":{"url":"http://hjat.likethemoviesband.com/django/optimize-your-environment-for-development-and-production-a-pydantic-tutorial-part-2","title":"Optimized Development Environment: Pydantic Tutorial, Part 2","text":null,"providers":["linkedin","twitter","facebook"],"gaCategory":null,"domain":{"name":"developers","title":"Engineering","vertical":{"name":"developers","title":"Developers","publicUrl":"http://hjat.likethemoviesband.com/developers"},"publicUrl":"http://hjat.likethemoviesband.com/developers/blog"},"hashtags":"Python,Django,Cloud"}}