Django のマルチテーブル クエリ

ORM リンク テーブル操作

django で orm を学習する場合、1 対多と多対多を前方探索と後方探索の 2 つの方法に分けることができます。

前方参照: ForeignKey は UserInfo テーブルにあります。UserInfo テーブルから他のテーブルのクエリを開始する場合、これは順方向の操作であり、UserType テーブルから他のテーブルのクエリを開始する場合、これは逆の操作です。

  • 一対多: モデル。外部キー (他のテーブル)
  • 多対多: モデル。ManyToManyField (その他のフォーム)
  • 一対一:モデル。1 対 1 フィールド (他のテーブル)
フォワード リンク テーブル操作の概要:

いわゆる順結合テーブル操作と逆結合テーブル操作の ID は、Foreign_Key フィールドが配置されているテーブルによってのみ決定されます。

Foreign_Key フィールドは、任意のテーブルのテーブルを結合するために使用できます。それ以外の場合は、Foreign_Key フィールドに関連付けられた小文字のテーブル名が使用されます。

  • 一対多: オブジェクト。外部キー。関連テーブル フィールド、値 (外部キー フィールド_関連テーブル フィールド)

  • 多対多: 外部キー フィールド。全て()

逆結合テーブル操作の概要:
  • 値、値のリスト、およびフィルターでテーブル間をリバース: 小文字の tablename_associated テーブル フィールド

  • オブジェクトごとにテーブルを逆にします: 小文字の surface _set.all()。

    • all(): すべて取得

    • フィルター: もう一度フィルターをかけます

    Class.objects.filter(id=1).first().stu_set.filter(name__startswith='o')
    
フィールド関係:
  • フィールド リレーションシップは、django がテーブル リレーションシップを維持する方法です。主に 1 対 1、多対 1、多対多があります。

  • 現在の 1 対 1 および多対 1 の関係では、次のように、関連付けられたデータが削除されたときの操作を記述するためにon_delete属性を設定する必要があります。

    • models.CASCADE: 関連付けられたデータを削除し、関連付けられたデータを削除します
    • models.PROTECT: 関連するデータを削除し、エラー ProtectedError を発生させます
    • models.SET_NULL: それに関連付けられた値が null に設定されています (前提として、FK フィールドを null 許容に設定する必要があります)。
    • models.SET_DEFAULT: 関連するデータを削除し、関連する値をデフォルト値に設定します (FK フィールドをデフォルト値に設定する必要があります)。
    • models.DO_NOTHING: 関連データを削除し、何もしません
1 対 1 の関係:

たとえば、教師テーブルがあり、教授テーブルが必要な場合、教授テーブルには教師テーブルの一連の属性が含まれている可能性があり、教師テーブルのフィールドを教授に直接コピーしたくない教授テーブル継承教師テーブルを実装するには、 OneToOneFieldを使用できます。

模型类使用OneToOneField用来定义一对一关系;

OneToOneField(to,on_delete,parent_link=False,options)

class Child(models.Model):
    name=models.CharField(max_length=100,verbose_name='姓名')
    age=models.CharField(max_length=100,verbose_name='年纪')
    def __str__(self):
        return self.name

class Man(models.Model):
    child=models.OneToOneField(to=Child,verbose_name='小孩',on_delete=models.CASCADE)
    Responsibility=models.BooleanField(verbose_name='责任',default=True)
    def __str__(self):
        return self.child.name

python .\manage.py shell
from myapp.models import *
c1=Child.objects.create(name='张三',age='18')  #添加一条数据到child表
m1=Man.objects.create(child=c1)
m1.child   --><Child: 张三>
m1.child.name   -->'张三'
c1.delete()   --> {'myapp.Man': 1, 'myapp.Child': 1})   删除被继承的表的数据  继承的表数据也同时被删除
多対一の関係

Django は django.db.models.ForeignKey を使用して多対 1 の関係を定義しますForeignKey
には位置パラメータが必要です: モデルに関連付けられたクラス
人生における多対 1 の関係: クラスの教師、クラスの関係。校長は多くのクラスを率いることができますが、各クラスには校長が 1 人しかいません

class Headmaster(models.Model):
	name=models.CharField(max_length=50)
	def __str__(self):
		return self.name

class Class(models.Model):
	class_name=models.CharField(max_length=50)
	teacher=models.ForeignKey(Headmaster,null=True,on_delete=models.SET_NULL)
	def __str__(self):
		return self.class_name


>>> H1 = Headmaster(name='渔夫')
>>> H1.save()
>>> H1
<Headmaster: 渔夫>
>>> H2 = Headmaster(name='农夫')
>>> H2.save()
>>> Headmaster.objects.all() 
[<Headmaster: 渔夫>, <Headmaster: 农夫>]

以上创建了两条老师数据
由于我们设置外键关联可以为空 null=True ,所以此时在班级表创建时,可以直接保存,不需要提供老师数据

>>> C1 = Class(class_name='一班') 
>>> C2 = Class(class_name='二班') 
#如果外键设置不为空时,保存会引发以下错误 
# IntegrityError: NOT NULL constraint failed: bbs_class.teacher_id 
>>> C1.teacher = H1 
>>> C2.teacher = H2 
>>> C1.save() 
>>> C2.save()

将老师分配个班级之后,由于班级表关联了老师字段,我们可以通过班级找到对应老师
虽然老师表中没有关联班级字段,但是也可以通过老师找到他所带的班级,这种查询方式也叫作关联查询
通过模型类名称后追加一个'_set',来实现反向查询
>>> H1.class_set.all() 
<QuerySet [<Class: 一班>]>

由于我们这是一个多对一的关系,也就说明我们的老师可以对应多个班级
我们可以继续给H1老师分配新的班级

>>> C3 = Class(class_name='三班') 
>>> C3.teacher = H1 
>>> C3.save() 
>>> H1.class_set.all() 
[<Class: 一班>, <Class: 三班>]
  • クラスは 1 人の教師にしか対応できず、外部キーは一意であるため、引き続き新しい教師をクラス C1 に割り当てると、以前の教師の情報は上書きされ、新しい教師は保存されません。
多対多の関係

多対多の関係は、 ManyToManyFieldフィールドを使用してモデルで定義されます

多対多の関係は、関連付けることも関連付けないこともできるため、 on_delete 属性を明示的に指定する必要はありません. 人生では、
多対多の関係: ミュージシャンは複数のバンドに所属でき、バンドは複数のバンドを持つことができますミュージシャン

class Artist(models.Model):
	artist_name=models.CharField(max_length=50)
	def __str__(self):
		return self.artist_name

class Band(models.Model):
	band_name=models.CharField(max_length=50)
	artist=models.ManyToManyField(Artist)
	def __str__(self):
		return self.band_name

创建音乐家以及乐队
>>> from bbs.models import Artist,Band 
>>> A1 = Artist.objects.create(artist_name='Jack') 
>>> A2 = Artist.objects.create(artist_name='Bob') 
>>> B1 = Band.objects.create(band_name='FiveMonthDay') 
>>> B2 = Band.objects.create(band_name='SHE')

创建出两个乐队之后对其进行音乐家的添加
多对多字段添加时,可以使用 add 函数进行多值增加

>>> B1.artist.add(A1,A2) 
>>> B2.artist.add(A2)

B1 乐队含有 A1 , A2 两名成员
B2 乐队含有 A1 成员

>>> B1.artist.all() 
[<Artist: Bob>, <Artist: Jack>] 
>>> B2.artist.all() 
[<Artist: Jack>]

可以在音乐家表中查找某个乐家属于哪些乐队
>>> Band.objects.filter(artist=A1) # 这里使用的是我们模型类来进行查找。 
[<Band: SHE>, <Band: FiveMonthDay>] # A1乐家属于,SHE以及FiveMonthDay 
>>> Band.objects.filter(artist=A2) 
[<Band: SHE>]

也可以查找这音乐家在哪个乐队
>>> A1.band_set.all() # 直接通过具体数据对象进行查找 
[<Band: SHE>, <Band: FiveMonthDay>] 
>>> A2.band_set.all() 
[<Band: SHE>]

多对多关联字段的删除,要使用 remove 来进行关系的断开
而不是直接使用 delete , remove 只会断开数据之间的联系,但是不会将数据删除
现在在B1乐队中删除A1乐家

>>> B1.artist.remove(A1) 
>>> B1.artist.all() 
<QuerySet [<Artist: Bob>]>

おすすめ

転載: blog.csdn.net/s_frozen/article/details/129031408