3
votes

I have the following class:

class Cloaker(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  domain = db.Column(db.String(32), unique=True, nullable=False, info={
    'description': 'Raw Domain Only (no www). i.e. hello.com',
    'validators': raw_domain_validator,
  })

(Note the unique=True for domain)

With a form generated by WTForm:

class CloakerForm(ModelForm):
  class Meta:
    model = Cloaker

I have the following code which handles CRUD for this model:

@cloaker_bp.route('/new/', methods=['GET', 'POST'])
@cloaker_bp.route('/<cloaker_id>/', methods=['GET', 'POST'])
def cloaker(cloaker_id=None):
  cloaker = Cloaker.query.get(cloaker_id) if cloaker_id else Cloaker()
  if request.method == 'GET':
    form = CloakerForm(obj=cloaker)
    form.populate_obj(cloaker)
  else:
    form = CloakerForm(request.form)
    if form.validate():
      form.populate_obj(cloaker)
      db.session.add(cloaker)
      db.session.commit()
      return redirect(url_for('.list_cloakers'))

  return render_template('cloaker/single.html', form=form, cloaker=cloaker)

When I update an object, I am consistently getting Already exists. for domain.

When I follow Using unique validator with existing objects on wtforms-alchemy's website:

  ...(from the CRUD view)... 
  else:
    form = CloakerForm(obj=cloaker)
    #form = CloakerForm(request.form)
    form.populate_obj(cloaker)
    if form.validate():
      db.session.add(cloaker)
      db.session.commit()

I am getting This field is required. for domain. I don't understand how WTForms-Alchemy is getting their data from request.form if I follow their recommendations.

How can I get unique=True to work with my views?

2

2 Answers

0
votes

Was having the "already exists" problem on POST/UPDATE as well. But the doc's solution did help in my case:

obj = MyModel.query.get(1) form = MyForm(obj=obj) form.populate_obj(obj) form.validate()

Thanks, because this question helped me find the section in the docs.

0
votes

With WTForms-Alchemy version 0.17.0 I've found that if I do

 record = MyModel.query.filter(MyModel.id = <some valid number>).one()

And then when request.method == 'POST'

 my_form = MyModelForm(request.form, obj=record)
 

Providing both the request.form and obj param addresses the Unique validator and gets around the required field BUT still allows updates.