Django model 项目配置详解

setting.py 配置文件

在 Django 的 settings.py 文件中,LANGUAGE_CODE 和 TIME_ZONE 是重要的配置选项,它们分别用于设置语言代码和时区。这两个设置可以根据您的需求进行自定义,但有一些规范和建议需要遵循。

LANGUAGE_CODE

LANGUAGE_CODE 用于指定您应用的默认语言。默认为:

LANGUAGE_CODE = 'en-us'  # 英文(美国)
  • 可用值
    • 该值应该是有效的语言代码,通常使用 ISO 639-1 标准(两个字母的语言代码)和国家/地区的 ISO 3166-1 标准(两个字母的国家代码),以连字符(-)连接。
    • 常见值:
      • 英文(美国):'en-us'
      • 中文(简体):'zh-hans'
      • 中文(繁体):'zh-hant'
      • 西班牙语:'es'
      • 法语:'fr'

TIME_ZONE

定义TIME_ZONE 用于设置系统的时区。默认为:

TIME_ZONE = 'UTC'  # 设置为协调世界时
  • 可用值
    • TIME_ZONE 应该是 Django 支持的有效时区,通常可以从 IANA 时区数据库 中查找。
    • 常见值:
      • 协调世界时:'UTC'
      • 北京时间:'Asia/Shanghai'
      • 纽约时间:'America/New_York'
      • 伦敦时间:'Europe/London'

静态文件添加

在 Django 项目中,静态文件(如 CSS、JavaScript 和图像文件)的管理和组织是至关重要的。合理地配置静态文件目录可以确保项目的可维护性和性能。以下是关于 Django 项目中静态文件的组织、获取逻辑以及与其他框架的不同之处的详细解释。

项目级别的静态目录结构

将静态文件放在项目的根目录下,通常有一个专门的 static 目录。

mysite/
├── static/
│   ├── css/
│   │   └── style.css
│   ├── js/
│   │   └── script.js
│   └── images/
│       └── my_image.jpg
├── manage.py
└── mysite/
    └── settings.py

多个 Django 应用,可以在每个应用中创建一个 static 目录,通常结构如下:

blog/
│
├── static/
│   └── blog/
│       ├── css/
│       │   └── blog.css
│       ├── js/
│       │   └── blog.js
│       └── images/
│           └── blog_logo.png
│
├── templates/
│   └── blog/
│       └── index.html
├── models.py
├── views.py
└── ...

在 settings.py 中,添加以下配置,告诉 Django 如何处理静态文件:

import os

# BASE_DIR 表示项目根目录
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# 静态文件的 URL (即在浏览器中访问时的前缀)
STATIC_URL = '/static/'

# 指定静态文件的文件夹
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),  # 项目级别的静态文件目录
]

# 你可以使用这个选项来定义不在 STATICFILES_DIRS 里的应用的静态文件的位置,通常不需要手动设置

使用静态文件

首先在模板文件顶部加载静态文件的模板标签库:

{% load static %}

然后可以使用 {% static %} 标签引用静态文件。例如,引用 CSS 和 JavaScript 文件:

<link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
<script type="text/javascript" src="{% static 'js/script.js' %}"></script>

基于项目https://www.ljh.cool/wp-admin/post.php?post=43305&action=edit

继续完善静态文件内容:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Blog Index</title>
    
    <!-- 加载静态文件 -->
    {% load static %}
    <link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">  <!-- 引用 CSS 文件 -->
    <script type="text/javascript" src="{% static 'js/script.js' %}"></script>  <!-- 引用 JS 文件 -->
</head>
<body>
    <h1>Welcome to the Blog Index!</h1>
    <p>This is where you can find the latest posts.</p>

    <!-- 添加静态图片 -->
    <h2>My Image:</h2>
    <img src="{% static 'images/my_image.jpg' %}" alt="My Image" style="max-width: 100%; height: auto;">
    
    <h2>Posts:</h2>
    <ul>
        {% for post in posts %}
            <li>
                <strong>{{ post.title }}</strong><br>
                {{ post.content }}<br>
                <em>Published on: {{ post.created_at }}</em>
            </li>
        {% empty %}
            <li>No posts available.</li>
        {% endfor %}
    </ul>
</body>
</html>

打开浏览器,访问静态资源,如 http://127.0.0.1:8000/static/images/my_image.jpg

Django model 项目配置详解

通过访问 http://127.0.0.1:8000/blog/ 加载静态资源

Django model 项目配置详解

apps.py 配置

在 Django 中,每个应用(app)都有一个 apps.py 文件,里面定义了一个应用的配置类。默认情况下,当您创建一个新应用时,Django 会自动为您生成这个文件。

在 apps.py 中,您将定义一个继承自 django.apps.AppConfig 的类。这个类主要包含以下内容:

  • 名称 (name):指定应用的名称,通常是该应用的模块名。
  • 标签 (label):用于唯一标识该应用的标签,可以是与名不同(可选)。
  • 初始化 (ready):这是用于初始化日志、信号等的地方。

使用 AppConfig

信号(Signals):Django 信号框架用来处理在特定事件发生时自动执行的逻辑。例如,您可以在创建模型实例时发送通知或记录日志。

应用信号:如果您使用了 Django 的信号机制(例如 post_save 或 pre_save),通常会在 ready 方法中进行连接。示例如下:

from django.apps import AppConfig
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Post

class BlogConfig(AppConfig):
    name = 'blog'
    verbose_name = "Blog Application"

    def ready(self):
        # 在这里连接信号
        from . import signals

信号的工作原理

  • 信号 是 Django 的一种机制,允许应用程序在某些事件发生时执行特定的操作。例如,当新的 Post 模型实例被保存时,您可能希望自动执行某些操作(如更新其他模型、发送通知等)。
  • post_save 信号 是在模型实例保存后自动发送的信号。您可以定义一个接收器(receiver)函数来响应这个信号:
@receiver(post_save, sender=Post)
def post_save_handler(sender, instance, created, **kwargs):
    if created:
        print(f"New post created: {instance.title}")
    else:
        print(f"Post updated: {instance.title}")

以下是一个示例 apps.py 文件的结构,以 blog 应用为例:

from django.apps import AppConfig


class BlogConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'blog'
    verbose_name = "Blog Application"  # 应用的可读名称
default_auto_field = 'django.db.models.BigAutoField'
  • 从 Django 3.2 开始,引入了 default_auto_field 选项来指定生成模型主键的默认类型。BigAutoField 是一个 64 位整数,可以自动递增,适用于希望支持更大数量记录的应用。
  • 使用 BigAutoField 比较适合大型应用,因为它允许比默认的 AutoField(32 位整数)支持更多的记录。

这个配置类有什么用?

  • 全局配置AppConfig 可以用于管理 Django 应用的元数据,配置如自动字段、显示名称等。
  • 信号连接:在将来使用信号(如保存、删除模型时)时,您可以在类的 ready 方法中设置信号的连接。
  • 更容易的管理和扩展:通过使用应用程序配置,您能够灵活地管理应用程序的行为。例如,您可以根据环境变量来设置特定于环境的行为。

model.py 模型概述

Django 模型是用于定义数据结构的 Python 类,通常继承自 django.db.models.Model。模型允许开发者通过 Python 代码描述数据库中的表和字段,Django 的 ORM(对象关系映射)自动将模型转换为数据库表。

为什么使用模型?

  1. 数据抽象:通过模型,您无需直接编写 SQL 语句,Django 会处理与数据库的交互。
  2. 数据验证:模型字段提供数据类型和约束,Django 在处理数据前进行验证。
  3. 易于维护:模型使代码更清晰,便于集中管理与数据相关的逻辑。

Django 模型组成部分

1、类定义
模型定义为一个 Python 类,例如:

from django.db import models

class Post(models.Model):
    ...

2、字段定义:

模型属性定义为字段,设置数据类型和约束。常用字段类型包括:

  • CharField:用于存储短文本。需要设置最大长度。
  • TextField:用于存储长文本,没有长度限制。
  • IntegerField:用于存储整数。
  • FloatField:用于存储浮点数。
  • DecimalField:用于存储固定精度的十进制数,适合金融计算。
  • DateField:用于存储日期。
  • DateTimeField:用于存储日期和时间。
  • BooleanField:用于布尔值(True 或 False)。
  • EmailField:用于存储电子邮件地址,自动验证格式。
  • URLField:用于存储 URL 地址。
  • ImageField/FileField:用于处理文件上传。

3、方法定义:

可以定义方法增加业务逻辑,例如重载 __str__ 方法,使其返回可读字符串表示。

def __str__(self):
    return self.title

Django 模型字段选项

null:指示数据库是否可以存储 NULL 值。

title = models.CharField(max_length=200, null=True)

blank:控制该字段在表单中是否可留空。

title = models.CharField(max_length=200, blank=True)

unique:指示字段在整个表中必须保持唯一性。

email = models.EmailField(unique=True)

default:设置字段的默认值。

status = models.CharField(max_length=20, default='draft')

完整的模型示例

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=200, null=False, blank=False, unique=True)
    content = models.TextField(null=True, blank=True)
    author_email = models.EmailField(unique=True)
    price = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    created_at = models.DateTimeField(auto_now_add=True)
    is_published = models.BooleanField(default=False)
    
    def __str__(self):
        return self.title

在修改模型后,需要运行以下命令生成并应用迁移,以更新数据库结构:

python manage.py makemigrations  # 生成迁移文件
python manage.py migrate         # 更新数据库

利用 Django ORM 进行操作

使用 Django ORM,通过创建、查询、更新和删除记录进行数据操作:

# 创建记录
new_post = Post(title="My First Post", content="This is the body of my post.")
new_post.save()  # 保存到数据库

# 查询记录
all_posts = Post.objects.all()  # 获取所有文章
specific_post = Post.objects.get(id=1)  # 获取特定文章

# 更新记录
post_to_update = Post.objects.get(id=1)
post_to_update.title = "Updated Title"
post_to_update.save()  # 保存更改

# 删除记录
post_to_delete = Post.objects.get(id=1)
post_to_delete.delete()  # 删除该文章

模型外键定义

在 Django 中,您可以使用 ForeignKey 字段在模型中建立外键关系。下面是如何实现的详细示例。

假设我们要创建一个博客应用,其中的 Post 模型可以有许多评论(Comment),而每个评论是对应某个帖子的。您可以在 Comment 模型中定义一个外键来指向 Post 模型。

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=200, null=False, blank=False, unique=True)
    content = models.TextField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    
    def __str__(self):
        return self.title

class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)  # 外键字段,用于链接到 Post
    content = models.TextField(null=False, blank=False)       # 评论内容
    created_at = models.DateTimeField(auto_now_add=True)      # 评论创建时间

    def __str__(self):
        return f'Comment on {self.post.title}'  # 显示评论相关的帖子标题

重要参数说明

在 ForeignKey 中,您可以设置一些重要的参数:

on_delete:指示当关联的对象被删除时,外键字段的行为。

  • models.CASCADE:级联删除,如果关联的帖子被删除,则相关的评论也会被删除。
  • models.SET_NULL:设置为 NULL,前提是外键字段允许 NULL
  • models.PROTECT:防止删除关联对象,如果尝试删除将抛出错误。
  • models.SET_DEFAULT:将外键设置为字段的默认值。

related_name:用于指定反向关系的名称。在 Comment 模型中可以定义反向关系。例如:

post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')

这样可以通过 post_instance.comments.all() 获取与该 post_instance 相关的所有评论。

Django ORM 和外键的使用

有了外键字段后,您可以用 Django 的 ORM 轻松查询和管理这两个模型之间的关系。

创建记录

# 创建一个 Post
new_post = Post(title="My First Post", content="This is the content of my first post.")
new_post.save()

# 创建与 Post 关联的 Comment
comment1 = Comment(post=new_post, content="Great post!")
comment1.save()

查询记录

你可以从 Post 模型中获取所有相关的评论:

post = Post.objects.get(id=1)  # 获取 ID 为 1 的帖子
comments = post.comments.all()   # 获取与该帖子关联的所有评论
for comment in comments:
    print(comment.content)

修改表名

以下是如何在 Django 中修改表名的示例:

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=200, null=False, blank=False, unique=True)
    content = models.TextField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = 'custom_post_table'  # 指定自定义表名

在这个例子中,db_table 属性被设置为了 'custom_post_table',这意味着即使 Django 的默认行为下表名为 blog_post(即应用名称加下划线和模型名称),实际在数据库中将会创建一个名为 custom_post_table 的表。

注意事项:如果已经迁移过数据库并且希望修改表名,您需要执行以下步骤:

  • 修改模型的 Meta 类以包含 db_table。(添加class Meta: db_table ='xxx')
  • 执行 makemigrations 命令生成迁移文件。(python manage.py makemigrations)
  • 执行 migrate 命令更新数据库。(python manage.py migrate

枚举类型

枚举(enum)是一种特殊的类型,可以让你定义一组固定和有限的选项。比如,你可以用它来表示文章的状态,比如 "草稿"(draft)、"已发布"(published)和 "归档"(archived)。使用枚举可以让你的代码更清晰,避免使用字符串。

为什么使用枚举?

  1. 限制选项:它只允许你选择特定的值。比如,对于文章的状态,你只能选择 "草稿"、"已发布" 或 "归档"。
  2. 易于维护:如果你想改变或添加状态,只需要在一处修改,不需要到处找。

在 Django 中,你可以通过模型的 choices 属性来使用枚举。这里有一个简单的例子:

from django.db import models

class Post(models.Model):  # 定义一个 Post 类(文章)
    
    # 定义文章状态的三个选项
    class Status(models.TextChoices):
        DRAFT = 'draft', '草稿'
        PUBLISHED = 'published', '已发布'
        ARCHIVED = 'archived', '归档'

    # 定义标题字段
    title = models.CharField(max_length=200, unique=True)  # 限制最多200个字符,且名称必须唯一
    # 定义内容字段
    content = models.TextField()  # 可以存储任意长的文本
    # 定义状态字段,用于选取枚举值
    status = models.CharField(max_length=10,
                              choices=Status.choices,  # 允许的选项
                              default=Status.DRAFT)  # 默认状态是草稿
    # 创建时间,自动设置为当前时间
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title  # 显示文章的标题
  1. 状态定义:我们创建了一个内部类 Status,通过 TextChoices 定义了三个状态:
    • DRAFT 值为 'draft',中文显示为 '草稿'
    • PUBLISHED 值为 'published',中文显示为 '已发布'
    • ARCHIVED 值为 'archived',中文显示为 '归档'
  2. 标题和内容title 字段是用来存文章的标题,而 content 字段是用来存文章的内容。
  3. 状态字段
    • status 字段定义了可以选择的状态,它只能是 'draft''published' 或 'archived' 中的一个。
    • 如果没有手动设置状态,默认值是 'draft'

修改数据库引擎

我这里在 macOS 上操作,对于 Ubuntu 或 windows 用户自行搜索文档:

步骤 1: 安装 MySQL

brew install mysql

步骤 2: 安装 mysqlclient 库

安装相关的开发工具

您可能需要安装 pkg-config 及一些开发库。

brew install pkg-config
brew install openssl
brew install mariadb-connector-c

设置环境变量(在虚拟环境中配置)

export PATH="/usr/local/opt/openssl/bin:$PATH"
export LDFLAGS="-L/usr/local/opt/openssl/lib"
export CPPFLAGS="-I/usr/local/opt/openssl/include"

安装 mysqlclient

pip install mysqlclient
Django model 项目配置详解

步骤 3: 修改 settings.py 配置

打开 Django 项目中的 settings.py 文件,找到 DATABASES 部分。您需要将其更改为 MySQL 数据库的配置。以下是一个使用 MySQL 的示例配置:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 设置为 MySQL
        'NAME': 'your_database_name',          # 您的数据库名称
        'USER': 'your_username',               # 您的用户名
        'PASSWORD': 'your_password',           # 您的密码
        'HOST': 'localhost',                   # 数据库主机
        'PORT': '3306',                        # MySQL 的默认端口
    }
}

步骤 4: 创建数据库

创建您在 settings.py 中指定的数据库:

CREATE DATABASE your_database_name CHARACTER SET UTF8mb4 COLLATE utf8mb4_unicode_ci;

步骤 5: 迁移数据

在修改数据库引擎并创建数据库后,您需要运行以下命令来生成迁移文件并应用迁移,以在新的 MySQL 数据库上创建所有表:

python manage.py makemigrations
python manage.py migrate

步骤 6: 测试连接

python manage.py runserver ,然后在浏览器中访问 http://127.0.0.1:8000/,查看应用是否正常工作。

例如:我们将https://www.ljh.cool/43305.html的数据库从 sqlite3 迁移到 mysql 过程:

# 创建数据库:
CREATE DATABASE blog_db CHARACTER SET UTF8mb4 COLLATE utf8mb4_unicode_ci;

# 修改 settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 设置为 MySQL
        'NAME': 'blog_db',           # 您的数据库名称
        'USER': 'root',              # 您的用户名
        'PASSWORD': 'XXXXXXXX',      # 您的密码
        'HOST': 'localhost',         # 数据库主机
        'PORT': '3306',              # MySQL 的默认端口
    }
}

# 迁移数据
python manage.py makemigrations
python manage.py migrate

查看迁移结果:

Django model 项目配置详解

后台登录插入一些内容,查看数据库是否成功插入

Django model 项目配置详解
Django model 项目配置详解

额外补充:假如使用pymysql

如果您使用 mysqlclient 并且成功地连接了 MySQL 数据库,那么您无需进行额外的配置。默认情况下,Django 会自动识别 mysqlclient。但是,如果您决定使用 pymysql 作为 MySQL 的数据库驱动程序,您需要在 Django 项目的 __init__.py 文件中添加以下代码:

在 mysite/__init__.py 中添加:

import pymysql
pymysql.install_as_MySQLdb()

这段代码的作用是让 pymysql 作为 MySQLdb 库来使用,因为 Django 的 MySQL 数据库后端默认是 MySQLdb。这就可以确保 Django 可以使用 pymysql 来与 MySQL 数据库进行交互。如果不在工程包中导入pymysql,会在执行迁移时报错:No module named 'MySQLdb'

Python 的 shell 调试 Django 应用程序

使用 Python 的 shell(REPL 环境)来调试 Django 应用程序可以帮助您理解 ORM(对象关系映射)如何工作,以及如何与数据库交互。您可以在 Django 的 shell 中执行操作,查询数据库等。

使用 Django Shell

在 Django 项目的根目录下(与 manage.py 位于同一目录)打开命令行或终端,然后输入以下命令进入 Django shell:

python manage.py shell

这将启动一个 Python 交互式 shell,您可以在其中直接使用 Django 的模型和功能。

一些基本操作

导入模型
首先,您需要导入 Post 模型:

from blog.models import Post

这里的 blog 是您的 Django 应用名称,如果您的应用名称不同,请相应地更改。

创建新文章
例如,您可以使用以下代码创建一个新的 Post 实例:

实例方法创建

new_post = Post(title="My First Post", content="This is the content of my first post.")
new_post.save()  # 保存到数据库

查询集方法创建

在需要更多灵活性和控制的情况下,使用 .save() 方法会更合适。如果您仅仅是创建新对象并保存,无需复杂逻辑,Post.objects.create() 可能是更为优雅和简洁的选择。

Post.objects.create(title="My Second Post", content="This is the content of my second post.")

批量创建

使用 bulk_create() 方法可以一次性创建多个对象。例如,假设我们要创建多个新的 Post 对象,可以这样做:

from yourapp.models import Post  # 替换为你的实际应用和模型导入

# 创建多个 Post 对象
posts_to_create = [
    Post(title="博客文章 1", content="内容 1", status="已发布"),
    Post(title="博客文章 2", content="内容 2", status="草稿"),
    Post(title="博客文章 3", content="内容 3", status="已发布"),
]

# 批量创建
Post.objects.bulk_create(posts_to_create)
  • 实例方法适合于你需要获取具体的对象实例时,便于后续对该实例的其他操作。
  • 查询集方法适合于批量操作,且更为高效和简洁,特别是在处理大量数据时。

更新文章
您可以更新某个文章的标题或内容:

实例方法更新

post = Post.objects.get(id=1)  # 获取 ID 为 1 的 Post
post.title = "修改标题后的博客文章 1"  # 更新标题
post.save()  # 保存更改

查询集方法更新

当你要更新多条记录时,可以使用 update() 方法借助 filter() 来实现 。filter() 返回的结果是多个对象的列表

Post.objects.filter(id=1).update(title="修改标题后的博客文章 1")

删除文章

使用 get() 方法获取对象并调用 delete() 方法来删除数据

post_to_delete = Post.objects.get(id=1)  # 获取要删除的 Post
post_to_delete.delete()  # 删除该 Post

使用 filter() 方法结合 delete() 方法来删除数据

Post.objects.filter(id=1).delete()

Django Shell 查询操作(重点)

目前数据库内容:

Django model 项目配置详解

1. 查询所有文章
获取所有的帖子并输出它们:

posts = Post.objects.all()  # 获取所有 Post 数据,返回结果为列表
for post in posts:
    print(post.title)  # 打印每个 Post 的标题

2. 获取特定文章
如果您知道某个帖子的 ID,可以轻松获取该帖子的内容:

post = Post.objects.get(id=1)  # 根据 ID 获取 Post,使用 get() 返回结果为单个对象
print(post.content)  # 打印该 Post 的内容

3. 使用特定字段查询

如果不知道帖子的 ID,可以通过其他属性进行查询。例如,通过标题或作者:

例如通过标题查询(如果查询的结果不存在,建议进行异常捕获)

# 假设要查找标题为 "博客文章 1" 的 Post
try:
    post = Post.objects.get(title="博客文章 1")  # 根据标题获取 Post
    print(post.content)  # 打印该 Post 的内容
except Post.DoesNotExist:
    print("没有找到该标题的帖子")

4. 使用 filter() 方法

filter() 方法可以用来根据某些条件获取多个对象。可以链式使用多个过滤条件:

# 获取状态为 "已发布" 的所有文章
published_posts = Post.objects.filter(status='已发布')
for post in published_posts:
    print(post.title)

你还可以使用 Q 对象组合查询条件,支持 OR 查询:

假设你想查找标题包含 "博客" 或者内容中包含 "first" 的文章。可以使用 Q 对象:

from django.db.models import Q

# 查询标题包含 "博客" 或内容中包含 "first" 的帖子
posts = Post.objects.filter(Q(title__icontains='博客') | Q(content__icontains='first'))
for post in posts:
    print(f'Title: {post.title}, Content: {post.content}')

5. 排序和限制结果

你可以使用 order_by() 方法对查询结果进行排序,使用 first() 或 last() 获取第一条或最后一条记录。

# 获取按发布日期降序排列的所有文章
# 按创建时间降序获取所有文章
posts = Post.objects.order_by('-created_at')
for post in posts:
    print(f'Title: {post.title}, Created At: {post.created_at}')

# 获取创建时间最新的文章
latest_post = Post.objects.order_by('-created_at').first()
if latest_post:
    print(f'最新文章: Title: {latest_post.title}, Created At: {latest_post.created_at}')

6. 使用切片

你可以使用切片来限制返回的结果数,例如获取前十条记录:

# 获取前两篇文章
top_two_posts = Post.objects.all()[:2]
for post in top_two_posts:
    print(f'Title: {post.title}, Created At: {post.created_at}')

7. 计数

你可以使用 count() 方法获取符合某个条件的记录数:

# 获取文章总数
total_posts = Post.objects.count()
print(f'总文章数: {total_posts}')

Django ORM 中一些复杂的查询语法技巧

我们要创建两个新的表:Author 表和 Comment 表

在 models.py 文件中定义两个新表对象:

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
    bio = models.TextField(blank=True, null=True)

    def __str__(self):
        return self.name


class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='posts')

    def __str__(self):
        return self.title


class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f'Comment by {self.author.name} on {self.post.title}'

创建迁移文件并应用

# 创建迁移文件
python manage.py makemigrations

# 应用迁移到数据库
python manage.py migrate

测试数据的插入

python manage.py shell

在 shell 中执行:

from blog.models import Author, Post, Comment  # blog 修改为你的应用名

# 创建作者
author1 = Author.objects.create(name="用户A", bio="技术爱好者")
author2 = Author.objects.create(name="用户B", bio="博客写手")

# 创建帖子
post1 = Post.objects.create(title="Django 入门", content="这是关于Django的基本知识.", author=author1)
post2 = Post.objects.create(title="Python 进阶", content="深入理解Python的特性.", author=author2)

# 创建评论
Comment.objects.create(post=post1, author=author2, content="非常棒的文章!")
Comment.objects.create(post=post1, author=author1, content="谢谢!")
Comment.objects.create(post=post2, author=author2, content="图文并茂,学习到了很多!")

插入结果:

Django model 项目配置详解

数据操作

1. F 对象

用途:
F 对象允许你在查询中引用模型字段的值,以便进行比较、算术运算等。这在需要根据同一模型的不同字段进行操作时非常有用。

示例:
假设你有一个 Post 模型,包含 likes 字段。你想找到所有点赞数大于 10 的帖子,并增加它们的点赞数。

from django.db.models import F

# 增加点赞数
Post.objects.filter(likes__gt=10).update(likes=F('likes') + 1)  # 增加点赞数

2. Q 对象

用途:
Q 对象用于构建复杂查询,支持逻辑运算符(如 AND、OR)。它使得组合多个查询条件变得更加灵活。

示例:
查找所有由“用户A”创作的帖子,或者评论内容中包含“图文并茂”的帖子:

from django.db.models import Q

posts = Post.objects.filter(Q(author__name='用户A') | Q(comments__content__icontains='图文并茂')).distinct()
for post in posts:
    print(f'Title: {post.title}, Author: {post.author.name}')

3. 聚合函数

用途:
Django 提供了一些内置的聚合函数(如 SumCountAvgMax 和 Min),用于在查询中获取统计信息。

示例:
获取每个作者所创作的帖子数量:

from django.db.models import Count

authors_with_post_count = Author.objects.annotate(post_count=Count('posts'))
for author in authors_with_post_count:
    print(f'Author: {author.name}, Post Count: {author.post_count}')

4. 关联查询

用途:
通过外键关系在查询中涉及多个表。Django ORM 允许通过模型属性轻松进行多表查询。

示例:
获取所有评论以及对应的帖子标题和作者:

comments = Comment.objects.select_related('post', 'author')  # 使用 select_related 来优化查询
for comment in comments:
    print(f'Comment by {comment.author.name} on post "{comment.post.title}": {comment.content}')

5. 使用 annotate() 进行复杂查询

用途:
annotate() 方法用于在查询集上添加计算字段,以汇总数据或计算汇总值。

示例:
获取每个帖子的评论数量:

from django.db.models import Count

posts_with_comment_count = Post.objects.annotate(comment_count=Count('comments'))
for post in posts_with_comment_count:
    print(f'Post: {post.title}, Comment Count: {post.comment_count}')

6. 复杂的筛选条件使用 exclude()

用途:
exclude() 方法用于从查询结果中排除满足特定条件的记录。

示例:
获取所有不是由“用户A”创作的帖子:

posts_not_by_author_a = Post.objects.exclude(author__name='用户A')
for post in posts_not_by_author_a:
    print(f'Title: {post.title}, Author: {post.author.name}')

发布者:LJH,转发请注明出处:https://www.ljh.cool/43387.html

Like (0)
LJH的头像LJH
Previous 6天前
Next 2023年4月20日 上午2:53

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注