Django validate form fields manually - python

I have a form which is dynamically generated. I cannot predict how many text inputs or multiple choices will be included before hand. Thus, I cannot use ModelForm or anything similar.
I wonder if I can leverage the built-in validating code from Django fields and apply them manually somehow, because I can determine the type of user inputs (e.g. whether if it is text, radio button, checkbox, etc.). Something like this would be great:
if type == 'Text':
#perform validation
#get clean data
elif type == 'Checkbox':
#perform validation
#get clean data
UPDATE: My site allows users to generate a survey according to their needs. So for example, an user decides to create a survey with two questions:
what is your name?
what's the brand of your smartphone? A) iPhone B) HTC
The first question is <input type="text"> and the second one is <input type="radio">
The information about what types of questions are generated is stored in the database. So I would have rows like this in the DB to describe the question:
ID TYPE TEXT
1 TEXT What is your name?
2 RADIO what is your name?
When the survey goes online and an user fills it out. I need to validate their input. How can I utilize the built-in validation functionality of Django to deal with this situation?

I'd recommend you using model formsets, as they are here for exactly the reason you've said: dealing with the arbitrary count of fields. And that way you still will be able to use Django's validation (which is very convenient).
If you post a sample form you're dealing with, I would be able to draft a formset example.
Update: Ah, so you need a survey functionality? It's a totally different beast. Then I can't imagine a reason not to leverage one of the existing solutions. The ed-questionnaire
package seems to be the most featured and mature one. And as always with Django, you can relatively easily customize it away.
If I haven't convinced you yet, just take a look at its models.py file. Do you really have the time and will to re-implement all that stuff?

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.

Option to add extra choices in django form

I am trying to create a model via a form that has multiple other models related to it. Say I have a model Publisher, then another model Article with a foreign key to Publisher. When creating a Publisher via a form, I want to create An article at the same time. I know how to do this via formsets. However, I don't know how to add a button that says add extra article at the same view, without having to be redirected to a new page and losing the old data since the form was not saved. What I want is when someone clicks add new article, for a new form for article to appear and for the user to add a new Article. Is this possible to be done in the same view in django, if so can someone give me and idea how to approach this?
I would show code or my attempts, but I am not sure how to even approach it.
This can only be done using JavaScript. The hard part is to have the management form sync up with the number of rows.
But there's two alternatives:
Semi-javascript (Mezzanine's approach): Generate a ton of rows in the formset and only show one empty. Upon the click of the "add another row" button, unhide the next one. This makes it easier to handle the management form as the unfilled extra's don't need any work.
No fix needed: Add as many rows as is humanly sane. In general, people don't need 40 rows, they get bored with filling out the form or worry that all that work is lost when the browser crashes.
Hope this helps you along. Good luck!

what is the best way to approach where next is depending on last step in django?

My concern is i am implementing one application, where i have multiple steps and in each step i have multiple forms. in step one my form two is depending on form one.
Scenario 1:
And inside form one also few questions are there. depending on the answer of questions field should get changed in form.
for example
form 1
Q 1) Are you working?
ans) a) yes b) No
if answer is yes it should display different fields and if no it should display diffident fields.
Scenario 2:
There is a address field in form 1 which i want to use in form 2. It should provide the option to select that address or enter new address.
Please provide me the best approach or available modules which i can use. If any specific name for this terminology please let me know.
Django comes with a Form Wizard that should be used for this kind of task. From the docs, the Form Wizard:
...splits forms across multiple Web pages. It maintains state in one of the backends so that the full server-side processing can be delayed until the submission of the final form.

multiple users and Django

Starting to learn Django, not sure how to deal with multiple users and user types. What I would like to do is have a signin page where users of type A, B or C can log in (or new users can register as type A or B) and depending on their type they are presented with a different site. Furthermore, users of types A and B can actually be organized in groups within their own type and across types. So B1 and B2 may be only assigned to A1 or a group 'GA' which contains members {A2, A1, A3}.
The main goal is to create a site where people can posts question to specific experts or to the general public. When the experts log in they would only be presented to the users assigned to them and if they don't know the answer they could contact other experts or pass the question on to a larger group of experts say GE = {E1, E3, E6}.
There may already be tool out there to do this and I am complete oblivious to it. As of now we're just going to write it from scratch, and Django seemed like a good tool to use.
Any suggestions are helpful.
Sounds like quite the task you have! The first step is to use a Custom User Model, which will take the built-in django user model and allow you to extend it flexibly. I would suggest extending from the AbstractUser.
When you have your user authentication working you can add fields to the users to categorize them how you want.
Your explanation of what you're trying to do after that in the view logic is a little confusing so I'm going to let you figure that part out, but building a custom user model should get you going in the right direction.
It sounds to me that you are building something like a task management system. Where questions are like tasks, and the experts are like the assignees of tasks.
There are two approaches.
APPROACH 1 - use the django authentication system
Suppose you already know how to create users, authenticate them and log them in.
Create user groups and assign permissions to each group (You could either do this through the django admin or through code)
In the views.py, output different contents based on the permission that the logged in user has.
APPROACH 2 - custom build it
Create a Model for User Type and a Model for User (you can either use the default User model or extend it)
Assign each question to a specific User Type.
In the views.py, determine what questions to display based on the User Type of the logged in User.
APPROACH 2 is recommended because it's more flexible and scalable, given that you will extend your programme with more functions in the future.
I think you should have the basic ideas to start with it. Good luck.

Separation of ORM and validation

I use django and I wonder in what cases where model validation should go. There are at least two variants:
Validate in the model's save method and to raise IntegrityError or another exception if business rules were violated
Validate data using forms and built-in clean_* facilities
From one point of view, answer is obvious: one should use form-based validation. It is because ORM is ORM and validation is completely another concept. Take a look at CharField: forms.CharField allows min_length specification, but models.CharField does not.
Ok cool, but what the hell all that validation features are doing in django.db.models? I can specify that CharField can't be blank, I can use EmailField, FileField, SlugField validation of which are performed here, in python, not on RDBMS. Furthermore there is the URLField which checks existance of url involving some really complex logic.
From another side, if I have an entity I want to guarantee that it will not be saved in inconsistent state whether it came from a form or was modified/created by some internal algorithms. I have a model with name field, I expect it should be longer than one character. I have a min_age and a max_age fields also, it makes not much sense if min_age > max_age. So should I check such conditions in save method?
What are the best practices of model validation?
I am not sure if this is best practise but what I do is that I tend to validate both client side and server side before pushing the data to the database. I know it requires a lot more effort but this can be done by setting some values before use and then maintaining them.
You could also try push in size contraints with **kwargs into a validation function that is called before the put() call.
Your two options are two different things.
Form-based validation can be regarded as syntactic validation + convert HTTP request parameters from text to Python types.
Model-based validation can be regarded as semantic validation, sometimes using context not available at the HTTP/form layer.
And of course there is a third layer at the DB where constraints are enforced, and may not be checkable anywhere else because of concurrent requests updating the database (e.g. uniqueness constraints, optimistic locking).
"but what the hell all that validation features are doing in django.db.models? "
One word: Legacy. Early versions of Django had less robust forms and the validation was scattered.
"So should I check such conditions in save method?"
No, you should use a form for all validation.
"What are the best practices of model validation?"*
Use a form for all validation.
"whether it came from a form or was modified/created by some internal algorithms"
What? If your algorithms suffer from psychotic episodes or your programmers are sociopaths, then -- perhaps -- you have to validate internally-generated data.
Otherwise, internally-generated data is -- by definition -- valid. Only user data can be invalid. If you don't trust your software, what's the point of writing it? Are your unit tests broken?
There's an ongoing Google Summer of Code project that aims to bring validation to the Django model layer. You can read more about it in this presentation from the GSoC student (Honza Kral). There's also a github repository with the preliminary code.
Until that code finds its way into a Django release, one recommended approach is to use ModelForms to validate data, even if the source isn't a form. It's described in this blog entry from one of the Django core devs.
DB/Model validation
The data store in database must always be in a certain form/state. For example: required first name, last name, foreign key, unique constraint. This is where the logic of you app resides. No matter where you think the data comes from - it should be "validated" here and an exception raised if the requirements are not met.
Form validation
Data being entered should look right. It is ok if this data is entered differently through some other means (through admin or api calls).
Examples: length of person's name, proper capitalization of the sentence...
Example1: Object has a StartDate and an EndDate. StartDate must always be before EndDate. Where do you validate this? In the model of course! Consider a case when you might be importing data from some other system - you don't want this to go through.
Example2: Password confirmation. You have a field for storing the password in the db. However you display two fields: password1 and password2 on your form. The form, and only the form, is responsible for comparing those two fields to see that they are the same. After form is valid you can safely store the password1 field into the db as the password.

Categories