### 连接指定数据库
参数的解析:
1.ENGINE: 引擎 django.db.backends.mysql
2.NAME :连接到的数据库名称 web.db
3.USER: 用户名称 ,通常为root
4.PASSWORD: 密码
5.HOST : 连接的主机,本机localhost/127.0.0.1/可以不写
实例如下:
model.py 的语法
字段
1) CharField() 字符串, 属性值max_length必须要写,表明字符串长度,相当于原生MySQL中的char()
2) BooleanField() 布尔值,True或者False
3) DataField() 时间,只有日期,不带时间点,例如:2018-1-1
4) DateTimeField() 时间,带时间点,例如:2018-1-1 12:00:00
5) DecimalField() 带小数点的定点数,可以用于与金融或者数字有关的字段
6) EmailField() Email类型
7) URLField() URL类型,在数据库中会转换为固定长度(200)字符串
8) FileField() 文件类型
9) IntergerField() 整型数
10) FloatField() 浮点数
11) ImageField() 图片,一般在实际应用中存放图片的地址
12) TextField() 文本
字段选项
1) null 是否允许为空,赋值True或者False,例如:name = models.Char(max_length= 10 , null = False)
2) blank 是否为空格
3) choices
4)db_column 属性名,例如:db_column = ' music_name '
5)db_index 索引,为该字段设置索引
6) default 默认值,例如:password = models.Char(max_length= 10 , defalut = '123456')
7) primary_key 主键,值为True/False,默认为False(不设置为主键)
ForeignKey、ManyToManyField 、OneToOneField
poll = models.ForeignKey(
Poll,
on_delete=models.CASCADE,
verbose_name="the related poll",
)
sites = models.ManyToManyField(Site, verbose_name="list of sites")
place = models.OneToOneField(
Place,
on_delete=models.CASCADE,
verbose_name="related place",
)
关联关系
应用场景
Django 提供了定义三种最常见的数据库关联关系的方法:多对一,多对多,一对一。
一对一:一般用于某张表的补充,比如用户基本信息是一张表,但并非每一个用户都需要有登录的权限,不需要记录用户名和密码,此时,合理的做法就是新建一张记录登录信息的表,与用户信息进行一对一的关联,可以方便的从子表查询母表信息或反向查询
多对一(外键):有很多的应用场景,比如每个员工归属于一个部门,那么就可以让员工表的部门字段与部门表进行一对多关联,可以查询到一个员工归属于哪个部门,也可反向查出某一部门有哪些员工
多对多:如很多公司,一台服务器可能会有多种用途,归属于多个产品线当中,那么服务器与产品线之间就可以做成对多对,多对多在A表添加manytomany字段或者从B表添加,效果一致
Many-to-one relationships
定义一个多对一的关联关系,使用 django.db.models.ForeignKey 类。就和其他 Field字段类型一样,只需要在你模型中添加一个值为该类的属性。
例如,如果一个 Car 模型 有一个制造者 Manufacturer --就是说一个 Manufacturer
制造许多辆车,但是每辆车都属于某个特定的制造者
可以创建一个 递归关系(一个模型与它本身有多对一的关系)
实例
from django.db import models
class Manufacturer(models.Model):
# ...
pass
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
Many-to-many relationships
定义一个多对多的关联关系,使用 django.db.models.ManyToManyField 类。就和其他 Field 字段类型一样,只需要在你模型中添加一个值为该类的属性。
例如:
如果 Pizza 含有多种 Topping
(配料) -- 也就是一种
Topping 可能存在于多个 Pizza中,并且每个Pizza 含有多种 Topping可以创建递归关系(一个对象与他本身有着多对多的关系)和与尚未定义的模型的关系。
对于多对多光联关系的两个模型,可以在任何一个模型中添加 ManyToManyField字段,但只能选择一个模型设置该字段,即不能同时在两模型中添加该字段。
from django.db import models
class Topping(models.Model):
pass
class Pizza(models.Model):
toppings = models.ManyToManyField(Topping)
在多对多(many-to-many)关系中添加添加额外的属性字段
如果你只是想要一个类似于记录披萨和配料之间混合和搭配的简单多对多关系,标准的 ManyToManyField就足够你用了。然而,有的时候你可能会需要在两个模型的关系中记录更多的数据。
举例
考虑一个需要跟踪音乐人属于哪个音乐组的应用程序。在人和他们所在的组之间有一个多对多关系,你可以使用 ManyToManyField来代表这个关系。然而,你想要记录更多的信息在这样的所属关系当中,比如你想要记录某人是何时加入一个组的。
可以在中间模型当中添加而外的字段。在实例化 ManyToManyField 的时候使用 through参数指定多对多关系使用哪个中间模型。代码如下:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __str__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
设置中间模型的时候,你需要显式地为多对多关系中涉及的模型指定外键。这种显式声明定义了这两个模型之间的关系。
实例化中间模型来创建关系:
>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
>>> beatles = Group.objects.create(name="The Beatles")
>>> m1 = Membership(person=ringo, group=beatles,
... date_joined=date(1962, 8, 16),
... invite_reason="Needed a new drummer.")
>>> m1.save()
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>]>
>>> ringo.group_set.all()
<QuerySet [<Group: The Beatles>]>
>>> m2 = Membership.objects.create(person=paul, group=beatles,
... date_joined=date(1960, 8, 1),
... invite_reason="Wanted to form a band.")
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>]>
- 和一般的多对多字段不同,你 不能 使用 add(), create(), 或 set() 来创建关系.
- remove() 在被调用的时候没有足够的信息来确定哪一个中间模型需要被删除。
- clear() 方法可以被用来移除一个实例的所有多对多关系:
- 通过创建中间模型创立了多对多关系,你可以执行查询。就和一般的多对多关系一样,你可以使用多对多关联模型的属性来执行查询
- 使用用中间模型的时候,你也可以查询他的属性
One-to-one relationships
使用 OneToOneField 来定义一对一关系。就像使用其他类型的 Field一样:在模型属性中包含它。当一个对象以某种方式“扩展”另一个对象时,这对该对象的主键非常有用。
例如,当你要建立一个有关“位置”信息的数据库时,你可能会包含通常的地址,电话等字段。接着,如果你想接着建立一个关于关于餐厅的数据库,除了将位置数据库当中的字段复制到Restaurant 模型,你也可以将一个指向 Place OneToOneField 放到 Restaurant
当中(因为餐厅“是一个”地点);事实上,在处理这样的情况时最好使用 inheritance ,它隐含的包括了一个一对一关系。
可选的 parent_link 参数。
OneToOneField 类通常自动的成为模型的主键,这条规则现在不再使用了(然而你可以手动指定 primary_key参数)。因此,现在可以在单个模型当中指定多 OneToOneField 字段。
跨文件模型
- 关联另一个应用中的模型是当然可以的。为了实现这一点,在定义模型的文件开头导入需要被关联的模型。
from django.db import models
from geography.models import ZipCode
class Restaurant(models.Model):
# ...
zip_code = models.ForeignKey(
ZipCode,
on_delete=models.SET_NULL,
blank=True,
null=True,
)
字段命名限制
- 字段的名称不能是Python保留字
- 字段名称不能包含连续的多个下划线
Meta 选项(可选)
from django.db import models
class Ox(models.Model):
horn_length = models.IntegerField()
class Meta:
ordering = ["horn_length"]
verbose_name_plural = "oxen"
模型属性(objects)
模型当中最重要的属性是 Manager。它是Django模型和数据库查询操作之间的接口,并且它被用作从数据库当中 retrieve the instances,如果没有指定自定义的 Manager 默认名称是objects。Manager只能通过模型类来访问,不能通过模型实例来访问。
模型方法
模型上定义自定义方法,以向您的对象添加自定义“行级”功能。尽管Manager方法旨在用于“表范围内的”事情,但是模型方法应作用于特定的模型实例。
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()
def baby_boomer_status(self):
import datetime
if self.birth_date < datetime.date(1945, 8, 1):
return "Pre-boomer"
elif self.birth_date < datetime.date(1965, 1, 1):
return "Baby boomer"
else:
return "Post-boomer"
@property
def full_name(self):
return '%s %s' % (self.first_name, self.last_name)
- str():返回任何对象的字符串表示形式。
- get_absolute_url():计算对象的URL
重写预定义的模型方
- 覆盖内置方法
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def save(self, *args, **kwargs):
do_something()
super().save(*args, **kwargs)
do_something_else()
- 防止保存
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def save(self, *args, **kwargs):
if self.name == "Yoko Ono's blog":
return
else:
super().save(*args, **kwargs)
- 传递可以传递给模型方法的参数也很重要-这就是位的作用。
- Django会不时地扩展内置模型方法的功能,并添加新的参数。
- 如果在方法定义中使用,则可以确保代码添加后将自动支持这些参数。
- args, **kwargsargs, **kwargs
模型继承(三种方式)
基类应该继承自 django.db.models.Model .
希望父模型本身就是具有自己的数据库表(具有自己的数据库表)的模型,还是希望父模型只是仅通过子模型可见的公共信息的持有者。
- 抽象继承
- 多表继承
- proxy model(代理model)
抽象基类
当您要将一些公共信息放入许多其他模型时,抽象基类很有用。你写你的基类,并把abstract=True在元类。这样,该模型将不会用于创建任何数据库表。相反,当将其用作其他模型的基类时,会将其字段添加到子类的字段中。
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Meta:
abstract = True
class Student(CommonInfo):
home_group = models.CharField(max_length=5)
该Student模型将有三个领域:name,age和home_group。该CommonInfo模型不能用作普通的Django模型,因为它是抽象的基类。它不生成数据库表或没有管理器,并且不能实例化或直接保存。
Meta inheritance
创建抽象基类后,Django 会将您在基类中声明的任何Meta内部类用作属性。如果子类没有声明自己的Meta类,它将继承父类的Meta。如果孩子想扩展父母的Meta类,则可以对其进行子类化。
from django.db import models
class CommonInfo(models.Model):
class Meta:
abstract = True
ordering = ['name']
class Student(CommonInfo):
class Meta(CommonInfo.Meta):
db_table = 'student_info'
多表继承
Django支持的第二种类型的模型继承是层次结构中的每个模型本身都是一个模型时。每个模型都对应于其自己的数据库表,并且可以单独查询和创建。继承关系在子模型及其每个父模型之间引入了链接(通过自动创建的OneToOneField)
from django.db import models
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
Meta和多表继承
在多表继承的情况下,子类从其父级的Meta类继承是没有意义的。所有元选项都已经应用于父类,并且再次应用它们通常只会导致矛盾的行为
class ChildModel(ParentModel):
# ...
class Meta:
ordering = []
继承和反向关系
由于多表继承使用隐式 OneToOneField链接子级和父级,因此可以从父级向下移动到子级,
class Supplier(Place):
customers = models.ManyToManyField(Place)
指定父链接字
Django将自动创建一个 OneToOneField将您的子类链接回任何非抽象父模型的链接。如果要控制链接回父类的属性的名称,则可以创建自己的属性OneToOneField并进行设置, parent_link=True 以指示您的字段是指向父类的链接。
代理模式¶
代理模型继承的目的:为原始模型创建代理。您可以创建,删除和更新代理模型的实例,所有数据都将像使用原始(非代理)模型一样保存。区别在于您可以更改诸如默认模型排序或代理中的默认管理器之类的东西,而无需更改原始模型。
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class MyPerson(Person):
class Meta:
proxy = True
def do_something(self):
pass
多重继承
您不需要从多个父母那里继承。有用的主要用例是“混入”类:向继承混入的每个类添加特定的额外字段或方法。尝试使继承层次结构尽可能简单明了,这样您就不必费力找出特定信息的来源。
class Article(models.Model):
article_id = models.AutoField(primary_key=True)
class Book(models.Model):
book_id = models.AutoField(primary_key=True)
class BookReview(Book, Article):
pass
或使用共同的祖先来持有AutoField。这要求使用OneToOneField从每个父模型到公共祖先的显式方法,以避免子对象自动生成和继承的字段之间发生冲突
class Piece(models.Model):
pass
class Article(Piece):
article_piece = models.OneToOneField(Piece, on_delete=models.CASCADE, parent_link=True)
class Book(Piece):
book_piece = models.OneToOneField(Piece, on_delete=models.CASCADE, parent_link=True)
class BookReview(Book, Article):
pass
在包中组织模
该命令创建一个包含文件的应用程序结构。如果您有许多模型,将它们组织在单独的文件中可能会很有用。创建一个models包。删除models.py并创建一个 myapp/models/目录,其中包含一个__init__.py文件以及用于存储模型的文件。您必须将模型导入__init__.py文件中。
MYAPP /模型/ __ init__.py中有所
from .organic import Person
from .synthetic import Robot