Opened 4 years ago

Closed 9 months ago

#16174 closed Cleanup/optimization (fixed)

Class based view update for FormPreview

Reported by: ryankask Owned by: ryankask
Component: contrib.formtools Version: 1.3
Severity: Normal Keywords: formpreview, preview
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: yes
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

I used the FormPreview class in django.contrib.formtools.preview for the first time this week. After working with class based views for a while, I really missed methods like get_form for custom form instantiation. Recently, the form wizard machinery (which is much more complex) got a class-based views update (#9200) so I decided to update the FormPreview class as well. It uses django.views.generic.FormView and it's on a Django branch on my Github account. (https://github.com/ryankask/django/blob/cbv-formpreview/django/contrib/formtools/preview.py -- I've also attached a diff based on the Django Github mirror which I am pretty sure is acceptable.

In order to maintain 100% compatibility, there are some issues to note:

  • The original class used get_context whereas the class based views use get_context_data. I've made it so both can be used but if backwards compatibility can be broken, it would be better to only use get_context_data.
  • The original class used __call__ so it could be easily instantiated with a form in a urlconf. I moved the important code to dispatch and __call__ just returns a call to dispatch.
  • The failed_hash method, which isn't documented, falls under a section in the code which says "METHODS SUBCLASSES MIGHT OVERRIDE IF APPROPRIATE." I left the ability to call that method and it just wraps post and sets the current stage to preview.
  • get_initial, process_preview, and security_hash, which all fall under the "override if you need to" section only documented in the code, used to take a request as an argument. They all still do. The methods that were marked "don't touch" now use the instance's request.

If backwards compatibility doesn't need to be maintained, the code can be cleaned up a little more.

Anyway, any comments on the patch would be much appreciated and I'd update the docs if devs think it's okay.

By the way, if none of this is acceptable, the test formtools.PreviewTests.test_form_submit_bad_hash needs to be fixed (it is in my patch). self.client.post('/previewpreview/', self.test_data) results in a 404 so the next assertion that some text isn't in the template passes when it shouldn't.

Attachments (4)

cbv-formpreview0.diff (10.2 KB) - added by ryankask 4 years ago.
cbv-formpreview1.diff (10.4 KB) - added by ryankask 4 years ago.
cbv-formpreview2.diff (10.5 KB) - added by ryankask 4 years ago.
cbv-formpreview3.diff (19.4 KB) - added by ryankask 4 years ago.

Download all attachments as: .zip

Change History (14)

Changed 4 years ago by ryankask

comment:1 Changed 4 years ago by jezdez

  • Needs documentation set
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

comment:2 Changed 4 years ago by AndrewIngram

  • UI/UX unset

I'm wondering whether it's more suitable for this to be implemented as a mixin class that can be easily used with CreateView and UpdateView, eg:

class MyCreateView(CreateView,PreviewMixin):
    pass

Changed 4 years ago by ryankask

comment:3 Changed 4 years ago by ryankask

I've updated the patch to remove the unneeded post override.

A mixin is an interesting idea. The only issue is getting the form_valid methods the play well with each other as those views are based on the ModelFormMixin. I'd love to hear some thoughts on that.

Changed 4 years ago by ryankask

comment:4 Changed 4 years ago by ryankask

I've updated the patch again. Because our site needs it now, I've created a package for it if anyone is interested (django-cbv-formpreview - https://github.com/ryankask/django-cbv-formpreview).

I will write improved documentation this weekend.

Changed 4 years ago by ryankask

comment:5 Changed 4 years ago by ryankask

I've updated the docs.

The basic question is does backwards compatibility need to be maintained? And if so, to what extent.

comment:6 Changed 4 years ago by ryankask

The more I use this in production, the more I realize that backwards compatibility would need to break. For example, the done method takes cleaned_data but it would be much better if it took the form object itself so you could, for example, call save.

I am going to break backwards compatibility in my fork (django-cbv-formpreview - https://github.com/ryankask/django-cbv-formpreview) and see where that takes me.

comment:7 Changed 4 years ago by jacob

  • milestone 1.4 deleted

Milestone 1.4 deleted

comment:8 Changed 4 years ago by jezdez

  • Patch needs improvement set

FWIW, I think we should consider providing a class based form preview view that has the ability to take advantage of as much class based views API as possible. In that sense it's possible to introduce it without keeping in line with the previously shipped form preview feature. The simplest way to do this is to ship it next to the current implementation like we are going to do with the form wizard. Deprecation of the current form preview would start as soon as the new class based form preview is included.

comment:9 Changed 4 years ago by ryankask

That approach is definitely best.

I think some sort of mixin as AndrewIngram mentioned would be ideal although it depends on what you mean by "as much class based views API as possible."

My initial thoughts are thoughts are that a mixin would be a bit brittle because its post method would always need to be resolved first with respect to the inheritance tree.

Another option would be to replace the ProcessFormView and provide new bases for the create, update, and delete views in the new form preview package.

If you mean the underlying API and not providing easy previews for the existing views in edit.py, perhaps the current form preview functionality could be replaced using the new form wizard machinery.

Maybe I'm just not thinking outside the box ;) Unfortunately I've been swamped at work so I haven't been able to get around to working on this as soon as I had hoped to. Hopefully I will find some time soon.

Last edited 4 years ago by ryankask (previous) (diff)

comment:10 Changed 9 months ago by gchp

  • Resolution set to fixed
  • Status changed from new to closed

formtools has been extracted into its own repository (​​​https://github.com/django/django-formtools/). Because of this, the issue tracking for this package has been moved to GitHub issues. I'm going to close this ticket, but I've created a GitHub issue to replace it where the conversation can continue: ​​​https://github.com/django/django-formtools/issues/19. Thanks!

Note: See TracTickets for help on using tickets.
Back to Top