簡體   English   中英

Django CreateView with get_success_url 不適用於此特定情況

[英]Django CreateView with get_success_url not working for this specific case

我正在使用 Django 2.1。 我在使用 CreateView 時遇到問題,因為我需要重定向到更新 url,但是 url 包含一個在驗證表單有效后手動創建的參數。

這是視圖代碼:

class ProjectCreateInvestmentCampaignView(LoginRequiredMixin, SuccessMessageMixin, generic.CreateView):
    template_name = 'webplatform/project_edit_investment_campaign.html'
    model = InvestmentCampaign
    form_class = CreateInvestmentCampaignForm
    success_message = 'Investment campaign created!'

    def get_success_url(self):
        return reverse_lazy('project-update-investment-campaign',
                            args=(self.kwargs['pk'], self.object.campaign.pk, self.object.pk))

    def form_valid(self, form):
        project = Project.objects.get(pk=self.kwargs['pk'])
        form.instance.investment_type = "A"
        form.instance.contract_type = "CI"
        form.instance.history_change_reason = 'Investment campaign created'
        valid = super(ProjectCreateInvestmentCampaignView, self).form_valid(form)
        if valid:
            campaign = CampaignBase.objects.create(project=project, )
            form.instance.campaign = campaign
            form.instance.campaign.project = project
            form.instance.campaign.creation_date = timezone.now()
            form.save()
        return valid

如您所見,在form_valid上,我首先驗證表單,然后創建 object 活動並分配所有相關數據。 這工作正常。 當我更改get_success_url以適合我的用例時出現問題,即重定向到更新視圖。 我調試並看到,當我在form_valid上創建變量valid時,它會檢查 url 是否成功,這會觸發我以下錯誤:

Exception Type: AttributeError
Exception Value:    
'NoneType' object has no attribute 'pk'
Exception Location: /Volumes/Archivos/work/i4b/webplatform/views/investor_campaign_views.py in get_success_url, line 25

我認為錯誤是因為尚未創建活動,因此它試圖從不存在的 object 獲取pk

問題是,如果表單未經驗證,我無法創建活動,但我需要活動來使 url 工作(url 正在工作,因為它在我已經擁有的UpdateView上工作)。

它只會在get_success_url之后調用form_valid 因此,由form_valid創建和保存所需的對象。 如果不創建它們是有效的,那么您需要一種不同的方法。 也許初始化(比如說) self.campaign_pk = 0 ,如果可以使用活動 object 的 pk 創建活動,則更新它,然后讓下一個視圖理清 pk==0 時該怎么做。 或者,

...
    args=(self.kwargs['pk'], 
          self.object.campaign.pk if self.object.campaign else 0, 
          self.object.pk))

(我沒有完全遵循你的代碼,所以我可能會在這里吠叫錯誤的樹)

可能您不想要CreateView而是FormView ,它不會為您處理 object 創建,因此您可能會發現如何處理無法始終完全兌現的有效表單具有更大的靈活性。 甚至,只是一個普通的基於函數的舊視圖,您可以在其中處理兩個或多個 forms,並且即使在所有 forms 都經過技術驗證之后,也更有能力決定構成無效的條件。

這是我使用的基於函數的視圖結構,其中我有兩個 forms 需要處理,並且在兩個 forms 驗證之后要做一組相當長但無聊的操作:

def receive_view( request):

    # let's put form instantiation in one place not two, and reverse the usual test. This
    # makes for a much nicer layout with actions not sandwiched by "boilerplate" 
    # note any([ ]) forces invocation of both .is_valid() methods 
    # so errors in second form get shown even in presence of errors in first

    args = [request.POST, ] if request.method == "POST" else []
    batchform = CreateUncWaferBatchForm( *args, layout=CreateUncWaferBatchLayout )
    po_form =  CreateUncWaferPOForm(     *args, layout = CreateUncWaferPOLayout, prefix='po')
    if request.method != "POST" or any(  
        [ not batchform.is_valid(), not po_form.is_valid() ]):

        return render(request, 'wafers/receive_uncoated.html',   # can get this out of the way at the top
            {'batchform': batchform,  
            'po_form': po_form, 
        })

    #it's a POST, everything is valid, do the work
    ...
    return redirect('appname:viewname', ...)

對我來說, get_success_url沒有被調用,因為表單無效( invalid )而且我不知道。 您可以覆蓋form_invalid(self, form)來控制行為。

此外,請考慮使用此代碼塊來顯示模板中的任何錯誤

{% if form.errors %}
<div class="alert alert-danger" role="alert">
    {% for field, errors in form.errors.items %}
    {% for error in errors %}
    <b>{{ field }}</b>: {{ error }}
    {% endfor %}
    {% endfor %}
</div>
{% endif %}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM