Вопрос

I am building an API endpoint, that receives only changed fields. Other fields are fetched from existing object. Below is simplified version of my code.

from wtforms import Form
from wtforms.fields import StringField

class User(object):
    first_name = ""
    last_name = ""

class UpdateForm(Form):
    first_name = StringField()
    last_name = StringField()

user = User()
user.first_name = 'First name'
user.last_name = 'Last name'
form = UpdateForm(formdata=None, data={'first_name':'Edited'}, obj=user)

I want form.data to be: {'first_name': 'Edited', 'last_name': 'Last name'}.

Instead I get: {'first_name': 'First name', 'last_name': 'Last name'}

Это было полезно?

Решение

I think you are coming at this backwards. The form is just a representation of the HTTP form as submitted by the user. You want to use it to stop malformed form submissions from getting bound into the models of your api classes. The way to do this not to manage the modified attributes in your form, but in the model your form is trying to protect.

In the example below we are using WTForms to protect the model User. The Form object will have what ever the user supplied in their POST the User model will represent valid data that was retrieved from storage. We want to prevent the POST from added malformed data in the currently valid model. If the submitted data passes validation we want to overwrite properties in the model with the data we now now to be valid. This implies that only one of three scenarios can occur. The two simple ones are either the supplied fields are valid or not. If one or more fields are not valid then you fail the submission. The third is a little more complicated and requires you to make a decision in your api. If a field is omitted you need to decide wether None is ignored or you want to overwrite the associated property with None. The point is that whether or not a property was edited or stayed the same is irrelevant. The only real question is whether or not its valid.

The example below demonstrates how this should work:

from wtforms import Form
from wtforms.fields import StringField

class User(object):
    first_name = ""
    last_name = ""

class UpdateForm(Form):
    first_name = StringField()
    last_name = StringField()

data = {'first_name':'EDITED'}

form = UpdateForm(obj=Struct(**data))

# this is for the purpose of creating 
# an existing user. We assume you are
# considering getting this out of a db
user = User()
user.first_name = 'OLD First name'
user.last_name = 'OLD Last name'

if form.data.get('first_name'):
    user.first_name = form.data.get('first_name')

if form.data.get('last_name'):
    user.last_name = form.data.get('last_name')

This results in the following. If the property isn't supplied the old value sticks. If it is supplied and its the same it will just overwrite the existing property to no effect. If the property has been edited and is valid then the new value will overwrite the old one.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top