Django細致講解多對多使用through自定義中間表方法
多對多中間表詳解
我們都知道對于ManyToMany字段,Django采用的是第三張中間表的方式。通過這第三張表,來關聯(lián)ManyToMany的雙方。下面我們根據(jù)一個具體的例子,詳細解說中間表的使用。
默認中間表
class Person(models.Model): name = models.CharField(max_length=128) def __str__(self): return self.name class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField(Person) def __str__(self): return self.name
在Group模型中,通過members字段,以ManyToMany方式與Person模型建立了關系。
讓我們來看看,中間表是個什么樣子的:
首先有一列id,這是Django默認添加的,沒什么好說的。然后是Group和Person的id列,這是默認情況下,Django關聯(lián)兩張表的方式。如果你要設置關聯(lián)的列,可以使用to_field參數(shù)。
可見在中間表中,并不是將兩張表的數(shù)據(jù)都保存在一起,而是通過id的關聯(lián)進行映射。
通過through自定義中間表
一般情況,普通的多對多已經(jīng)夠用,無需自己創(chuàng)建第三張關系表。但是某些情況可能更復雜一點,比如如果你想保存某個人加入某個分組的時間呢?想保存進組的原因呢?
Django提供了一個through參數(shù),用于指定中間模型,你可以將類似進組時間,邀請原因等其他字段放在這個中間模型內(nèi)。例子如下:
modle:
from django.db import models class Person(models.Model): name = models.CharField(max_length=128) def __str__(self): return self.name class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField(Person, through='Membership') def __str__(self): return self.name class Membership(models.Model): person = models.ForeignKey(Person, on_delete=models.CASCADE) group = models.ForeignKey(Group, on_delete=models.CASCADE) date_joined = models.DateField() # 進組時間 invite_reason = models.CharField(max_length=64) # 邀請原因
view:
class PersonViews(ModelViewSet): queryset = Person.objects.filter() serializer_class = PersonSerializers class GroupViews(ModelViewSet): queryset = Group.objects.filter() serializer_class = GroupSerializers class MembershipViews(ModelViewSet): queryset = Membership.objects.filter() serializer_class = MembershipSerializers
serializer:
from .models import Person, Group, Membership class MembershipSerializers(serializers.ModelSerializer): class Meta: model = Membership fields = '__all__' class PersonSerializers(serializers.ModelSerializer): class Meta: model = Person fields = '__all__' class GroupSerializers(serializers.ModelSerializer): def to_representation(self, instance): representation = super(GroupSerializers, self).to_representation(instance) representation['members'] = [] for i in PersonSerializers(instance.members, many=True).data: reason = MembershipSerializers(instance.membership_set.get(group=instance.id, person=i['id'])).data['invite_reason'] i['invite_reason'] = reason representation['members'].append(i) return representation class Meta: model = Group fields = '__all__'
從Membership角度,他是建立量到兩個模型(Group,Person)的多對1關系,Django在啟動時,會自動在其關聯(lián)的模型上建立"[model]_set"的屬性,就想常規(guī)的多對一關系一樣——實際上他就是常規(guī)的多對一關系,只不過Person讓其充當另外的角色罷了。
reason = MembershipSerializers(instance.membership_set.get(group=instance.id, person=i[‘id’])).data[‘invite_reason’]
instance.membership_set.get(group=instance.id, person=i[‘id’]) group和person聯(lián)合查出邀請原因
person和group模型上membership對象的默認名稱都將為membership_set.所以通過instance.membership_set.get()可以查看group下的所有關系
person下的所有membership:
# def to_representation(self, instance): # representation = super(PersonSerializers, self).to_representation(instance) # representation['reason'] = MembershipSerializers(instance.membership_set, many=True).data # return representation
到此這篇關于Django細致講解多對多使用through自定義中間表方法的文章就介紹到這了,更多相關Django through自定義中間表內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
解決在pycharm運行代碼,調(diào)用CMD窗口的命令運行顯示亂碼問題
今天小編就為大家分享一篇解決在pycharm運行代碼,調(diào)用CMD窗口的命令運行顯示亂碼問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-08-08python中邏輯與或(and、or)和按位與或異或(&、|、^)區(qū)別
這篇文章主要介紹了python中邏輯與或(and、or)和按位與或異或(&、|、^)區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-08-08解決pytorch下只打印tensor的數(shù)值不打印出device等信息的問題
這篇文章主要介紹了解決pytorch下只打印tensor的數(shù)值不打印出device等信息的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-05-05python爬蟲開發(fā)之Request模塊從安裝到詳細使用方法與實例全解
這篇文章主要介紹了python爬蟲開發(fā)之Request模塊從安裝到詳細使用方法與實例全解,需要的朋友可以參考下2020-03-03python操作MySQL 模擬簡單銀行轉(zhuǎn)賬操作
這篇文章主要介紹了python操作MySQL 模擬簡單銀行轉(zhuǎn)賬操作,需要的朋友可以參考下2017-09-09python TF-IDF算法實現(xiàn)文本關鍵詞提取
這篇文章主要為大家詳細介紹了python TF-IDF算法實現(xiàn)文本關鍵詞提取,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-05-05