django.relatedField-關聯域

對於django的model,尤爲是related field,我建議從model的自己含義出發,而不要從數據庫的角度去看。python

related_field僅僅是表示model之間的關係,至於數據庫的實現,須要的時候再去了解。這樣才能比較容易的理解django的model設計思想。數據庫

好比ForeignKey的含義,就是多對一的關係。這裏並不是字段的對應,而是model的對應。也就是說,有多個model對應一個model。因此ForeignKey在django中,就是表示model的含義,而非字段。
django

ManyToManyField的含義,也是指定多個model對應於多個model的關係。app

先創建所需的model:ui

class Color(models.Model):
    name = models.CharField(max_length=10)
    
    def __str__(self)
        return self.name


class Fruit(models.Model):
    name = models.CharField(max_length=10)
    price = models.IntegerField()
    color = models.ForeignKey(Color)
    
    def __str__(self)
        return self.name

class Area(models.Model):
    province = models.CharField(max_length=10)
    fruits = models.ManyToManyField(Fruit)
    
    def __str__(self)
        return self.name

class User(models.Model):
    name = models.CharField(max_length=10)
    fruits = models.ManyToManyField(Fruit, related_name='related_name', related_query_name='related_query_name')
    
    def __str__(self)
        return self.name


Fruit與Area是多對多的關係, 一個地區會生產多種水果,而一種水果也會被多個地區生產。
spa

Fruit與User是多對多的關係,一個用戶能夠喜歡多種水果,而一種水果也會被多個用戶喜歡。設計

Fruit與Color是多對一,一種水果相對有一種顏色。code


插入數據:
orm

首先向Color插入數據:對象

>>> color_red = Color(name='red')
>>> color_yellow = Color(name='yellow')
>>> color_red.save()
>>> color_yellow.save()
>>> color_green = Color(name='green')
>>> color_green.save()

而後向Fruit插入數據。注意color是Fruit的外鍵,因此添加時,須要指定color爲Color的實例。

>>> apple = Fruit(name='apple', price=10, color=color_red)
>>> apple.save()
>>> orange = Fruit(name='orange', price=5, color=color_yellow)
>>> orange.save()
>>> watermelon = Fruit(name='watermelon', price=20, color=color_green)
>>> watermelon.save()

而後向Area添加數據。注意Area和Fruit是多對多的關係,必須先保存,而後在來指定二者的關係。

>>> shanghai = Area(province='shanghai')
>>> shanghai.save()
>>> guangzhou = Area(province='guangzhou')
>>> guangzhou.save()

>>> shanghai.fruits.add(apple)
>>> apple.area_set.add(guangzhou)

    關係的添加和刪除是由ManyRelatedManager對象管理的。

    它的獲取方式與ManyToManyField的定義的位置有關。

    若是在有ManyToManyField的model中,直接提取字段名就能夠。

    在沒有ManyToManyField的model中, 使用related_name獲取,若是沒有默認爲xxx_set, xxx爲對應的model名。

向User添加數據,

>>> jack = User(name='jack')
>>> jack.save()
>>> jack.fruits.add(apple)
>>> orange.related_name.add(jack)

>>> july = User(name='july')
>>> july.save()
>>> july.fruits.add(apple)


查詢數據

查詢有喜歡apple的user

>>> User.objects.filter(fruits__name='apple')
<User: jack>, <User: july>]

這裏使用了雙下劃線, xxxx1__xxxx2。

xxxx1的獲取,

    分爲兩種狀況

  1. ManyToManyField在model中

    直接獲取其字段名

  2. ManyToManyField不在model中

        a.  獲取ManyToManyField的related_query_name屬性。

        b. 獲取ManyToManyField的related_name屬性。

        c. 獲取對應model名的小寫格式。

xxxx2即爲字段名。


查詢有用戶是jack的喜歡的水果

>>> Fruit.objects.filter(related_query_name__name='jack')
[<Fruit: apple>, <Fruit: orange>]
>>>
>>> User.objects.get(name='jack').fruits.all()
[<Fruit: apple>, <Fruit: orange>]


查詢用戶名是j開頭的喜歡的水果

>>> Fruit.objects.filter(related_query_name__name__startswith='j')
[<Fruit: apple>, <Fruit: orange>, <Fruit: apple>]


這裏指定了related_name和related_query_name的屬性值,比較特殊,是爲了更好的解釋其做用。

通常來講,我習慣把related_name設爲model的名字加上s, related_query_name設爲model的名。

好比上面的User中fruits字段, 

fruits = models.ManyToManyField(Fruit, related_name='users', related_query_name='user')


最後有一點注意到,若是一個model會有兩個指向同一個model的外鍵。那麼這兩個外鍵必須指定related_name,而且還不能相同。舉例來講:

class User(models.Model):
    name = models.CharField(max_length=20)
    
    def __str__(self):
        return self.name

class Message(models.Model):
    content = models.CharField(max_length=200)
    sender = models.ForeignKey(User, related_name='send_messages')
    receiver = models.ForeignKey(User, related_name='receive_messages')
    
    def __str__(self):
        return self.content

寫數據:

>>> names = ['Mary', 'Jim', 'Sam']
>>> for name in names:
        user = User(name=name)
        user.save()
>>> import itertools
>>> users = User.objects.all()
>>> for sender, receiver in itertools.permutations(users, 2):
        content = '%s-to-%s' % (sender.name, receiver.name)
        msg = Message(content=content, sender=sender, receiver=receiver)
        msg.save()

在上面代碼中,實例化三我的Mary,Jim,Sam。而且都互相發送了短信。

>>> Mary = User.objects.get(name='Mary')

# get messages which Mary sends
>>> Mary.send_messages.all()
[<Message: Mary-to-Jim>, <Message: Mary-to-Sam>]

# get messages which Mary reveives
>>> Mary.receive_messages.all()
[<Message: Jim-to-Mary>, <Message: Sam-to-Mary>]
相關文章
相關標籤/搜索