2016-07-06 49 views
1

使用GenericStackedInline在Django 1.9 (Python的3.4)我想之前訪問要求對象救了我的模型在Django的管理如何訪問請求對象在Django的GenericStackedInline聯繫

當使用MediaItemAdmin運行obj.save()之前,我可以攔截保存功能,如在這個例子中:

admin.py

class StuffAdmin(admin.ModelAdmin): 
    def save_model(self, request, obj, form, change): 
     # Do some stuff here like obj.user = request.user before saving. 
     obj.save() 

然而,相同的行爲或 '鉤' ISN」 t使用GenericStackedInline可用。這似乎調用模型保存方法直接:

admin.py

class StuffAdmin(GenericStackedInline): 
    model = StuffModel 

    def save_model(self, request, obj, form, change): 
     print("I'm never run :(") 
     obj.save() 

據我瞭解從formGenericStackedInline繼承,所以我使用的形式和覆蓋也嘗試了在這個例子:

admin.py

class StuffAdmin(GenericStackedInline): 
    model = StuffModel 
    form = StuffForm 

class StuffForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     super(StuffForm, self).__init__(*args, **kwargs) 

    def save_model(self, request, obj, form, change): 
     print("Still not run!(") 
     obj.save() 

    def save_form(self, request, obj, form, change): 
     print("Work already!") 
     obj.save() 

我已經搜索過stackoverflow,但大多數都沒有答案,如在這裏看到的accessing request object within a django admin inline model或說用init來做類似self.request = kwargs.pop('request')然而,request永遠不會傳到這裏吧?

無論如何,任何想法如何在模型save()被調用之前調用請求對象並更新我的實例?

回答

1

保存「內聯」的方法是ModelAdmin的一部分,而不是InlineModelAdmin

class BarInline(GenericStackedInline): 
    model = Bar 

class FooModelAdmin(ModelAdmin): 
    model = Foo 
    inlines = [BarInline] 

    def save_formset(self, request, form, formset, change): 
     """ 
     `form` is the base Foo form 
     `formset` is the ("Bar") formset to save 
     `change` is True if you are editing an existing Foo, 
        False if you are creating a new Foo 
     """ 
     if formset_matches_your_inline_or_some_requirement(formset): 
      do_something_with(request) 
     super().save_formset(request, form, formset, change) 

如果你想檢查表單集是否是BarInline的表單集,你可以做這樣的事情:

class BarInline(GenericStackedInline): 
    model = Bar 

    def get_formset(self, *args, **kwargs): 
     formset = super().get_formset(*args, **kwargs) 
     formset.i_come_from_bar_inline = True 
     return formset 


class FooModelAdmin(ModelAdmin): 
    model = Foo 
    inlines = [BarInline] 

    def save_formset(self, request, form, formset, change): 
     if getattr(formset, 'i_come_from_bar_inline', False): 
      do_something_with(request) 
     super().save_formset(request, form, formset, change) 

甚至更​​好,使它通用:

class BarInline(GenericStackedInline): 
    model = Bar 

    def pre_save_formset(self, request, form, model_admin, change): 
     """Do something here with `request`.""" 

class FooModelAdmin(ModelAdmin): 
    model = Foo 
    inlines = [BarInline] 

    def save_formset(self, request, form, formset, change): 
     if hasattr(formset, 'pre_save_formset'): 
      formset.pre_save_formset(request, form, self, change) 
     super().save_formset(request, form, formset, change) 
     if hasattr(formset, 'post_save_formset'): 
      formset.post_save_formset(request, form, self, change) 

如果您需要在每個表單保存之前對請求執行某些操作,而不是在每個表單集之前進行操作,那麼您需要已經使用自己的形式和表單集中通過表單集的形式傳播請求:

from django.forms import ModelForm 
from django.forms.models import BaseInlineFormSet 

class BarForm(ModelForm): 
    model = Bar 

    def __init__(self, *args, **kwargs): 
     request = kwargs.pop('request', None) 
     super().__init__(*args, **kwargs) 
     self.request = request 

    def save(self, commit=True): 
     print(self.request) 
     print(self.instance) 
     obj = super().save(False) # Get object but don't save it 
     do_something_with(self.request, obj) 
     if commit: 
      obj.save() 
      self.save_m2m() 
     return obj 

class BarFormSet(BaseInlineFormSet): 

    @property 
    def request(self): 
     return self._request 

    @request.setter 
    def request(self, request): 
     self._request = request 
     for form in self.forms: 
      form.request = request 

class BarInline(GenericStackedInline): 
    codel = Bar 
    form = BarForm 
    formset = BarFormSet 


class FooModelAdmin(ModelAdmin): 
    inlines = [BarInline] 

    def _create_formsets(self, request, obj, change): 
     formsets, inline_instances = super()._create_formsets(request, obj, change) 
     for formset in formsets: 
      formset.request = request 
     return formsets, inline_instances 

根據您的用例,保存方法也可能只是看起來是這樣的:

class BarForm(ModelForm): 
    model = Bar 

    def save(self, commit=True): 
     do_something_with(self.request, self.instance) 
     return super().save(commit) # Get object but don't save it 
+0

謝謝,我可以看到,我現在使用def save(),但這並沒有得到我的請求對象 – Prometheus

+0

@Prometheus我更新了我的答案 –

+0

我得到錯誤''set_request()缺少1所需的位置參數:'self '''在這行''formset.set_request(request)''那是因爲在這個階段沒有''self'對嗎? – Prometheus

1

管理員類不從表單繼承;他們包括的形式。並且ModelForms沒有save_modelsave_form方法,它們只有一個save方法。覆蓋該方法是完全可能的,但它不接受request;您還需要重寫__init__以接受該參數,並將其從modeladmin的get_form_kwargs方法中傳入。

+0

好的,這是有道理的。你知道''__init__''中的請求參數隱藏在哪裏,它在post.DATA等還是self? – Prometheus

+1

它沒有隱藏在任何地方。您必須在方法簽名中明確接受它,或者從'** kwargs'中獲取它,並將其存儲在實例屬性中。 –

相關問題