Wtforms: Best way to split a form across multiple pages? - python

I'm dynamically generating a form using WTForms with Flask (based off of a custom form schema), which I'd like to split for UX reasons over multiple pages / refreshes. I'm trying to figure out what is the best way to achieve this. My current thinking is the following options:
Set all not rendered questions to hidden widgets and somehow handle any validation on them.
Reimplement / steal django's form wizard and dynamic section up the form into many smaller forms.
I'm going to have to add some sort of concept of sections into the Meta of the form class to handle the layout abstraction but I'm perplexed as to which of the two options (or others I haven't thought of) might be the best way to achieve the web UX?
If these were hard coded forms, I'd just have one form per page and handle the interim logic in the view, but I need to be able to dynamically generate them unfortunately.

You're trying too hard to make HTTP into a stateful protocol when it was designed to be a stateless protocol
Your best bet is to hide the fact that there are two steps from the server. Just show two different pages to the user and keep the input values in memory until you have all of them and can send them to the server.
You haven't said which technology you're using for the UX btw, but this is a classic HTTP problem which is best solved on the frontend.

Related

Best Practice: Processing complex dynamic form on single-page with Django

I'm looking for the most pythonic way to handle a complex form on a single-page. My "submit" page has a series of questions that, based on the user's input, will generate different forms/fields.
A simplified example:
--- Shift 1 --> Form #1
--- Yes -- What shift? -- |
| --- Shift 2 --> Form #2
|
Enter Date --- Did you work? ---|
|
| --- Yes --> Form #3
--- No -- Was this PTO? ---|
--- No --> Form #4
I'm trying to figure out most efficient/pythonic way to handle the above.
Possible Approaches:
Lots of jquery, ajax, and function based views. This is my current setup, but I'd like to move it to CBV and ModelForms if possible because my current code is about 2000 lines (with 10+ ajax functions, 10+ view-handling urls, and too many input fields to count) within my template/models/views just to load/process this form. It is a complete nightmare to maintain.
Single page with ModelForms embedded within a dynamic div. The form page calls a jquery load depending on your answers to the questions. For instance, if you answered "Today", "Yes", "Shift 1", I would call $("#form-embed").load("/forms/form1/") which contains the Form #1 ModelForm. A couple problems with this: 1. Some of the "questions" are actually form fields, and if I'm reloading a blank form, then that field would be blank. I could solve this with JS on the front-end or custom cleaning on the back-end, but this ends up being a lot of code as well. And 2. Form POSTing and error handling would be pretty complex with so many potential forms on one page.
Same as above but with an Iframe. This solves some of the above issues, but feels "icky" for some reason and makes me worry about responsive UI/compatibility across platforms.
Multiple pages, each with its own form. This eliminates the convenience of a single-page approach, which I'd really like to keep if possible.
Combine all my models into a single model. This gets pretty complex pretty quickly because the actual fields involved on each form are very different, and the logic handling would therefore get messy and bloated.
Create a new single model with a corresponding modelform for use only with this form that contains all possible fields, dynamically displayed via JS based on user input, then routes the fields to the appropriate models after submission.
Don't use modelforms, instead create my own custom Form Class that involves all possible fields, then route to the appropriate models after submission. Use JS to display/hide fields based on user input.
Is there an approach I'm missing, or is one of these the best? These would all theoretically work just fine, but none of them feels very pythonic. #7 maybe feels like the best option, but I'm still not super happy with it.
My hope for the front-end is to maximize ModelForm and Django's template management, while minimizing JS. My hope for the back-end is to maximize CBV/ModelForm customization while minimizing FBV. My overall goal is to reduce code volume and improve maintainability/modification.
Looks like the functionality I was looking for is the class-based view FormView and forms.Form (not forms.ModelFormView).
In forms.py, I created a forms.Form form which contained all possible fields (ended up being about 10, able to reuse several. Had to make a lot of them required=False), then loaded them all at the same time in individual divs within a FormView. Each div shared the name of the field, so I could easily hide/show each div using simple JS depending on what combination of fields I wanted to display based on user input.
I also included a hidden "form number" field which updates based on the final input, which helps to direct my form validation.
I then used the def clean(self) mixin in my forms.py to process each individual form.
Haven't finished the entire thing yet, but it's already looking like my code length will be cut from 2000+ down to a couple hundred or so. Plus this will be much easier to maintain, and keeps most of my logic on the serverside rather than in the html file.

What would be the most efficient way of creating charts/graphs with data from a Django backend

I built an application using Django and I was wondering what would the most efficient way of creating charts and graphs for my data (for personal viewing). I was thinking of having the charts/graphs in a dashboard with the ability to create and delete records in the database(perhaps in a different tab). Originally I was thinking of having this in the Django admin panel since I already use it a lot for looking at/deleting/creating small data. I researched various custom django admin libraries but a lot of them just seems like a UI improvement. Another small feature that I wanted was to regroup various models in different applications into one listing as opposed to the default layout where the main heading is the various django application and under each is the models for the application.
I have a couple ideas about how to go about doing this:
Create custom django admin template for what I need. This would include graphs/charts but I'm not sure about the regrouping.
Maybe create a front-end application to do the graphs and make the groupings myself. This would communicate to the backend via GET/POST/DELETE requests. I would write something in the backend to transform the data into JSON and return that. This options seems like a lot more work but I feel like it would be more flexible for my needs
Use a library. However, I haven't been able to find one that fits what I'm looking for.
Overall I'm looking for something that looks/performs like a dashboard but has the functionality of the django admin panel where i can create/modify/delete records at will.
Any help and/or recommendations would be appreciated.
From python/serverside perspective there are various ploting librarys such as matplotlib that can generate svg graphics. You could make them interactive by sending new request to the server.
If you rather want something on the client side (D3.js) for example:D3.js with Django

Django Multi-site with shared database

I am about to develop multiple sites for different real estate companies. All share the same html, sections, etc. The difference is in the content, specially the properties... But some of those properties can be shared among the rest of the companies.
I am thinking in sharing the same database and differentiate content using the url. In this way I can use only one project instead of one for each company.
Does anyone have recommendations for this kind of projects?
Thanks,
I have done that.
Was it a good idea? Yes, in my case it was. I had to reuse the same content and when we changed the content, it had to be changed on all pages. On a simple site, a triple deploy and changing the content in three different projects is kind of overkill. But whereas it works fine in a simple front-end page (that hardly even requires Django), I do not recommend it for "real" web apps.
What will break? Think about the things that your pages will share and see if it's a problem.
1) I'm guessing that if you'll want to have user login capability on the page (besides the admin login), then that's a problem, if I can use the same user for different companies that have no apparent connection whatsoever. You could be in for a lot of trouble if the companies find out that user private details aren't as private as they thought. And the same goes for the users who really don't have a clue how they ended up with a user account on a page they've never visited.
2) URLs. You can't have different ones for each company without some extra hacking. If one of the companies wants to have /about/ and the other one /company/ page, you're gonna start hacking a bad solution that will blow up in your face when the companies ask for the next page.
3) Anything else you might want to have on your page that is connected to hardcoded data or database values. I.e. social authentication etc.
What can you do about it?
If I was hellbound on solving the first one, here's what I would do:
- Override the user model and add info about the registering page
- Create custom managers for user model for each page
- Write a middleware that only lets you use the page-specific manager for the current request
All in all, I wouldn't do it in a million years. Way too hacky, way too vulnerable. Just create separate databases.
For solving the second one, you can create a multi-host middleware that checks from which domain the request comes from and returns the correct URL config. Sth similar to this . It's not really hard to rewrite and modify to your needs.
It's impossible to decide for you, but I've given you something to think about before going one way or the other. Good luck!

Django - Managing page content in Django Admin

I'm new to working with Django and am developing for a client who wants to be able to change page content in the Django Admin. They need to be able to change the html of the index page without editing the files on the server.
I know about flatfiles but I'm not sure that's completely what I'm after as I can't display stuff such as Django forms for example.
EDIT: Kind of like how a CMS works but without the users/group stuff and be able to use Django View modules such as forms.
Any advice?
Thanks
Honestly, the scope of what you're looking for is too huge to cover in this format. There's a number of ways this could be done, but they're all going to require some work and customization based on the client's needs.
Flatpages could work if you allow HTML content and make sure the content is rendered as "safe" in the template. This really only covers the "content" area of the site, though. It wouldn't be wise to use flatpages for an entire site template, including header, sidebar, footer, etc.
You could create editable areas. So, you actually create models for things like headers, sidebars, footers, and modules within those areas, and then just pull them into the template as needed. Then, the client is only editing pieces of the template instead of responsible for the whole HTML document.
Forms are going to be a challenge, because they require backend-processing that requires a connected view. The client won't be able to just arbitrarily drop in some form code and have a form. But, you could use a third-party service form forms and just embed them in the available content regions. Or, there's a couple of django apps that try to implement a type of "form builder" in the admin. That might somehow let the client add a form via something like the shortcodes used in Wordpress, but you'd likely have to lay down some infrastructure to make that work.
At a certain point, stuff like this reaches a point of diminishing returns, though. The only way to allow total customization of the template is to drop down into the actual physical file and make changes there. You can make certain things easier for the client, but ultimately, they either need to scale back their customization needs or deal with the fact that they'll have to work with the filesystem.
I don't believe that is possible at this time. Of course you can edit your models but templates, I think not.
I would find out how much they need to change? If they plan a complete redesign every week then you're still looking for an answer. If they just need a dynamic front page then you can split it up into variables and let them edit sections of html. Much safer and less prone to breaking the html.

Cleanest design pattern for displaying form data and validation errors?

In real-life applications, if I use a form framework, I inevitably end up fighting it at some point.
I'm interested in best practice patterns for building forms in a website. Reference to implementations in any language would be a bonus (I usually work in Python). I'm particularly interested in the problem of creating / displaying the forms to the end user.
Here's how I see the subject. Most parts of the form workflow can be handled with relatively lightweight components that I can pull out of frameworks like formencode and formish. By "most parts" I mean decoding submitted form data into a sensible data structure (e.g. repeated fields in the form should become lists in Python); marshalling the values into the types that we want (e.g. an "age" field should become an integer); and validating the values (e.g. "age must not be blank").
The bit I end up fighting is making and displaying the forms themselves. Many frameworks (e.g. FormAlchemy) tightly couple their schemas, validation and models to some kind of form widget generation scheme, which I don't like.
The tasks involved in making a form are:
Making dynamic widgets (e.g. a select list with values from a database)
Looping over repeating fieldsets (e.g. a list of name, age pairs that each represent a person)
Embedding existing values in the form fields (from a data structure)
Displaying validation errors next to form fields or at the top of the page
The options I see for doing this are:
generate, based on widgets that are defined in the schema (e.g. Django)
post-process forms, by applying a data structure containing errors and values to an HTML template (e.g. htmlfill)
accept that for all but the simplest cases, you may as well start from the beginning by encoding the logic (loops, error display, etc) manually in each of your form templates
Are there any other patterns for handling the problem? What are the pros and cons of each?
The frameworks (Python) I've looked at / had pointed out so far are: flatland, formencode, FormAlchemy, formish, WTForms, Django forms, web2py, deform, FormConvert and web.py
Update: I've not really got very far with answering the question about best practise for building forms, but I've made the decision with my current project to go for deform / colander, which is a sane way of handling serialisation etc, but more importantly is well-documented and well-tested. I am going to avoid form generation at all for all but the simplest forms.
You can try django. It has forms module, that provides many useful mechanisms for web forms.
There's also web.py's Form class which you may find interesting. There are examples in its cookbook.
You might check out web2py, which provides several mechanisms for generating and processing forms (see also form-related Javascript and Ajax functionality). Its form objects (and other HTML helper objects) are server-side representations of the HTML DOM and can be manipulated prior to serialization into HTML (see ref1, ref2, ref3, ref4). If you have further questions about it, ask on the mailing list.
I have recently used flatland to handle a complex form and found it to be very flexible. There's no widgets library, but it has a powerful HTML generator/filter, and as pointed out in the documentation, it's quite simple to write your own widgets. Don't let the "0.0.2" version fool you, the library is quite mature and stable.
A panel featuring several form library authors was presented at PyCon 2010, which might be relevant to your question:
http://www.pycon.tv/video/184/
have you seen Bruno's django-floppyforms? It doesn't answer your question but it's worth being aware of it being done.

Categories