How to save form without validation - django

I want that my users can fill a post form partially, save as draft and then edit, finish and publish it. So the draft can have some required (text) fields empty. However I want the fields secure to store in the database (so, no special character, etc).
What's the best (or a good way) way to do this?
I think these solutions:
1) make two different models, one with required=False fields or
2) fill the empty text field with a temporary string ('draft'), then delete it e redraw as needed while edit, publish, save the draft. Or
3) deactivate the validation (novalidation, I'm not sure this works).
or what else?
I'm looking to the second way because the first I think will give me problems to manage two models and the third maybe is not secure.
PS I'm using ajax to call the views.

Related

Saving ModelForm progress values to session in Django

I have flow where users can create (model) forms. If form is valid, object gets saved and flow continues, but selection is in multiple pages. I need to keep current state of created object, which cannot be saved before it's completely valid.
One thing I can do is to always pass things around those views in the ModelForm to make sure, that user never loses data, but I also wanna make sure, that if he leaves the flow and comes back, he doesn't lose data, that he already entered previously.
That's why I decided I wanna save all the fields to session.
Is this correct approach?
How would you do this?
Where would you put this session logic?
What's best way of getting the fields from incomplete form to be saved?
Edit:
Please don't give me advice on how to use session, I am talking more about high level logic and architecture than specific implementation.
I should describe my flow a bit more. Model has 3 fields.
normal dropdown (foreign key referencing another model)
textfield
another foreign key, but this time not done by select, but it's own separate page with lots of filters to help user pick the right (foreign) model
Flow is not linear, because user can start in different parts of page.
Sometimes user can go to page, where he has first 2 fields + button "Browse", which takes you to selection page for 3rd field. Then after he selects field there, he comes back.
But sometimes he selects first this field and then comes to screen with 2 remaining fields, where he needs to fill those.
django-formtools offers a great way to do this using Form wizard.
The form wizard application 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.
More info here https://django-formtools.readthedocs.io/en/latest/wizard.html
to save in session:
request.session["variable_name"] = "value"
to get from session request.session["variable_name"]. sure you can use request.session.get("..") in both too

Flask WTF SelectField with custom entry?

I want to create a SelectField that offers suggestions but still allow the user to enter something else.
class MyForm(Form):
username = wtf.StringField()
title = wtf.SelectField('Job title', choices=['Owner', 'Manager'], validate_choices=False)
WTF documentation suggests that setting validate_choices to False allows this:
Note the validate_choice parameter - by setting this to False we are telling the SelectField to skip the choice validation step and instead to accept any inputted choice without checking to see if it was one of the given choices.
But, no data entry or modification is possible with above. Is this possible or do I need another 'manual entry' field?
Or, is there perhaps a way to show my suggestions in a StringField using JS similar to the way the browsers offer autocomplete suggestions for addresses etc?
I'm not aware of any way to do this. It seems you and I are in a similar position. However, I did have an idea I wanted to share that could work for you.
Many forms will have a dropdown with a value "Other" and if you select "Other" there is another empty box that appears for you to type in. You could implement this pretty easily in wtforms. Alternatively you could have the extra box always display and just do a check that they did indeed select "Other" if they have a custom input.
I have opened an issue, but they are not planning to add this feature.
Based on this, we could, but it is not a pure python implementation

Implement a typeahead for manytomany field

I am looking for a robust solution to implement a typeahead (Twitter typeahead) for a manytomany field. Basically, something identical to the tag input field here in StackOverflow.
The default widget for manytomany is a multiselect. However, since I want the user to provide new values, I need to use a inputText widget. My question is, what would be the best way to implement this functionality so that I can later pass an array of models instances to a cleaning stage?
In my cleaning stage I plan on doing a loop through the elements to check if they exist in the db, create them if they don't and apply validators to each elements.
My initial intuition was to use a hidden field that would receive the actual fields from the typeahead via javascript manipulation. Thus the input field would not be part of the model, just serve as an input box for the user.
Why reinvent the wheel. You can simply use django-taggit together with selectize.js. By using both of them, you don't even need any customization.

Detect which fields change in a Django ModelForm

I have an app where user submitted data needs to go through a verification process before it shows up on the site. At the moment this means they cannot edit the item without removing it from the site (so our admins can check it's okay).
I'd like to write another model where I can store revisions. Basically three fields where I store the date submitted, a boolean saying if the user is ready for that revision to be considered and a third where I store all the changes (as a pickled/JSON dict).
The problem I have at the moment is I don't want to bombard the admins with a complete listing each time. I only want them to see the changed fields. This means I need a way of generating a list of which fields have changed when the user submits the edit ModelForm so I only save this data in the revision.
There are probably several ways of doing this but my post-pub-quiz brain is slightly numb and can't think of the best way. How would you do it?
In terms of where this would go, I'd probably write it as an abstract ModelForm-inheriting class that other forms use. I'd override save() to stop it writing the data directly back to database (I'd want to redirect it through this fancy new revisions model).
Come to think of it, is there an app that already does this generically?

What kind of validations should I use in my db models?

My form validators are pretty good, and if a form passes is_valid, all data should be ok to insert in the db. Should I still validate something on the db model? What else could there be validated on the db side? Because right now, except maybe for uniqueness ( which I can't do from my FormModel ), I can't think of anything else.
EDIT:
I did some work with Rails earlier, and there you would validate a form on the client side, using JS, and on the server side using model validations. I saw in django you can validate on the client side, using JS, and on the server side you have 2 validation checks: forms and models. This is what confused me.
All data should be validated in the database if possible whether you validate from the front end or not. The first validation should be the datatype, for instance using a date datatype will ensure that no nondates can ever get into your database. If you have relationships between tables these absolutely must be enforced at the database level. If the data must be unique, it is irresponsible to not put a unique index on it. If you have a distinct set of values that are the only ones allowed, then put them in a lookup table and add a forign key constraint to that table.
The reason why it is CRITICAL to do validations in the database itself is that the user interface will not be the only thing that interacts with the database (even if you think it will be). Other applications may do so, people will need to make data changes through imports or at a query window (to fix/change large amounts of data such as when client a buys client B and you need to convert all the data to client A). Also if you change the application interface you might lose the some of the critical data integrity checks in the rewrite. Data integrity is one of the most critical factors in database design and maintenance. If you can't count on data integrity, you have no data. I have never seen a database that lets this stuff be handled by the application that didn't lose data integrity over time. Remember the database will far outlast the current application. People will still be looking at this data for years to come. The application typically doesn't consider reporting which is where the data integrity problems tend to come to light. You don't want to have to explain why you have 10,000,000 in orders that you can't identify who they were shipped to, for instance.
If your data has a constraint that's always valid, you should force it in the model/database level (and optionally at the form level). Your DB can be input in multiple ways besides just a form where validation was checked. E.g., someone can go to the django shell to save models directly or someone could create/edit a model in the admin interface or some later designer creates a new form somehow, that doesn't validate correctly.
Granted this is only required if there are additional constraints on the data. Django automatically will validate for things like fields storing proper values, if you are using the correct field types. E.g., IntegerField validates to ensure it contains an integer, EmailField checks that its entered in the form of a valid email address, django.contrib.localflavor.us.models.PhoneNumberField is a US phone number, etc. Note, this only happens if your models have the proper fields (e.g., if you use CharFields for email addresses no validation can be performed.
But there may be other links between data structures, where you should write your own validation. E.g., if all custom orders requiring special instructions (and non-custom orders only sometimes have special instructions), you should check to enforce all custom orders have something in the special instructions field (and maybe have some minimum length).
EDIT: In response to your edit, the reason for three potential validations in django is straightforward -- different validations at different points for different reasons.
Client side (javascript/jquery) validation can't be trusted at all, and should only be given as a convenience for users almost as an afterthought (if you want a spiffy smooth interface). AFAIK, django doesn't have JS validation unless you use an external package like django-ajax-forms or something, but you don't trust that the validation is correct.
Second, there's a difference between form and model validation. One model may have multiple forms for different purposes. For example, you may have a blog with a Comment Model and allow two types of users to comment: signed in users, or anonymous users. The form for anonymous users may require giving a name/email before they comment, while the form for logged in users doesn't need those fields. The signed in user form, when processed in a view may automatically add the correct name and email addresses of the signed in user to the comment model before being saved.
In contrast, model validation always applies and will always be true at the database level, regardless of how they tried saving the data. If you want to make sure some condition always applies make sure it is at the DB level. (And you don't have to write put that validation in at the form level).