每天40分玩转Django:Django模型

server/2024/12/17 11:48:27/

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/server/150883.html

相关文章

scala的泛型特质的应用场景

//泛型特质的应用场景 //作比较找出最大值 //定义一个函数,用来求List元素中的最大值参考代码:object Test4 {def getMax[T](list:List[T])(implicit ev:T > Ordered[T]): T {list.reduce((a:T,b:T)> if(a>b) a else b)}def main(args: Array…

因特网的发展三个阶段

因特网的发展大致分为哪几个阶段,这几个阶段的主要特点 第一个阶段——单个网络到互联网 1969年美国创建第一个分组交换的单个网络ARPANET(单个的分组交换网)所有要连接在ARPANET上的主机都直接与就近的节点交换机相连; 20世纪…

React系列(一)——React的入门和组件化思想

前言 React是现在前端使用频率最高的三大框架之一,React率先提出虚拟DOM的思想和实现,使其保持有良好的性能。同时,掌握React语法不仅可以写Web应用的页面,还可以写IOS和安卓的页面,可以说是实用性很强的框架了。本篇文…

《操作系统 - 清华大学》7 -2:全局页面置换算法:两个全局置换算法

文章目录 1. 工作集页面置换算法1.1 工作集置换算法示例 2. 缺页率页面置换算法2.1 缺页率2.2 缺页率页面置换算法2.3 缺页率置换算法示例 1. 工作集页面置换算法 它的思想很简单,前面介绍了工作集的概念,有一个工作集的窗口,窗口由 t Δ &a…

FlowNex 中的两相建模基础知识

通过 FlowNex 中的两相建模解开高效流体动力学的秘密,彻底改变制造业。 挑战 两相流是指两个不同相(通常是液体和气体)同时流动,它们具有不同的特性和行为。在制造业中,了解两相流对于优化热交换器、化学反应器和流体…

git常用指令

1.克隆远程仓库&#xff08;第一次获取项目时使用&#xff09;&#xff1a; git clone <repository_url> 2.从远程仓库master分支拉取最新的变更&#xff08;如果你已经克隆了仓库&#xff0c;只需要更新本地副本&#xff09;&#xff1a; git pull origin master 3.…

Scala的隐式对象

Scala中&#xff0c;隐式对象&#xff08;implicit object&#xff09;是一种特殊的对象&#xff0c;它可以使得其成员&#xff08;如方法和值&#xff09;在特定的上下文中自动可用&#xff0c;而无需显式地传递它们。隐式对象通常与隐式参数和隐式转换一起使用&#xff0c;以…

链接定位技术解析:如何实现精准 GPS 定位与 IP 地址获取

1. 引言 在数字化时代&#xff0c;定位技术 已经成为现代社会的核心基础设施。从导航与物流到社交分享与紧急救援&#xff0c;定位技术让我们的生活更加智能与便捷。然而&#xff0c;很多开发者在实际应用中发现&#xff1a; “通过链接实现定位只能获取IP 地址&#xff0c;但…