您的位置:首页 > 编程语言 > Python开发

Python工程师详细讲解Django之model

2017-12-27 20:57 627 查看
一大波model操作

model的功能:创建数据库表、操作数据库表、数据验证(弱)

关于自定义表名

下面是一个创建表的的类:

1

2

3

class
User(models.Model):


user
=
models.CharField(max_length
=
32
)


pwd
=
models.CharField(max_length
=
64
)


这样默认生成的表名为app名称+下划线+类名这里即:app01_user

如果想要更改默认的表名,可以通过db_table参数实现,并且必须在 class Meta类下写,代码更改为更改为:

1

2

3

4

5

class
User(models.Model):


user
=
models.CharField(max_length
=
32
)


pwd
=
models.CharField(max_length
=
64
)


class
Meta:


db_table
=
"user"


关于索引

按照之前的方式我们会这样创建表:

1

2

3

4

5

class
User(models.Model):


user
=
models.CharField(max_length
=
32
,db_index
=
True
)


pwd
=
models.CharField(max_length
=
64
,db_index
=
True
)


class
Meta:


db_table
=
"user"


这样就会在本地生成两个文件来保存索引

联合索引

这里可以通过创建联合索引index_together从而生成一个文件,代码如下:

1

2

3

4

5

6

7

8

class
User(models.Model):


user
=
models.CharField(max_length
=
32
)


pwd
=
models.CharField(max_length
=
64
)


class
Meta:


db_table
=
"user"


index_together
=
[


(
"user"
,
"pwd"
)


]


联合索引的特点:

最左前缀

上面代码中生成索引是("user","pwd")是name在前面,所以这样会导致:

select * fromuserwhere user= "zhaofan" 可以命中索引

select * fromuserwhere user= "zhaofan" and pwd= "123" 可以命中索引

select * fromuserwhere pwd= "123" 这种查询时则无法命中索引

所以联合索引的就会导致只有加上最左边的索引值时索引才能起作用,这里的name在最左边,所以查询时条件中有name时索引才能命中

联合唯一索引

unique_together = (("name", "pwd"),)

表示("name","pwd")的组合是唯一的

多表操作及参数

一对多

下面是创建一对多的类:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

class
UserType(models.Model):


name
=
models.CharField(max_length
=
32
)


class
User(models.Model):


user
=
models.CharField(max_length
=
32
,db_index
=
True
)


pwd
=
models.CharField(max_length
=
64
,db_index
=
True
)


class
Meta:


db_table
=
"user"


index_together
=
[


(
"name"
,
"pwd"
)


]


ut
=
models.ForeignKey(


to
=
"UserType"
,


to_field
=
"id"
,


)


如果数据库中已经有用户属于每个usertype,这样当我们通过下面方式删除usertype表中的数据时:

UserType.objects.filter(id=1).delete()

Django1.10之后不会报错,并且默认还会把属于usertype的用户user也删除

这里ForeignKey有几个参数:

to 要进行关联的表名

to_field 要关联的表中的字段名称

on_delete 当删除关联表中的数据时,当前表与其关联的行的行为

- models.CASCADE,删除关联数据,与之关联也删除

- models.DO_NOTHING,删除关联数据,引发错误IntegrityError(这个错误是数据库提示的错误)

- models.PROTECT,删除关联数据,引发错误ProtectedError(这个错误是Django提示的错误)

- models.SET_NULL,删除关联数据,与之关联的值设置为null(前提该字段需要设置为可空)

- models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提该字段需要设置默认值)

- models.SET,删除关联数据

a. 与之关联的值设置为指定值,设置:models.SET(值)

b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象即函数)

关于正向查找

model中的代码如下:

1

2

3

4

5

6

7

8

9

10

class
UserType(models.Model):


name
=
models.CharField(max_length
=
32
)


class
User(models.Model):


user
=
models.CharField(max_length
=
32
)


pwd
=
models.CharField(max_length
=
64
)


ut
=
models.ForeignKey(


to
=
"UserType"
,


to_field
=
"id"
,


)


在views函数中写如下代码:

1

2

3

def
index(request):


v1
=
models.User.objects.
all
().values(
"user"
,
"ut__name"
)


return
HttpResponse(v1)


即正常的通过models.User.objects.all().values("user","ut__name"),就可以实现跨表

当然也可以通过下面方式实现跨表查询:

v2 = models.User.objects.all()

for i in v2:

print(i.ut.id,i.ut.name)

关于反向查找

通过v3 = models.UserType.objects.all().values("name","user__user")同样能够实现反向跨表查询

同样也可以通过for循环实现反向查询的跨表

v4 = models.UserType.objects.all()

for i in v4:

print(i.name,i.user_set.name)

这里的反向操作都需要用另外一张的表名_set__列名或者表名__列名

这里可以实现自定制related_name

在models里设置表结构的时候:

1

2

3

4

5

6

7

8

class
User(models.Model):


user
=
models.CharField(max_length
=
32
)


pwd
=
models.CharField(max_length
=
64
)


ut
=
models.ForeignKey(


to
=
"UserType"
,


to_field
=
"id"
,


related_name
=
"cc"


)


这样再次获取的时候就可以通过related_name值获取:

v3 = models.UserType.objects.all().values("name","cc__user")这种方式和

3 = models.UserType.objects.all().values("name","user__user")结果是一样的

这里还有一个参数叫related_query_name

反向操作时,使用的连接前缀,用于替换“表名__set”中的“表名”,如果related_query_name=“aa”,则反向查找是可以通过aa_set查找

在Django admin中用到的参数

limit_choices_to

通过limit_choices_to,在Admin或ModelForm中显示关联数据时,提供的条件

如下图所示usertype中有四个类型:



如果不做任何设置,添加用户时应该也能看到四个类型如下图:



在代码中通过limit_choices_to={"id__gt":2},可以修改显示的个数

1

2

3

4

5

6

7

8

9

class
User(models.Model):


user
=
models.CharField(max_length
=
32
)


pwd
=
models.CharField(max_length
=
64
)


ut
=
models.ForeignKey(


to
=
"UserType"
,


to_field
=
"id"
,


related_name
=
"cc"
,


limit_choices_to
=
{
"id__gt"
:
2
},


)




db_constraint=True # 是否在数据库中创建外键约束

parent_link=False # 在Admin中是否显示关联数据

一对一OnetoOneField

OneToOneField(ForeignKey)

OneToOneField继承ForeignKey

所以同样有

to, # 要进行关联的表名

to_field=None # 要关联的表中的字段名称

on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为

当两个类之间有继承关系时,默认会创建一个一对一的字段

多对多ManyToManyField

常见的参数:

to, # 要进行关联的表名

related_name# 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()

related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')

limit_choices_to # 在Admin或ModelForm中显示关联数据时,提供的条件

特殊参数:

symmetrical=None,

仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段

做如下操作时,不同的symmetrical会有不同的可选字段

symmetrical=True:

class BB(models.Model):

code = models.CharField(max_length=12)

m1 = models.ManyToManyField('self',symmetrical=True)

这个时候可选字段有:code,id,m1

symmetrical=Falses时:

class BB(models.Model):

code = models.CharField(max_length=12)

m1 = models.ManyToManyField('self',symmetrical=False)

这个时候可选字段有:code,id,m1,bb

其实这个时候发反向查询没有多大意义,毕竟这里是多丢多的自关联

创建对多的三种方式

第一种:让django自动创建第三张表,即通过models.ManyToManyField

1

2

3

4

5

class
Blog(models.Model):


site
=
models.CharField(max_length
=
32
)


m
=
models.ManyToManyField(
"Tag"
)


class
Tag(models.Model):


name
=
models.CharField(max_length
=
32
)


这样就可以通过

models.Blog.m.add

models.Blog.m.update

models.Blog.m.clear

models.Blog.m.all

models.Blog.m.create

……

第二种方式:手动创建第三张表

1

2

3

4

5

6

7

8

9

class
Blog(models.Model):


site
=
models.CharField(max_length
=
32
)


class
Tag(models.Model):


name
=
models.CharField(max_length
=
32
)


class
B2T(models.Model):


b
=
models.ForeignKey(
"Blog"
)


t1
=
models.ForeignKey(
"Tag"
)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: