0

I tried to implement a cancel button via a mixin, but fail to get the correct URL. I want to go back to the page before the CreateView if the user presses "cancel" - if that should fail, I want the user to end up in index.

views.py:

class CancelButtonMixin(object):
    def post(self, request, *args, **kwargs):
        if "cancel" in request.POST:
            if request.META.get('HTTP_REFERER') != None:
                url = request.META.get('HTTP_REFERER' , '/')
            else:
                url = reverse_lazy("index/")
            return redirect(url)
        else:
            return super(CancelButtonMixin, self).post(request, *args, **kwargs)


class SomeCreateView(CancelButtonMixin, CreateView):
    model = SomeModel
    template_name ="projectname/some_update.html"
    form_class = SomeFormsetName
    success_url = reverse_lazy('index/')

forms.py:

class SomeFormsetName(ModelForm):
    required_css_class = "required"
    
    class Meta:
        model = SomeModel
        fields = ("one", "two", "three", "four")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.helper = FormHelper()
        self.helper.form_method = 'POST' 
        self.helper.layout = Layout(Row(Column(Field('one')),
                                        Column(Field('two', css_class='form-control')),
                                        css_class='form-row'),
                                    Submit('submit', 'Save', css_class='btn-primary'),
                                    Submit('cancel', 'Cancel', css_class='btn-secondary', formnovalidate='formnovalidate'),
                                    Field("three", type="hidden"),
                                    Field("four", type="hidden"))

my problem is that the url parameter holds exactly the url I am at, not the one from the previous page. How can I correct this behavior? url in my example will refer to http://127.0.0.1:8000/some_update/2

xtlc
  • 1,070
  • 1
  • 15
  • 41
  • [This post](https://stackoverflow.com/questions/12758786/redirect-return-to-same-previous-page-in-django) might be useful, though I don't see that it uses mixins. – Rekamanon Jul 27 '20 at 14:42
  • Thing is, I want to go to the page BEFORE the CreateView and my question is, if there is a built in method I did not find yet, or if I have to store that information in a hidden field to go back. – xtlc Jul 27 '20 at 18:03

1 Answers1

0

I am not sure I am happy with my solution, so what I did now is to save the previous page in a hidden argument of the form and retrieve it upon clicking "cancel". Here is my code, maybe someone else wants to comment on it or use it:

forms.py:

class SomeFormsetName(ModelForm):
    required_css_class = "required"
    
    class Meta:
        model = SomeModel
        fields = ("one", "two", "three", "four")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.helper = FormHelper()
        self.helper.form_method = 'POST' 
        self.helper.layout = Layout(Row(Column(Field('one')),
                                        Column(Field('two', css_class='form-control')),
                                        css_class='form-row'),
                                    Submit('submit', 'Save', css_class='btn-primary'),
                                    Submit('cancel', 'Cancel', css_class='btn-secondary', formnovalidate='formnovalidate'),
                                    Field("three", type="hidden"),
                                    Field("four", type="hidden"))

views.py:

class CancelButtonMixin(object):
    """ 
    save url in hidden form variable ("previous_page")
    retrieve it with request._get_post()["previous_page"]
    """
    def post(self, request, *args, **kwargs):
        if "cancel" in request.POST:
            if request.META.get('HTTP_REFERER') != None:
                url = request._get_post()["previous_page"]
            else:
                url = reverse("index/")
            return HttpResponseRedirect(url)
        else:
            return super(CancelButtonMixin, self).post(request, *args, **kwargs)


class SomeCreateView(CancelButtonMixin, CreateView):
    model = SomeModel
    template_name ="projectname/some_update.html"
    form_class = SomeFormsetName
    success_url = reverse_lazy('index/')

    def get_initial(self):
        return {"previous_page": "/PREV_PAGE_NAME/"+str(self.kwargs["PREV_PAGE_pk"]),}

Replace PREV_PAGE with whatever your urls.py has as an entry. I think the code in the get_initial could be nicer though.

xtlc
  • 1,070
  • 1
  • 15
  • 41