自關聯
表內自關聯是指表內數據相關聯的對象和表是相同字段,這樣我們就直接用表內關聯將外鍵關聯設置成自身表的字段。同樣表內關聯也分一對多字段和多對多字段
例如:對於微博評論,每條評論都可能有子評論,但每條評的字段內容應該都是相同的,並且每條評論都只有一個父評論,這就滿足了,一對多的情形。父評論為關聯字段,可以對應多個子評論,這就是一對多的自關聯。
一對多
在django項目的models中創建評論表。
#評論表
class Comment(models.Model):
#評論的內容字段
content=models.CharField(max_length=255)
#評論的發布時間
push_time=models.DateTimeField(auto_now_add=True)
#關聯父評論的id,可以為空
pcomment = models.ForeignKey(to='self',null=True)
def __str__(self):
return self.content
添加數據,第一條數據關聯字段為空,說明是父評論,第二條數據關聯了第一條數據說明是第一條數據的字評論,同樣后兩條數據是是第二條數據的子評論.
接下來查找第一條數據的子評論:
#第一條數據的id是1,可以通過篩選父評論關聯字段等於1的對象
print(Comment.objects.filter(pcomment_id=1))
#根據子評論關聯id正向查找父評論的內容
print(Comment.objects.filter(pcomment_id=2).values('pcomment__content'))
#根據父評論的id反向查找子評論
print(Comment.objects.filter(id=1).values('comment__id'))
注意:外鍵關聯是在子評論中,有關聯字段的是子評論,子評論查父評論是正向,父評論查子評論是反向。
多對多表自關聯
建立一張表,表字段為姓名以及朋友多對多字段,一個人可有多個朋友,也可以是多個人的朋友,找一個人的朋友是正向查找,找是某個人的朋友是反向查找。
class Person(models.Model):
name = models.CharField(max_length=12)
#人和人交朋友
friends = models.ManyToManyField(to='self',symmetrical=False,related_name='ship')
def __str__(self):
return self.name
# 查找沁陽的基友
#正向查找關聯字段__name
print(Person.objects.filter(name='沁陽').values('friends__name'))
# 反向查找沁陽的基友
# print(Person.objects.all().filter(ship__name='沁陽'))
# 查找王帥的基友
# 正向查找關聯字段__name,王帥是沁陽的朋友但王帥的朋友是空,因為王帥沒有關聯別人
print(Person.objects.get(name='王帥').friends.all())
#反向查找是王帥朋友的人,也是空
print(Person.objects.filter(ship__name='王帥'))
# 基友是沁陽的那個人反向查找
print(Person.objects.get(name='沁陽').ship.all())
#基友是王帥的那個人反向查找
# print(Person.objects.get(name='王帥').ship.all())
# 基友含有沁陽的人反向
print(Person.objects.filter(name='沁陽').values('ship__name'))
注意:查找某人的朋友是正向,查找朋友里面有某人的人是反向查找
反向名稱related_name
反向名稱,用來從被關聯字段指向關聯字段。
注意,在你定義 抽象 model (abstract models) 時,你必須顯式指定反向名稱; 只有在你這么做了之后, 某些特別語法 (some special syntax) 才能正常使用。
class Book(models.Model):
name=models.CharField(max_length=20)
pub=models.ForeignKey(Publisher,related_name='pub')
authors=models.ManyToManyField(Author,related_name='author')
這樣用Publisher或者Author反向查詢Book時可以用related_name了:publisher1.pub.all()或者author1.author.all()。
如果不想設置反向關系,設置related_name為'+'或者以'+'結束。
user = models.ForeignKey(User, related_name='+')
如果有多個ManyToManyField指向同一個Model,這樣反向查詢FOO_set的時候就無法弄清是哪個ManyToManyField字段了,可以禁止反向關系:
users = models.ManyToManyField(User, related_name='u+')
referents = models.ManyToManyField(User, related_name='ref+')
