2011-05-17 29 views
38

我有一個標準的多對一關係設置。有一堆領域,但對於我們的目的,相關模型爲:一對多內嵌選擇與Django管理

class Class(models.Model): 
    name = models.CharField(max_length=128) 

class Student(models.Model): 
    class = models.ForeignKey(Class) 
    name = models.CharField(max_length=128) 
    address = models.CharField(max_length=128) 
    # ...etc 

我創建了一個管理員,和它的偉大工程。當我編輯學生時,它甚至會自動爲我設置課程。但是,當我去創建/編輯一個類時,我所得到的只是該名稱的輸入框。

有沒有辦法添加一個可以添加學生作爲班級成員從班級管理頁面的框/字段?我可以製作一個內聯表格,但這是爲了創建新的學生。我已經創建了所有我的學生,並且只是尋找一種快速方法將多個現有學生添加到不同班級中。

+0

沒辦法。在連續搜索google後,我沒有找到解決方案...... – zen11625 2015-06-16 08:38:52

回答

26

這裏是 「自定義窗體」 解決方案,盧克Sneeringer建議。無論如何,我很驚訝,因爲缺乏現成的Django解決方案來解決這個問題(相當自然,也許很常見)。我錯過了什麼嗎?

from django import forms 
from django.db import models 
from django.contrib import admin 

class Foo(models.Model): 
    pass 

class Bar(models.Model): 
    foo = models.ForeignKey(Foo) 

class FooForm(forms.ModelForm): 
    class Meta: 
     model = Foo 

    bars = forms.ModelMultipleChoiceField(queryset=Bar.objects.all()) 

    def __init__(self, *args, **kwargs): 
     super(FooForm, self).__init__(*args, **kwargs) 
     if self.instance: 
      self.fields['bars'].initial = self.instance.bar_set.all() 

    def save(self, *args, **kwargs): 
     # FIXME: 'commit' argument is not handled 
     # TODO: Wrap reassignments into transaction 
     # NOTE: Previously assigned Foos are silently reset 
     instance = super(FooForm, self).save(commit=False) 
     self.fields['bars'].initial.update(foo=None) 
     self.cleaned_data['bars'].update(foo=instance) 
     return instance 

class FooAdmin(admin.ModelAdmin): 
    form = FooForm 
+1

我真的不知道我最終做了什麼來解決這個問題。很確定這是類似的東西。是的,它很奇怪,他們沒有預製/簡單的東西。 – MrGlass 2012-01-11 12:53:11

+1

我喜歡這個解決方案,但是想確定你的意思是「FIXME:'commit'參數是熱處理的」。這裏有什麼問題? – 2012-10-12 20:35:43

+2

爲了與ModelForm API保持一致,foo_form.save(commit = False)應返回尚未保存到數據庫的對象(請參閱https://docs.djangoproject.com/en/dev/topics/forms/ modelforms /#的保存方法); hovewer提供的實現忽略了'commit'參數。很可能你不會使用commit = False;如果是這樣,就沒有問題。 – zag 2012-10-26 22:56:45

29

還有!你想在短暫的InlineModelAdmin(see InlineModelAdmin documentation here)

示例代碼:

class StudentAdminInline(admin.TabularInline): 
    model = Student 

class ClassAdmin(admin.ModelAdmin): 
    inlines = (StudentAdminInline,) 
admin.site.register(Class, ClassAdmin) 
+3

順便說一下,要非常小心地命名模型類「Class」。它確實有用,但它會在以後咬你(例如,在「學生」的第一行)。而且,'class = models.ForeignKey(Class)'*不會工作,因爲「class」是一個保留字。 – 2011-05-17 16:36:50

+0

是的。其實這些都是假的名字:P安全,等等等等等等。實際上,我希望作爲一名大學生找到幫助功課 - 這就像是一項重要任務的標準場景。 – MrGlass 2011-05-17 17:03:41

+8

嘗試執行,這不會做我需要的。正如我在問題中所說的,我知道如何添加內聯表單,但TabularInline旨在創建一個新對象。我只想讓用戶從現有的學生列表中進行選擇。 – MrGlass 2011-05-18 21:11:40