Django框架学习第2天:Django模型
一、课程概述
学习项目 具体内容 预计用时 模型定义 模型类编写、字段类型、关系类型 90分钟 ORM操作 增删改查、高级查询、聚合函数 90分钟 数据库迁移 迁移命令、迁移文件、数据导入导出 60分钟
二、模型定义
2.1 基本模型结构
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操作
post = Post( title= '第一篇博客' , body= '内容...' , author= user)
post. save( )
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 )
post = Post. objects. get( id = 1 )
post. title = '新标题'
post. save( )
Post. objects. filter ( id = 1 ) . update( title= '新标题' )
post = Post. objects. get( id = 1 )
post. delete( )
3.2 高级查询
from django. db. models import Q, Count, Avg
from django. utils import timezone
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' ) )
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 查询优化
posts = Post. objects. select_related( 'author' , 'category' ) . all ( )
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
python manage.py sqlmigrate blog 0001
python manage.py check
4.2 数据迁移示例
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) , ]
五、实战练习:博客评论系统
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 评论视图
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 = postnew_comment. save( ) else : comment_form = CommentForm( ) return render( request, 'blog/post/detail.html' , { 'post' : post, 'comments' : comments, 'comment_form' : comment_form} )
六、进阶技巧
6.1 自定义模型管理器
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 模型信号
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( )
七、常见问题和解决方案
数据库迁移冲突:
python manage.py migrate blog zero
python manage.py makemigrations blog
python manage.py migrate blog
关联字段删除:
author = models. ForeignKey( User, on_delete= models. SET_NULL, null= True , blank= True
)
大数据查询优化:
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
八、作业和练习
创建一个完整的博客数据模型,包含用户、分类、标签、文章和评论 实现文章的增删改查功能 添加评论功能 实现文章分类和标签功能 优化查询性能
九、扩展阅读
Django Model字段类型详解 数据库事务处理 Django ORM高级查询技巧 数据库性能优化方案
怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!