Django 05
Django数据模型层使用了ORM(对象关系映射).我们以操作python的对象的方式去访问数据库。
定义数据表
在django中, 我们不需要直接在数据库中定义数据表(CREATE TABLE), 而是在models.py
文件中定义一个继承Model的类, 接下来在这个类中定义一系列Field类型的类属性来描述数据的每个字段.
from django.db import models
class Blog(models.Model):
title = models.CharField(max_length=150)
body = models.TextField()
timestamp = models.DateTimeField()
定义好数据表后, 我们使用django提供的工具, 来由这些Model的子类来创建数据库中的表.
1. 首先要确保, 这个应用在settings中的INSTALLED_APPS中.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# my app
'blog',
]
- 使用makemigrations命令, 来告诉django我们的model的做了改动.
$ python manage.py makemigrations blog
Migrations for 'blog':
blog/migrations/0001_initial.py:
- Create model Blog
此时, 数据库还未发生真正的改动, 我们可以使用sqlmigrate命令, 看看我们修改model, 对应的修改数据库的SQL语句.(此步骤可选)
$ python manage.py sqlmigrate blog 0001
BEGIN;
--
-- Create model Blog
--
CREATE TABLE "blog_blog" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"title" varchar(150) NOT NULL,
"body" text NOT NULL,
"timestamp" datetime NOT NULL);
COMMIT;
- 这时我们使用migrate, 改变数据库.
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying blog.0001_initial... OK
Applying sessions.0001_initial... OK
之后每次新建或更新model, 我们还要执行makemigrations和migrate这俩条命令更新数据库.
常用Field
- CharField: 字符串(varchar)
- EmailField: 邮件地址(varchar)
- IPAddressField: IP地址(char)
CharField(max_length=64)
CharField(max_length=32, blank=True)
- TextField: 文本(text)
- IntegerField: 整数(integer)
IntegerField()
IntegerField(default=0)
- FloatField: 浮点数(real)
- BooleanField: 布尔(bool)
- TimeField: 时间(time)
- DateField: 日期(date)
- DateTimeField: 日期时间(datetime)
- FileField: 文件
- ImageField: 图片
多对一关系
使用ForeignKey来描述多对一关系, 例如一个作者写了多本书, 也就是多本书对应一个作者.
class Book(models.Model):
title = models.CharField(max_length=256)
author = models.ForeignKey('Author')
price = models.FloatField()
class Author(models.Model):
name = models.CharField(max_length=256)
age = models.IntegerField()
根据上面的model会创建出如下的表.
--
-- Create model Author
--
CREATE TABLE "blog_author" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" varchar(256) NOT NULL,
"age" integer NOT NULL
);
--
-- Create model Book
--
CREATE TABLE "blog_book" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"title" varchar(256) NOT NULL, "price" real NOT NULL,
"author_id" integer NOT NULL REFERENCES "blog_author" ("id")
);
ManyToManyField: 多对多关系
使用ManyToManyField来描述多对一关系, 例如一本书有多个读者, 每个读者订阅了多本书.
class Reader(models.Model):
name = models.CharField(max_length=256)
books = models.ManyToManyField('Book')
我们看到多对多关系, 通过辅助表blog_reader_books来描述.
--
-- Create model Reader
--
CREATE TABLE "blog_reader" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" varchar(256) NOT NULL
);
CREATE TABLE "blog_reader_books" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"reader_id" integer NOT NULL REFERENCES "blog_reader" ("id"),
"book_id" integer NOT NULL REFERENCES "blog_book" ("id")
);
数据访问
- 创建 create
from blog.models import Blog
blog = Blog(title='How to learn Django', body='xxx')
blog.save()
- 更改 update
from django.utils import timezone
blog.title = '怎样学习django'
blog.timestamp = timezone.now()
blog.hits = 30
blog.save()
- 删除 delete
blog.delete()
- 查询 query
# 查询全部
blog.objects.all()
# 查找某范围
blog.objects.all()[100:200]
blog.objects.all()[:100]
# 查询第一条
book = Book.objects.first()
# 查询最后一条
book = Book.objects.last()
# get()
book = Book.objects.get(id=1)
# filter()
# 查找发布日期为2015-5-23的书.
books = Book.objects.filter(pubDate='2015-5-23')
# 查找点击量超过1000的blog
books = Blog.objects.filter(hits__gt=1000)
# 查找年龄的40-50的作者.
authors = Author.objects.filter(age__range=(40, 50))
# 查找标题中包含'how to'字样的blog
blogs = Blog.objects.filter(title__contains='how to')
# 查找作者名为'刘硕'的书
books = Book.objects.filter(author__name='刘硕')
# order_by() 以某字段排序
authors = Authors.objects.order_by('-age')
blogs = Blog.objects.filter(hits__gt='2015-5-23').order_by('hits')
# count() 获取数量
books = Blog.objects.filter(hits__gt=1000).count()
# only() defer() 指定取/不取字段
Blog.objects.only('id', 'title')
Blog.objects.defer('body')