首页 > 其他分享 >django 数据表关系学习和应用

django 数据表关系学习和应用

时间:2024-04-23 10:14:12浏览次数:19  
标签:关系 models 模型 django 学习 数据表 ManyToManyField 关联 self

数据表有 一对一,一对多,多对多,关系

在django 中如何实现?

django 提供了三种最常见的数据库关联关系方法:多对一,多对多,一对一

多对一关联:

定义多对一关联关系,使用django.db.model.ForeignKey 类,就和其它 Field 字段类型一样,只需要在你模型中添加一个值为该类的属性。

ForeignKey 需要添加一个 位置参数,即你想要关联的模型类名

from django.db import models
#被关联类
#唯一方,制造商是惟一的 class Manufacturer(models.Model): # ... pass #设有关联的字段类
#多方,car 有很多辆,与 制造方只有一个关系 class Car(models.Model):
  #这里的定义方是,设置一个制造方的字段,manufacturer
  #其中,标红的,是需要关联的类.
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE) # ...

 

多对多关系

 定义一个多对多的关联关系,使用 django.db.models.ManyToManyField 类。就和其他 Field 字段类型一样,只需要在你模型中添加一个值为该类的属性。

ManyToManyField 类需要添加一个位置参数,即你想要关联的模型类名。

例如:如果 Pizza 含有多种 Topping (配料) -- 也就是一种 Topping 可能存在于多个 Pizza 中,并且每个 Pizza 含有多种 Topping --那么可以这样表示这种关系:

 1 from django.db import models
 2 
 3 
 4 class Topping(models.Model):
 5     # ...
 6     pass
 7 
 8 
 9 class Pizza(models.Model):
10     # ...
11     toppings = models.ManyToManyField(Topping)

和 ForeignKey 类一样,你也可以创建 自关联关系 (一个对象与他本身有着多对多的关系)和 与未定义的模型的关系 。

建议设置 ManyToManyField 字段名(上例中的 toppings )为一个复数名词,表示所要关联的模型对象的集合。

对于多对多关联关系的两个模型,可以在任何一个模型中添加 ManyToManyField 字段,但只能选择一个模型设置该字段,即不能同时在两模型中添加该字段。

一般来讲,应该把 ManyToManyField 实例放到需要在表单中被编辑的对象中。在之前的例子中, toppings 被放在 Pizza 当中(而不是 Topping 中有指向 pizzas 的 ManyToManyField 实例 )因为相较于配料被放在不同的披萨当中,披萨当中有很多种配料更加符合常理。按照先前说的,在编辑 Pizza 的表单时用户可以选择多种配料.

在多对多(many-to-many)关系中添加添加额外的属性字段

如果你只是想要一个类似于记录披萨和配料之间混合和搭配的多对多关系,标准的 ManyToManyField 就足够你用了。但是,有时你可能需要将数据与两个模型之间的关系相关联。

举例来讲,考虑一个需要跟踪音乐人属于哪个音乐组的应用程序。在人和他们所在的组之间有一个多对多关系,你可以使用 ManyToManyField 来代表这个关系。然而,你想要记录更多的信息在这样的关联关系当中,比如你想要记录某人是何时加入一个组的。

对于这些情况,Django 允许你指定用于控制多对多关系的模型。你可以在中间模型当中添加额外的字段。在实例化 ManyToManyField 的时候使用 through 参数指定多对多关系使用哪个中间模型。对于我们举的音乐家的例子,代码如下:

 1 from django.db import models
 2 
 3 
 4 class Person(models.Model):
 5     name = models.CharField(max_length=128)
 6 
 7     def __str__(self):
 8         return self.name
 9 
10 
11 class Group(models.Model):
12     name = models.CharField(max_length=128)
13     members = models.ManyToManyField(Person, through="Membership")
14 
15     def __str__(self):
16         return self.name
17 
18 # 这是自定义了一张 多对多的关系表.
  #因为多对多关系中,django 在不指定关系表的情况下,会自动生成一个 中间关系表,
  #且只有 两个表的 id字段,没有其他任何字段.
  # 如果 你想记录 多对多关系中,更多信息,就需要 自定义 一个 关系表.
  # 并拓展相应的字段,来实现
  # 使用 through = "XXXX"表类,来指定 关联关系.
  # 这个将在 自己的事例中使用到.
19 class Membership(models.Model): 20 person = models.ForeignKey(Person, on_delete=models.CASCADE) 21 group = models.ForeignKey(Group, on_delete=models.CASCADE) 22 date_joined = models.DateField() 23 invite_reason = models.CharField(max_length=64)

你需要在设置中间模型的时候,显式地为多对多关系中涉及的中间模型指定外键。这种显式声明定义了这两个模型之间是如何关联的。

在中间模型当中有一些限制条件:

  • 你的中间模型要么有且  有一个指向源模型(我们例子当中的 Group )的外键,要么你必须通过 ManyToManyField.through_fields 参数在多个外键当中手动选择一个外键,如果有多个外健且没有用 through_fields 参数选择一个的话,会出现验证错误。对于指向目标模型(我们例子当中的 Person )的外键也有同样的限制。
  • 在一个用于描述模型当中自己指向自己的多对多关系的中间模型当中,可以有两个指向同一个模型的外健,但这两个外健分表代表多对多关系(不同)的两端。如果外健的个数 超过 两个,你必须和上面一样指定 through_fields 参数,要不然会出现验证错误。

现在你已经设置好了你的 ManyToManyField 来使用你的中介模型(在这种情况下是 Membership),你可以开始创建一些多对多关系。你可以通过创建中介模型的实例来实现这一点:

>>> 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>]>

 

一对一关联

使用 OneToOneField 来定义一对一关系。就像使用其他类型的 Field 一样:在模型属性中包含它。

当一个对象以某种方式“继承”另一个对象时,这对该对象的主键非常有用。

OneToOneField 需要一个位置参数:与模型相关的类。

例如,当你要建立一个有关“位置”信息的数据库时,你可能会包含通常的地址,电话等字段。接着,如果你想接着建立一个关于关于餐厅的数据库,除了将位置数据库当中的字段复制到 Restaurant 模型,你也可以将一个指向 Place OneToOneField 放到 Restaurant 当中(因为餐厅“是一个”地点);事实上,在处理这样的情况时最好使用 模型继承 ,它隐含的包括了一个一对一关系。

 1 from django.db import models
 2 
 3 
 4 class Place(models.Model):
 5     name = models.CharField(max_length=50)
 6     address = models.CharField(max_length=80)
 7 
 8     def __str__(self):
 9         return f"{self.name} the place"
10 
11 
12 class Restaurant(models.Model):
13     place = models.OneToOneField(
14         Place,
15         on_delete=models.CASCADE,
16         primary_key=True,
17     )
18     serves_hot_dogs = models.BooleanField(default=False)
19     serves_pizza = models.BooleanField(default=False)
20 
21     def __str__(self):
22         return "%s the restaurant" % self.place.name
23 
24 
25 class Waiter(models.Model):
26     restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
27     name = models.CharField(max_length=50)
28 
29     def __str__(self):
30         return "%s the waiter at %s" % (self.name, self.restaurant)

OneToOneField 字段还接受一个可选的 parent_link 参数。

OneToOneField 类通常自动的成为模型的主键,这条规则现在不再使用了(然而你可以手动指定 primary_key 参数)。因此,现在可以在单个模型当中指定多个 OneToOneField 字段。

 

数据表中,多字段联合唯一 ,如何实现?

联合唯一这个也要定义,还要重新迁移表

否则表的的定义方式有欠缺.

unique_together

Options.unique_together

使用 UniqueConstraint 与 constraint 选项代替。

UniqueConstraint 比 unique_together 提供更多的功能。unique_together 今后可能会被废弃。

一组字段名,合起来必须是唯一的:

unique_together = [["driver", "restaurant"]]

这是一个列表,这些列表在一起考虑时必须是唯一的。它 在Django 管理中使用,并在数据库级别执行(即在 CREATE TABLE 语句中包含适当的 UNIQUE 语句)。

为方便起见,unique_together 在处理单组字段时可以是一个单一的列表:

unique_together = ["driver", "restaurant"]

ManyToManyField 不能包含在 unique_together 中。(甚至不清楚这意味着什么!)如果需要验证与 ManyToManyField 相关的唯一性,请尝试使用信号或显式的 through 模型。

在模型验证过程中,当约束条件被违反时引发的 ValidationError 具有 unique_together 错误代码

 

自关联字段字的一对多查询 ,如何实现?

关联实现:

ForeignKey

class ForeignKey(toon_delete**options)

一个多对一的关系。需要两个位置参数:模型相关的类和 on_delete 选项。

要创建一个递归关系——一个与自己有多对一关系的对象——使用 models.ForeignKey('self', on_delete=models.CASCADE)

关联查询:

django 自关联下的 一对多查询

在Django中,自关联的一对多查询指的是一个模型中的一个字段关联到了模型本身。例如,一个Comment模型可能有一个外键指向它自己,表示每个评论都可以回复另一个评论。

以下是一个简单的例子:

   
1 from django.db import models
2  
3 class Comment(models.Model):
4     text = models.TextField()
5     reply_to = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='replies')
6  
7     def __str__(self):
8         return self.text

查询所有顶级评论(即没有reply_to的评论):

top_level_comments = Comment.objects.filter(reply_to__isnull=True)

查询特定评论的所有回复:

  1 comment = Comment.objects.get(id=comment_id) 2 replies = comment.replies.all() 

在这个例子中,top_level_comments 是一个顶级评论的查询集,而 replies 是作为 comment 对象的回复的查询集。

#如果没有 指定related_name ,那就按照 默认的 形式:XXX_set来代表 查询集

例 :“反向” 关联

若模型有 ForeignKey,外键关联的模型实例将能访问 Manager,后者会返回第一个模型的所有实例。默认情况下,该 Manager 名为 FOO_set, FOO 即源模型名的小写形式。 Manager 返回 QuerySets,后者能以 “检索对象” 章节介绍的方式进行筛选和操作。

 

>>> b = Blog.objects.get(id=1)
>>> b.entry_set.all()  # Returns all Entry objects related to Blog.

# b.entry_set is a Manager that returns QuerySets.
>>> b.entry_set.filter(headline__contains="Lennon")
>>> b.entry_set.count()

 

 

在 django 设置model ,然后迁移生成数据表,(database)方便还是直接使用mysql ,在数据库中创建表方便.

数据库中,即mysql 定义 外键,如何实现?

这个问题,稍微复杂点,单独来起说明

 

标签:关系,models,模型,django,学习,数据表,ManyToManyField,关联,self
From: https://www.cnblogs.com/bdxily/p/18148924

相关文章

  • 初接触:从创建工程到导出gerber(学习Altium Designer)
    学习AltiumDesignerAltiumDesigner的工程文件后缀为.PrjPcb,主要包含SourceDocuments和Libraries。SourceDocuments里面有SchDoc文件,即原理图文件;PcbDoc文件,即PCB文件。Libraries即库,包含原理图库和pcb库,原理图库里面是component,可以自行绘制,在properties可以添加footprint,将......
  • Markdown 学习
    Markdown学习二级标题##+空格三级标题字体Hello,World!两边加两个**Hello,World!两边加一个*Hello,World!三个*Hello,World!两边加~~引用选择狂神说java分割线图片超链接点击跳转到博客列表abcabc表格名字性别生日......
  • Python遗传算法GA对长短期记忆LSTM深度学习模型超参数调优分析司机数据
    全文链接:https://tecdat.cn/?p=36004原文出处:拓端数据部落公众号随着大数据时代的来临,深度学习技术在各个领域中得到了广泛的应用。长短期记忆(LSTM)网络作为深度学习领域中的一种重要模型,因其对序列数据的强大处理能力,在自然语言处理、时间序列预测等领域中取得了显著的成果。然......
  • 【专题】2023年中国社会办口腔医疗企业报告PDF合集分享(附原数据表)
    原文链接:https://tecdat.cn/?p=34300原文出处:拓端数据部落公众号口腔健康是整体健康的重要基石,当前,无论是哪个年龄段的人群,或多或少都会受到口腔问题的困扰。随着国民口腔健康意识的不断提高,消费者对口腔医疗服务的需求日益多元化,口腔医疗行业也迎来了快速发展阶段。阅读原文,获......
  • Python利用GPU进行深度学习
    在深度学习当中,我们训练模型通常要对模型进行反复的优化训练,仅用CPU来进行训练的话需要花费很长时间,但是我们可以使用GPU来加速训练模型,这样就可以大大减少训练模型花费的时间。 首先我们需要一张NVIDIA显卡在搜索栏中搜索设备管理器前往NVIDIA官网下载显卡对应的Studio......
  • C++开发学习
    C++第三方库使用如何在VS中配置第三方C++库教程在程序的源文件(如.c和.cpp文件)编辑阶段,为了使用第三方库,我们一般会在编辑器中使用#include指令来包含库的头文件(.h或.hpp文件)。编写好程序的源文件后,在编译阶段,编译器会根据头文件中声明的函数、类等信息去寻找这个函数......
  • C语言学习笔记
    ​学习C语言是掌握计算机科学的基础,并为学习其他高级编程语言打下坚实的基础。C语言是一种高效率的编程语言,被广泛用于系统软件和应用软件的开发。1、C语言基础变量和数据类型:理解基本数据类型(int,char,float,double等)以及更复杂的类型,如数组和结构体。运算符:熟悉C语言支持......
  • C# 学习笔记
    ​  1、C#基础数据类型和变量:学习如何使用基本数据类型(int,double,char,bool等)以及更复杂的类型(数组、枚举、结构体)。运算符:理解各种运算符(算术运算符、比较运算符、逻辑运算符等)的使用。控制结构:学习使用条件语句(if,switch)和循环结构(for,while,do-while,foreach)来......
  • 软考高项(已通过,E类人才)-学习笔记材料梳理汇总
    软考高项,即软考高级信息系统项目管理师,全国计算机技术与软件专业技术资格(水平)考试中的高级水平测试。适用于从事计算机应用技术、软件、网络、信息系统和信息服务等领域的专业人员,以及各级企业管理人员和从事项目管理事业的相关人士。申请杭州E类人才等用途资源整理地址备注......
  • 【pytorch学习】之线性代数
    3线性代数3.1标量如果你曾经在餐厅支付餐费,那么应该已经知道一些基本的线性代数,比如在数字间相加或相乘。例如,北京的温度为52◦F(华氏度,除摄氏度外的另一种温度计量单位)。严格来说,仅包含一个数值被称为标量(scalar)。如果要将此华氏度值转换为更常用的摄氏度,则可以计算表达式$C=......