Django CreateView с get_success_url не работает для этого конкретного случая - PullRequest
0 голосов
/ 30 октября 2019

Я использую 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 я сначала проверяю форму, а затем создаю объектную кампанию и назначаю всесвязанные данные. Это работает нормально. Проблема возникла, когда я изменил get_success_url, чтобы он соответствовал моему сценарию использования, то есть перенаправляется в представление обновлений. Я отладил и увидел, что в данный момент я создаю переменную valid на form_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

Я предполагаю, что ошибкапотому что кампания еще не создана, поэтому она пытается получить pk от несуществующего объекта.

Дело в том, что я не могу создать кампанию, если форма не проверена, но мне нужна кампания, чтобызаставить работать URL (этот URL работает так же, как и на UpdateView, который у меня уже есть).

1 Ответ

0 голосов
/ 30 октября 2019

Он будет вызывать get_success_url только после form_valid. Так что до form_valid можно создавать и сохранять необходимые объекты. Если они не созданы, вам нужен другой подход. Возможно, инициализируйте (скажем) self.campaign_pk = 0, обновите его, если кампанию можно создать с помощью pk объекта кампании, и позвольте следующему представлению разобраться, что делать, когда pk == 0. Или,

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

(я не полностью следую вашему коду, поэтому я, возможно, лаю не на том дереве)

Возможно, вы не хотите CreateView, ноFormView, который не обрабатывает создание объектов для вас, так что вы можете найти большую гибкость в том, как обрабатывать правильную форму, которая, тем не менее, не может быть полностью соблюдена все времяИли даже просто старое, основанное на функциях представление, в котором вы можете обрабатывать две или более форм и иметь гораздо больше возможностей принимать решения об условиях, которые составляют недействительность, даже после того, как все формы технически проверены.

Это структура представления на основе функций, которую я использовал, когда у меня есть две формы для обработки и довольно длинный, но скучный набор операций, которые нужно выполнить после проверки ОБА форм:

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', ...)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...