2013-09-25 66 views
1

我想盡可能地使用CBV,並且希望根據generic.CreateView和通過URL傳入的一些數據預先填充ModelForm中的數據。Django CBV Forms prepopulated foreign key dataset

我可能會過度思考或迷惑自己。所有代碼刪節易讀

我們有PartNumbers(抽象),運營商(PartNumbers的實際實例與位置,序列號和數量編號)的庫存系統和記錄從庫存中提取項目時的移動,多少採取以及它來自哪個Carrier。

我希望在PartNumber詳細信息頁面上有「提取庫存」鏈接,然後將可用載體(pn.carrier_set.all())自動填充到MovementForm的FK下拉列表中。

models.py

class PartNumber(models.Model): 
    name = models.CharField("Description", max_length=100) 
    supplier_part_number = models.CharField(max_length=30, unique=True) 
    slug = models.SlugField(max_length=40, unique=True) 

class Carrier(models.Model): 
    part_numbers = models.ForeignKey(PartNumber) 
    slug = models.SlugField(max_length=10, unique=True, blank=True, editable=False) 
    location = models.ForeignKey(Location) 
    serial_number = models.CharField(max_length=45, unique=True, null=True, blank=True) 
    qty_at_new = models.IntegerField() 
    qty_current = models.IntegerField() 

class Movement(models.Model): 
    carrier = models.ForeignKey(Carrier) 
    date = models.DateField(default=timezone.now()) 
    qty = models.IntegerField() 

我一直get_initial()和get_form_kwargs()玩耍沒有成功:

urls.py我通過URL作爲pn_slug收集PARTNUMBER

url(r'^partnumber/(?P<pn_slug>[-\w]+)/extract/$', views.MovementCreate.as_view(), name='pn_extract'), 

forms.py是通用

class MovementForm(forms.ModelForm): 
    class Meta: 
    model = Movement 

views.py

class MovementCreate(generic.CreateView): 
    form_class = MovementForm 
    model = Movement 

    def get_form_kwargs(self): 
    kwargs = super(MovementCreate, self).get_form_kwargs() 
    kwargs['pn_slug'] = self.request.POST.get("pn_slug") 
    return kwargs 

    # here we get the appropriate part and carrier and. 
    # return it in the form 
    def get_initial(self): 
    initial = super(MovementCreate, self).get_initial() 
    # this didn't work, hence using get_form_kwargs 
    #pn = PartNumber.objects.get(slug=self.request.POST.get("pn_slug")) 
    pn = PartNumber.objects.get(slug=self[pn_slug]) 
    carriers = pn.carrier_set.all() 
    initial['carrier'] = carriers 
    return initial 

既然這樣,我得到「全球名‘pn_slug’沒有定義」的錯誤 - 但我懷疑這個錯誤準確地反映了什麼我做錯了。

我一直在使用這些帖子粗糙準則:

How to subclass django's generic CreateView with initial data?

How do I use CreateView with a ModelForm

+0

我有點困惑你的過程。這個創建形式是用於運動還是表單來創建PartNumber?您將模型設置爲「Movement」,但是您將初始數據設置爲「PartNumber」。 ('pn = PartNumber.objects。得到(slug = self [pn_slug])') – jproffitt

+0

好吧,有兩件事。 --- 1.我從一個部分創建一個運動。從部分,我們得到載體。在MovementCreateView中,我們希望Carrier FK成爲所有運營商的子集(基於PartNumber)。 因此,我們從slug獲得零件對象,然後通過pn.carrier_set.all()獲得可用載體列表,然後將該載體列表發送到Movement的ModelForm。我有這個工作的一個子集 - 我需要在get_initial()中使用pn = PartNumber.objects.get(slug = self.kwargs [「pn_slug」]) – datakid

+0

因此, m尋找一種方式來改變一個窗體中的FK使用的查詢集。 – datakid

回答

1

如果我理解正確,我們的意見,所有你需要的只是改變MovementForm「的查詢集運營商字段設置可用選項。在那種情況下,我會使用get_initialget_form_kwargs。相反,我會做在get_form

def get_form(self, *args, **kwargs): 
    form = super(MovementCreate, self).get_form(*args, **kwargs) 

    pn = PartNumber.objects.get(slug=self.kwargs['pn_slug']) 
    carriers = pn.carrier_set.all() 

    form.fields['carrier'].queryset = carriers 
    return form 

另一種方式來做到這一點是使用get_form_kwargs

def get_form_kwargs(self): 
    kwargs = super(MovementCreate, self).get_form_kwargs() 
    kwargs['pn_slug'] = self.kwargs.get("pn_slug") 
    return kwargs 

然後,在形式的__init__,設置查詢集:

class MovementForm(forms.ModelForm): 
    class Meta: 
    model = Movement 

    def __init__(self, *args, **kwargs): 
     pn_slug = kwargs.pop('pn_slug') 
     super(MovementForm, self).__init__(*args, **kwargs) 

     pn = PartNumber.objects.get(slug=pn_slug) 
     carriers = pn.carrier_set.all() 

     self.fields['carrier'].queryset = carriers 

個人而言,我更喜歡第一種方法,因爲它代碼少。

+0

完美 - 工作一種享受。謝謝@ jproffitt – datakid