django系列(三)之模型
django中说的模型(model)就是数据库中的table(表)
django模型文档地址:https://docs.djangoproject.com/zh-hans/5.2/intro/tutorial02/
一、创建模型
模型是在你创建的app目录下的models.py中创建django中模型是以类的形式存在,一个类就是一张表
from django.db import models
# Create your models here.
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField(null=True, db_comment='日期', verbose_name='日期')
class Meta: # 定义表的元数据,例如排序,表名等等
# 定义表的名称,否则默认是app名_类名
db_table = 'question'
def __str__(self):
return '问题表'
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
class Meta:
db_table = 'choice'
def __str__(self):
return self.question
# 解释
1、每个模型都是 django.db.models.Model 类的子类。每个模型有许多类变量,它们都表示模型里的一个数据库字段。
2、每个字段的数据类型都是 Field 类的实例 ,比如,字符字段被表示为 CharField ,日期时间字段被表示为 DateTimeField 。这将告诉 Django 每个字段要处理的数据类型。
3、__str__(self) 这个是返回 self.question_text 这个值,方便辨认
字段选项:
4、django默认是not null,如果想要字段可以为null要显示指定
5、db_comment是列的注释,注意与help_text的区别,help_text主要用于admin 后台表单提示、自动生成文档等。db_comment是完全专注于数据库
6、primary_key,指定主键,如果不设置,默认django会设置一个名称为id的字段为主键`id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY
7、unique=True,设置唯一键
8、verbose_name='日期',也是后台表单里会显示,表单里看到的字段名就直接是日期,而不是pub_date,更适合人类阅读。与help_text的区别就是verbose_name就是字段名,help_text是字段的 “辅助说明”(更长的描述,通常显示在字段下方)
字段类型:
官网地址:https://docs.djangoproject.com/zh-hans/4.2/ref/models/fields/#model-field-types
如果django中没有所需要的字段类型,也可以自定义字段类型
官网地址:https://docs.djangoproject.com/zh-hans/4.2/howto/custom-model-fields/
二、激活模型
1、python manage.py makemigrations polls
# 该命令会检测你对模型文件的修改,并且把修改的部分写进迁移文件中。结果会输出以下内容
Migrations for 'polls':
polls\migrations\0001_initial.py
- Create model Question
- Create model Choice
这时在你的app目录下的migrations目录下会生成一个迁移文件
0001_initial.py
2、python manage.py sqlmigrate polls 0001
该命令会生成0001_initial.py文件中对应的sql语句,
--
-- Create model Question
--
CREATE TABLE `polls_question` (`id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, `question_text` varchar(200) NOT NULL, `date published` datetim
e(6) NOT NULL);
--
-- Create model Choice
--
CREATE TABLE `polls_choice` (`id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, `choice_text` varchar(200) NOT NULL, `votes` integer NOT NULL, `q
uestion_id` bigint NOT NULL);
ALTER TABLE `polls_choice` ADD CONSTRAINT `polls_choice_question_id_c5b4b260_fk_polls_question_id` FOREIGN KEY (`question_id`) REFERENCES `poll
s_question` (`id`);
# 注意:
数据库的表名是由应用名(polls)和模型名的小写形式( question 和 choice)连接而来。(如果需要,你可以自定义表名)
这个 sqlmigrate 命令并没有真正在你的数据库中的执行迁移 - 相反,它只是把命令输出到屏幕上,让你看看 Django 认为需要执行哪些 SQL 语句
3、python manage.py migrate
# 该命令真正会在数据库中执行对应的sql语句,
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Rendering model states... DONE
Applying polls.0001_initial... OK
4、python .\manage.py migrate polls
Operations to perform:
Apply all migrations: polls
Running migrations:
No migrations to apply.
# 如果模型没有更改,可以看到,不会进行重复执行
三、API使用执行sql语句
执行 python manage.py shell 命令进入django命令行,并自动加载当前 Django 项目的环境。
这意味着你可以在这个交互式环境中:
* 直接导入和操作 Django 项目中的模型(Model)
* 调用 Django 的各种功能和 API
* 执行数据库操作(查询、创建、更新、删除数据等)
* 测试代码片段或调试问题
# 1、写入数据,有两种方式
一是创建模型实例 + 调用 save() 方法
b = models.Blog(name="新闻博客", tagline="重大新闻")
b.save()
二是create方法或者bulk_create方法
Blog.objects.create(name="球类博客", tagline="足球运动")
create() 内部会自动调用 save(),无需手动执行
批量插入
books = [
Book(title=" book1", author="A", price=30),
Book(title=" book2", author="B", price=40),
]
Book.objects.bulk_create(books) # 批量插入
bulk_create内部是没有调用save方法的,它和update一样,直接生成sql语句执行
# 2、更新数据
Book.objects.filter(author="张三").update(price=55.00)
update直接在数据库层面执行 UPDATE 语句,不会触发模型的 save() 方法
# 3、删除
Book.objects.filter(price__lt=30).delete()
delete() 会生成 DELETE SQL 语句,直接在数据库中删除记录,不会触发模型的 save() 方法
# 4、查询
filter(**kwargs)
返回一个新的 QuerySet,包含的对象满足给定查询参数。
exclude(**kwargs)
返回一个新的 QuerySet,包含的对象 不 满足给定查询参数。
get() 只返回一条记录,如果记录不存在或者有多条会报错,适合主键或者唯一键查询
all()查询所有数据
# 5、限制返回条目数
Entry.objects.all()[:5] 相当于limit 5
Entry.objects.all()[5:10] 相当于 offset 5 limit 5
queryset官网地址:
https://docs.djangoproject.com/zh-hans/4.2/ref/models/querysets/#queryset-api
# 6、where条件
官网地址:https://docs.djangoproject.com/zh-hans/4.2/ref/models/querysets/#field-lookups
它们以关键字参数的形式传递给 QuerySet 方法 filter(), exclude() 和 get()。
条件参数采用 field__lookuptype=value (使用双下划线)形式。例如:
Entry.objects.filter(pub_date__lte="2006-01-01")
它等价于SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';
Entry.objects.get(headline__exact="Cat bites dog")
注意:exact是可以被省略的,因为这是最常用的形式,可以直接写成
Entry.objects.get(headline="Cat bites dog")这种形式
它等价于SELECT ... WHERE headline = 'Cat bites dog';
# 模糊查询
Entry.objects.get(headline__contains="Lennon")
它等价于SELECT ... WHERE headline LIKE '%Lennon%';
# 7、join查询
# 8、F对象和Q对象
F 对象用于引用模型字段的值,直接在数据库层面操作字段,避免 Python 层面的二次处理,常用于:
字段间的比较
基于自身值的更新操作
避免竞态条件
# 1. 字段间比较:查询库存大于销量的商品
Product.objects.filter(stock__gt=F('sales'))
# 2. 基于自身值更新:所有商品价格上涨10%
Product.objects.update(price=F('price') * 1.1)
# 3. 复杂表达式:库存减少5个(原子操作,避免并发问题)
product = Product.objects.get(id=1)
product.stock = F('stock') - 5
product.save()
Q 对象用于构建复杂的查询条件,支持逻辑运算符(& 与、| 或、~ 非),解决 filter() 中参数默认 “与” 逻辑的限制。
# 1. 逻辑或(|):查询标题含"Python"或作者是"张三"的文章
Article.objects.filter(
Q(title__contains="Python") | Q(author="张三")
)
# 2. 逻辑与(&):查询阅读量>1000且发布时间在2023年后的文章
Article.objects.filter(
Q(read_count__gt=1000) & Q(publish_date__year__gt=2023)
)
# 3. 逻辑非(~):查询不包含"广告"标签的文章
Article.objects.filter(~Q(tags__contains="广告"))
# 4. 嵌套使用:更复杂的条件组合
Article.objects.filter(
Q(author="张三") & (Q(read_count__gt=500) | Q(comment_count__gt=100))
)
# 9、只返回指定字段

浙公网安备 33010602011771号