2014-02-14 27 views
1

我想構建一個新的相關字段類型。這裏有一個簡單的例子:構建一個返回多個值的Django「ForeignKey」

class CustomQuerySet(QuerySet): 
    def current(self): 
     return self.filter(invalid_date__isnull=True) 

class CustomManager(Manager): 
    def get_query_set(self): 
     return CustomQuerySet(self.model, using=self._db) 
    def current(self): 
     return self.get_query_set().current() 

class Item(models.Model): 
    objects = CustomManager() 

    row_id = models.IntegerField(primary_key=True) 
    id = models.IntegerField() 
    name = models.CharField(max_length=100) 
    change_date = models.DateTimeField(auto_now_add=True) 
    invalid_date = models.DateTimeField(null=True, blank=True) 


class Collection(models.Model): 
    item = MultipleRelatedField(Item, related_field='id', related_name='collections') 
    name = models.CharField(max_length=100) 

鑑於c = Collection()

  • c.item應該返回一個QuerySet相當於Item.objects.filter(id=c.item_id)
  • 該查詢集確實需要是CustomQuerySet的一個實例
  • Item.objects.filter(collections__name='SomeName')應該按預期工作。
  • 操作Collection.objects.filter(item__name='OtherName', item__invalid_date__isnull=True)應該按預期工作。

我知道這可以用ManyToManyField實現,但我不想手動添加/刪除項目對象到c.item。我不需要連接表,因爲c.item總是使用單個id值,但它不是Collection上的主鍵。並且c.item可能/不包含具有不同id值的項目對象。

我知道這可能需要子類django.db.models.fields.related.ForeignRelatedObjectsDescriptor和/或django.db.models.fields.related.ForeignObject(或可能ManyToMany等效)。

+0

每個項目是否屬於一個集合?如果是這樣,您可能只需在您的Item對象上指向'Collection'的'ForeignKey'。您可以使用'RelatedManager'來自定義反向關係爲您提供的查詢集。 –

+0

好問題。名字是人爲設計的,可能有多個類像'Collection',並且修改'Item'爲每個類添加'ForeignKey'是不可接受的。 'MultiRelatedField'作爲一個返回多個值的'ForeignKey'函數。所以不止一個'Collection'可以引用相同的'id'值。 –

回答

1

它在我看來,像你真正想要的是一種自動方式來根據A中的字段值從模型A生成一個查詢集與另一個模型B

我懷疑,最終,將該queryset返回爲A上的字段值並不是真正的最佳解決方案 - 這確實違背了ORM的粒度,並且會使其難以使用,例如,使用模型在管理員或其他常見的地方。

相反,它會更好,從如何Django的治療領域與choices集取一個想法:自動生成模型類中的方法返回得到的信息,例如,如果你的模型有一個字段:

item = MultipleRelatedField(Item, related_field='id', related_name='collections') 

你會自動獲得像get_item_queryset這樣的方法,它會返回你指定的查詢集。

要建立的是,你很可能要繼承現有場(IntegerField可能會是一個很好的起點),然後重寫__init__方法(接受額外的參數)和contribute_to_class方法(其中新的方法將被生成)。你可以在the choices-derived get_FIELD_display method here的地方看到這個地方的靈感。

+0

不是一個可怕的解決方案,但沒有解決連接問題。 –

+0

@AaronMcMillin,我不確定你的意思是「加入的問題」 –

+0

這個:Item.objects。過濾器(collections__name ='SomeName')'不會與您的解決方案一起工作,因爲它不會像Django那樣創建關係。 –