每天40分玩转Django:Django模型

news/2024/12/15 20:27:47/

Django框架学习第2天:Django模型

一、课程概述

学习项目具体内容预计用时
模型定义模型类编写、字段类型、关系类型90分钟
ORM操作增删改查、高级查询、聚合函数90分钟
数据库迁移迁移命令、迁移文件、数据导入导出60分钟

在这里插入图片描述

二、模型定义

2.1 基本模型结构

# blog/models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import Userclass Category(models.Model):name = models.CharField(max_length=100, verbose_name='分类名称')description = models.TextField(blank=True, verbose_name='分类描述')created_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')class Meta:verbose_name = '分类'verbose_name_plural = verbose_nameordering = ['-created_time']def __str__(self):return self.nameclass Post(models.Model):STATUS_CHOICES = (('draft', '草稿'),('published', '发布'),)title = models.CharField(max_length=200, verbose_name='标题')slug = models.SlugField(max_length=250, unique_for_date='publish')author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts')body = models.TextField(verbose_name='正文')publish = models.DateTimeField(default=timezone.now, verbose_name='发布时间')created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')updated = models.DateTimeField(auto_now=True, verbose_name='更新时间')status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')category = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name='分类')tags = models.ManyToManyField('Tag', blank=True, verbose_name='标签')class Meta:ordering = ('-publish',)verbose_name = '文章'verbose_name_plural = verbose_namedef __str__(self):return self.titleclass Tag(models.Model):name = models.CharField(max_length=100, verbose_name='标签名称')created_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')class Meta:verbose_name = '标签'verbose_name_plural = verbose_namedef __str__(self):return self.name

2.2 常用字段类型

字段类型说明示例
CharField字符串字段title = models.CharField(max_length=200)
TextField长文本字段content = models.TextField()
IntegerField整数字段age = models.IntegerField()
DateTimeField日期时间字段created = models.DateTimeField(auto_now_add=True)
BooleanField布尔字段is_active = models.BooleanField(default=True)
EmailField邮件字段email = models.EmailField()
FileField文件字段file = models.FileField(upload_to=‘files/’)
ImageField图片字段image = models.ImageField(upload_to=‘images/’)

2.3 字段选项

# 字段选项示例
class Product(models.Model):name = models.CharField(max_length=100,           # 最大长度verbose_name='商品名称',   # 人性化名称unique=True,              # 唯一值db_index=True,           # 数据库索引help_text='请输入商品名称' # 帮助文本)price = models.DecimalField(max_digits=10,           # 最大位数decimal_places=2,        # 小数位数null=True,               # 允许为空blank=True              # 表单可以为空)

三、ORM操作

3.1 基本的CRUD操作

# 创建对象
# 方法1:
post = Post(title='第一篇博客', body='内容...', author=user)
post.save()# 方法2:
Post.objects.create(title='第二篇博客', body='内容...', author=user)# 查询对象
# 获取所有文章
posts = Post.objects.all()# 获取单个对象
post = Post.objects.get(id=1)# 过滤对象
draft_posts = Post.objects.filter(status='draft')
recent_posts = Post.objects.filter(publish__year=2024)# 更新对象
# 方法1:
post = Post.objects.get(id=1)
post.title = '新标题'
post.save()# 方法2:
Post.objects.filter(id=1).update(title='新标题')# 删除对象
post = Post.objects.get(id=1)
post.delete()

3.2 高级查询

# 查询API示例
from django.db.models import Q, Count, Avg
from django.utils import timezone# Q对象 - 复杂查询
# 查找标题包含"Django"或内容包含"Python"的文章
Post.objects.filter(Q(title__contains='Django') | Q(body__contains='Python'))# 查找不是草稿且作者是指定用户的文章
Post.objects.filter(~Q(status='draft'), author=user)# 聚合查询
# 统计每个分类下的文章数量
categories = Category.objects.annotate(post_count=Count('post'))# 查找文章数量大于5的分类
popular_categories = Category.objects.annotate(post_count=Count('post')
).filter(post_count__gt=5)# 关联查询
# 获取指定作者的所有文章
user.blog_posts.all()# 获取包含指定标签的所有文章
tag = Tag.objects.get(name='Django')
tag.post_set.all()

3.3 查询优化

# select_related() - 处理外键和一对一关系
# 一次性获取文章及其作者和分类信息
posts = Post.objects.select_related('author', 'category').all()# prefetch_related() - 处理多对多关系
# 一次性获取文章及其标签信息
posts = Post.objects.prefetch_related('tags').all()# 组合使用
posts = Post.objects.select_related('author', 'category').prefetch_related('tags').all()

四、数据库迁移

4.1 迁移命令

# 生成迁移文件
python manage.py makemigrations# 执行迁移
python manage.py migrate# 查看迁移文件的SQL语句
python manage.py sqlmigrate blog 0001# 检查迁移文件
python manage.py check

4.2 数据迁移示例

# migrations/0002_auto_20240112_1234.py
from django.db import migrations, modelsdef populate_slug(apps, schema_editor):Post = apps.get_model('blog', 'Post')for post in Post.objects.all():post.slug = f"{post.title.lower().replace(' ', '-')}-{post.id}"post.save()class Migration(migrations.Migration):dependencies = [('blog', '0001_initial'),]operations = [migrations.AddField(model_name='post',name='slug',field=models.SlugField(default='', max_length=250),preserve_default=False,),migrations.RunPython(populate_slug),]

五、实战练习:博客评论系统

# blog/models.py
class Comment(models.Model):post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')name = models.CharField(max_length=80, verbose_name='评论者')email = models.EmailField(verbose_name='邮箱')body = models.TextField(verbose_name='评论内容')created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')active = models.BooleanField(default=True, verbose_name='是否显示')class Meta:ordering = ('created',)verbose_name = '评论'verbose_name_plural = verbose_namedef __str__(self):return f'Comment by {self.name} on {self.post}'

5.1 评论视图

# blog/views.py
from django.shortcuts import render, get_object_or_404
from .models import Post, Comment
from .forms import CommentFormdef post_detail(request, year, month, day, post):post = get_object_or_404(Post,slug=post,status='published',publish__year=year,publish__month=month,publish__day=day)# 获取该文章的所有活动评论comments = post.comments.filter(active=True)if request.method == 'POST':comment_form = CommentForm(data=request.POST)if comment_form.is_valid():# 创建评论对象但不保存到数据库new_comment = comment_form.save(commit=False)# 指定评论的文章new_comment.post = post# 保存评论到数据库new_comment.save()else:comment_form = CommentForm()return render(request,'blog/post/detail.html',{'post': post,'comments': comments,'comment_form': comment_form})

六、进阶技巧

6.1 自定义模型管理器

# blog/models.py
class PublishedManager(models.Manager):def get_queryset(self):return super().get_queryset().filter(status='published')class Post(models.Model):# ... 其他字段 ...objects = models.Manager()  # 默认管理器published = PublishedManager()  # 自定义管理器# 使用自定义管理器
published_posts = Post.published.all()

6.2 模型信号

# blog/signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Post@receiver(post_save, sender=Post)
def create_post_slug(sender, instance, created, **kwargs):if created:instance.slug = f"{instance.title.lower().replace(' ', '-')}-{instance.id}"instance.save()

七、常见问题和解决方案

  1. 数据库迁移冲突:
# 重置迁移
python manage.py migrate blog zero
python manage.py makemigrations blog
python manage.py migrate blog
  1. 关联字段删除:
# 使用on_delete选项
author = models.ForeignKey(User,on_delete=models.SET_NULL,  # 设置为NULLnull=True,blank=True
)
  1. 大数据查询优化:
# 分批处理
from django.core.paginator import Paginator
paginator = Paginator(Post.objects.all(), 100)
for page in paginator.page_range:for post in paginator.page(page).object_list:# 处理每篇文章pass

八、作业和练习

  1. 创建一个完整的博客数据模型,包含用户、分类、标签、文章和评论
  2. 实现文章的增删改查功能
  3. 添加评论功能
  4. 实现文章分类和标签功能
  5. 优化查询性能

九、扩展阅读

  1. Django Model字段类型详解
  2. 数据库事务处理
  3. Django ORM高级查询技巧
  4. 数据库性能优化方案

怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!


http://www.ppmy.cn/news/1555399.html

相关文章

【数据结构——线性表】单链表的基本运算(头歌实践教学平台习题)【合集】

目录😋 任务描述 相关知识 测试说明 我的通关代码: 测试结果: 任务描述 本关任务:编写一个程序实现单链表的基本运算。 相关知识 为了完成本关任务,你需要掌握:初始化线性表、销毁线性表、判定是否为空表、求线性…

使用idea创建一个JAVA WEB项目

文章目录 1. javaweb项目简介2. 创建2.1 idea新建项目2.2 选择,命名2.3 打开2.4 选择tomcat运行2.5 结果 3. 总结 1. javaweb项目简介 JavaWeb项目是一种基于Java技术的Web应用程序,主要用于开发动态网页和Web服务。这种项目能够构建在Java技术栈之上&a…

使用 UniApp 实现简单的个人中心页面

1. 创建 UniApp 项目 首先,确保你已经安装了 HBuilderX 或其他支持 UniApp 的开发工具。然后创建一个新的 UniApp 项目。 # 使用 HBuilderX 创建新项目 # 选择 uni-app 模板 -> 选择 Vue.js 模板 -> 输入项目名称 -> 创建2. 安装依赖 UniApp 内置了一些…

交流负载箱的安全事项和注意事项有哪些?

交流负载箱用于模拟实际负载的电气设备,广泛应用于电力系统、通信系统、自动化控制系统等领域。在使用过程中,为确保人身和设备安全,需要注意以下安全事项和注意事项: 选择合适的交流负载箱:根据实际需求选择合适的交…

Python生成对抗神经网络GAN预测股票及LSTMs、ARIMA对比分析ETF金融时间序列可视化

全文链接:https://tecdat.cn/?p38528 本文聚焦于利用生成对抗网络(GANs)进行金融时间序列的概率预测。介绍了一种新颖的基于经济学驱动的生成器损失函数,使 GANs 更适用于分类任务并置于监督学习环境中,能给出价格回…

CodeFuse「编码挑战季」:冲刺最后1个月!MelGeek磁轴键盘、Beats耳机等你来拿~

本次活动自 1024 程序员节开始,12 月底结束,还有一个月的挑战时间,速来参与,赢取超值奖品!!! 活动介绍 本次 CodeFuse「编码挑战季」活动,需实际完成muAgent、MFTCoder、ModelCache…

Nginx性能优化全方案:打造一个高效服务器

Nginx性能优化全方案:打造一个高效服务器 调整工作进程数和线程数调整工作进程数调整线程数 启用Gzip压缩安装Gzip模块配置Gzip压缩 配置缓存策略配置浏览器缓存时间配置代理服务器缓存时间 优化文件访问方式使用sendfile()函数发送文件数据启用sendfile_max_chunk和…

从 CephFS 到 JuiceFS:同程旅游亿级文件存储平台构建之路

随着公司业务的快速发展,同程旅行的非结构化的数据突破 10 亿,在 2022 年,同程首先完成了对象存储服务的建设。当时,分布式文件系统方面,同程使用的是 CephFS,随着数据量的持续增长,CephFS 的高…