2012-07-24 66 views
1

我在我的models.py具有一個ForeignKey主體材料一個CarType:過濾ForeignKey的

class BodyMaterial(models.Model): 
    location    = models.ForeignKey('CarType') 
    name     = models.CharField(max_length=255) 

class CarType(models.Model): 
    name     = models.CharField(max_length=255) 
    default_body_material = models.ForeignKey(BodyMaterial, null = True, blank = True, default = "", limit_choices_to={'location__exact': 1}) 

主體材料是在CarType內聯在我admin.py:

class BodyMaterial_Inline(admin.StackedInline): 
    model = BodyMaterial 
    extra = 1 

class CarType_Admin(admin.ModelAdmin): 
    inlines = [BodyMaterial_Inline] 

admin.site.register(CarType, CarType_Admin) 

我想過濾default_body_material的ForeignKey以僅顯示相關的BodyMaterials(在同一個管理頁面上出現/添加的BodyMaterials)。例如,我創建了2個座位的CarType,並在同一個頁面中添加了一些BodyMaterials。然後我創建一個SVU CarType和一些其他BodyMaterials。當我回到2個座位的CarType時,我只想在default_body_material的下拉列表中看到相關的BodyMaterials。

我嘗試使用id上的limit_choices_to進行過濾。所以我使用post_init來做這件事,因爲在運行時確定了對象的ID:

def setID(**kwargs): 
    instance = kwargs.get('instance') 
    default_body_material = instance._meta.get_field_by_name('default_body_material')[0] 
    default_body_material.limit_choices_to = {'location__exact': instance.id} 

post_init.connect(setID, CarType) 

不幸的是,那什麼都不做。我錯過了什麼?有沒有一個爲什麼我的目的過濾ForeignKey(這可能是非常基本的)?

請注意,此問題僅適用於管理界面。

回答

0

只需使用自定義ModelForm

class CarTypeAdminForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     super(CarTypeAdminForm, self).__init__(*args, **kwargs) 
     # Can't limit it until instance has been saved at least once 
     if self.instance.pk: 
      self.fields['default_body_material'].queryset = \ 
       self.fields['default_body_material'].queryset \ 
        .filter(location=self.instance) 

class CarTypeAdmin(admin.ModelAdmin): 
    form = CarTypeAdminForm 
    ... 
+0

太好了。這工作! – user1549769 2012-07-25 14:45:30

+0

我確實有一個問題。當我運行instance.bodymaterial_set.all()時,即使沒有你建議的代碼,它也會打印出正確的foregnkeys。我不太熟悉Django,以便了解Django如何在沒有明確聲明查詢集的情況下知道,但它確實如此。我想知道是否有一種更簡單的方法可以在不使用queryset的情況下完成上述操作。 – user1549769 2012-07-25 15:02:43

+0

關鍵是你必須實際存儲一個新的過濾的查詢集來代替當前查詢集的字段。你可以輕鬆地做self.fields ['default_body_material']。queryset = self.instance.bodymaterial_set.all()'。但是,正如我所做的那樣,過濾已分配的查詢集更加穩健,因爲它會從窗體的任何子類中進行更改等,而使用此代碼將會取代它。 – 2012-07-25 15:07:50

0

你想看看重寫查詢集功能爲您在線。