欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 社会 > 每天40分玩转Django:Django模型

每天40分玩转Django:Django模型

2024/12/22 2:12:25 来源:https://blog.csdn.net/weixin_40780178/article/details/144420114  浏览:    关键词:每天40分玩转Django:Django模型

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大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com