Django 模型间的关系

Django模型之间的关系

Django模型的对应关系,一对一,一对多,以及多对多的关系。

  • 一对一 OneToOneField

  • 一对多 ForeignKey

  • 多对多 ManyToManyField

关联表删除时的操作

on_delete

  • protect:当在父表(即外键的来源表)中删除对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除。

    models.OneToOneField(other_table, on_delete=models.PROTECT)

  • cascade(级联):当在父表中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为null(不过这就要求该外键允许取null)

    eg:models.OneToOneField(other_table, on_delete=models.CASCADE)

  • set_null:父表删除记录时,从表关联字段设置为空

    models.OneToOneField(other_table, on_delete=models.SET_NULL)

  • set_default:父表删除记录时,从表设置为默认值

    models.OneToOneField(other_table, on_delete=models.SET_DEFAULT)

一对一

一对一模型,顾名思义就是一个唯一对应另一个,比如你的身份证对应你的这种关系,当然也是一个表对应该表的扩展表。这里以用户表和用户信息扩展表做例子。

1)创建用户模型:

class User(models.Model):
    u_name = models.CharField(max_length=10)
    u_sex = models.BooleanField()
    u_birth = models.DateField()
    u_create_time = models.DateField(auto_now_add=True)
    u_operate_time = models.DateField(auto_now=True)
    r_id = models.ForeignKey(Role,
                             on_delete=models.CASCADE) #这里指定用户所属的角色组

    class Meta:
        db_table = 'user'
  1. 创建用户扩展模型:
class Userinfo(models.Model):
    u_tel = models.IntegerField()
    u_addr = models.CharField(max_length=50)
    u = models.OneToOneField(User, on_delete=models.CASCADE)

    class Meta:
        db_table = 'info'

注意:将两个模型一对一绑定使用的是 models.OneToOneField(User, on_delete=models.CASCADE)

这里会将自动去关联用户模型的主键.

插入数据:

用户表
用户拓展表

3)查询用户信息的方法:

def selu(request):
    # 拓展表信息查用户信息
    user = Userinfo.objects.get(u_addr='太升路10号').u.u_name

    # 用户信息查拓展信息
    users = User.objects.get(u_name='admin').userinfo
    return render(request, 'show.html', {'users': users, 'user': user})

结果如下:

一对一查询结果

注意:1.通过父表去查询字表的信息,可以通过单个父表用户对象.子模型名的形式得到一个子表对象,通过子表对象即可获取到与附表信息对应的子表的信息。
2.通过子表信息去查父表对象则通过子表用户对象的外键属性去创建父表用户数据对象,从而获得与之匹配的父表中与该子表信息相关的信息。

一对多

一对多指的是在一张表中有多条数据指向另一个表中的某一条数据的这种模式,如一个班级中有多个学生,在学生表中属于同一个班的学生的信息中就有一条指向了班级表中的同一个条目。

这里我们还是以用户表和角色组表来做演示,这里角色组合用户表示一对多的关系,所有应该在用户表中创建外键,管理角色组,在前面我们创建用户模型的时候已经创建了,解下来创建角色模型:

class Role(models.Model):
    r_name = models.CharField(max_length=10)

    class Meta:
        db_table = 'role'

插入数据:

角色组

一对多模型下根据角色组查用户和根据用户查属于的角色组:

from users.models import User
from authority.models import Role, Permission
def onetomore(request):
    # 查询admin属于哪个角色组
    jiao = User.objects.get(u_name='admin').r_id.r_name

    # 查询管理员角色组下有哪些用户
    users = Role.objects.get(r_name='管理员').user_set.all()

    return render(request, 'show_ontomore.html', {'users': users, 'jiao': jiao})

结果如下:

显示配置
一对多查询结果

注意:在一对多模型中要通过子表访问父表的元素是通过'模型名字_set'去创建父表的对象,来获取父表中的值的。

多对多模型

多对多模型指的是一个A和B两张表A表中的某些内容对应B中的多个条目,同时B表中的某些内容又对应A表中的多个条目。例如超市里的商品和购买商品的用户之间的关系,同一个用户可以买很多商品,同一个商品也可以被很多用户购买。

这里在前面的基础上我们以权限表和角色组来作为案例讲解:

1)创建权限模型:

class Permission(models.Model):
    p_name = models.CharField(max_length=10)
    p_r = models.ManyToManyField(Role)

    class Meta:
        db_table = 'permission'

注意:这里创建权限表使用的是 models.ManyToManyField() 来指定为多对多模型。使用python manage.py makemigrationspython manage.py migrate创建成功后,可以看到数据库中有三张表,分别是:'permission','role','permission_p_r'其中 'permission'
别用来存储 'permission' 和 'role'两张表各个条目的关联关系。'permission_p_r'是Django自动帮我们创建的。

创建后插入如下数据

权限表
多对多关系表

2)数据查询:

from authority.models import Role, Permission
def moretomore(request):
    # 查询管理员角色组有哪些权限?
    pers = Role.objects.get(r_name='管理员').permission_set.all()

    # 查询哪些角色组有查询用户列表信息的权限?
    roles = Permission.objects.filter(p_name='查询用户列表信息').first().p_r.all()

    return render(request, 'moretomore.html', {'pers': pers, 'roles': roles})

结果如下:

多对多显示界面配置
多对多查询结果

注意:这里在做对象转换的时候分别使用的是permission_setp_r,在实际使用的时候要注意这里的方法分别为 'A表_set' 和 第三张表用下划线连起来的后两个字段。

扩展练习:

  1. 查询admin用户具备那些权限?

2)判断王大锤一个用户是否有登录权限?

def showall(request):
    #1) 查询admin用户具备那些权限?

    pers = User.objects.get(u_name='admin').r_id.permission_set.all()

    #2)判断王大锤一个用户是否有登录权限?

    islogin = User.objects.get(u_name='王大锤').r_id.permission_set.filter(p_name='登录').exists()

    return render(request, 'showall.html', {'pers': pers, 'islogin': islogin})

结果如下图:

显示界面配置
查询结果
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • Django Model 定义语法 版本:1.7主要来源:https://docs.djangoproject.c...
    罗田阅读 31,017评论 2 42
  • Django 1.8.2 文档Home | Table of contents | Index | Modules...
    轩辕小爱阅读 2,344评论 0 2
  • 你从梦里向我走来 步履蹒跚 你从梦里向我呼唤 亲昵不变 多少次的想 汇成这样的念 多少次的思 汇成这样的爱 惊醒又...
    果冻果呐阅读 172评论 0 4