Max
Max

Reputation: 2475

WTF - jumbles forms value

I am using WTForms with flask and store data to Sql-Alchemy database. Evrything seems to be in right place. I have a models.py, forms.py, views.py and html document and raises no error. The only thing is that when I submit the data everything mixes up, more precisely the form value jumbles and swaps with other. Here is the error:

sqlalchemy.exc.StatementError
StatementError: SQLite DateTime type only accepts Python datetime and date objects
as input. (original cause: TypeError: SQLite DateTime type only accepts Python datetime 
and date objects as input.) 'INSERT INTO menu (title, title_eng, alias, menu_type, 
ordering, check_out_time, access, published, content, content_eng, image) 
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' [{'content': u'url/folder/image.jpg', 
'title_eng': u'Home', 'title': u'\u0413\u043b\u0430\u0432\u043d\u0430\u044f', 
'ordering': 1, 'menu_type': u'simple', 'content_eng': u'asd', 
'access': datetime.date(1990, 1, 17), 'alias': u'home', 'image': u'asd', 
'published': u'1', 'check_out_time': u'public'}]

However instead of the above stament there must be like the bellow:

sqlalchemy.exc.StatementError
StatementError: SQLite DateTime type only accepts Python datetime and date objects
as input. (original cause: TypeError: SQLite DateTime type only accepts Python datetime 
and date objects as input.) 'INSERT INTO menu (title, title_eng, alias, menu_type, 
ordering, check_out_time, access, published, content, content_eng, image) 
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' [{'content': u'asd', 
'title_eng': u'Home', 'title': u'\u0413\u043b\u0430\u0432\u043d\u0430\u044f', 
'ordering': 1, 'menu_type': u'simple', 'content_eng': u'asd', 
'access': u'public', 'alias': u'home', 'image': u'url/folder/image.jpg',
'published': u'1', 'check_out_time': datetime.date(1990, 1, 17)}]

as you might noticed there are 4 variables which data are swaped. content and image and the other is access and check_out_time

can you please tell me what is the issue?

here is my models.py:

class Menu(db.Model):
"""Menu is used for websites navigation titles.
eg. Home/About Us/Blog/Contacts/and etc""" 

id          = db.Column(db.Integer, primary_key = True)
title       = db.Column(db.String(255))
title_eng   = db.Column(db.String(255))
alias       = db.Column(db.String(255))
menu_type   = db.Column(db.String(10))
#menu type: simple, blog, gallery, contacts, products
ordering    = db.Column(db.SmallInteger, default = '1')
check_out_time = db.Column(db.DateTime)
access      = db.Column(db.String(30))
#access: user, reductor, manager, administrator 
published   = db.Column(db.SmallInteger, default = '1')
content     = db.Column(db.String)
content_eng = db.Column(db.String)
image       = db.Column(db.String(350))

def __init__(self, title, title_eng, alias, 
        menu_type, ordering, check_out_time, access,
        published, content, content_eng,
        image, metakey, metades):
    self.title = title
    self.title_eng = title_eng
    self.alias = alias
    self.menu_type = menu_type
    self.ordering = ordering
    self.check_out_time = check_out_time
    self.access = access
    self.published = published
    self.content = content
    self.content_eng = content_eng
    self.image = image
    self.metakey = metakey
    self.metades = metades

here is views.py:

@admin.route('/manage/add_menu', methods = ['GET', 'POST'])
@login_required
def add_menu(parent = ''):
    form = Add_menu_form()

    if form.validate_on_submit():
        new_menu = Menu(
            form.title.data,
            form.title_eng.data,
            form.alias.data,
            form.menu_type.data,
            form.ordering.data,
            form.access.data,
            form.check_out_time.data,
            form.published.data,
            form.image.data,
            form.content.data,
            form.content_eng.data,
            form.metakey.data,
            form.metades.data)

        db.session.add(new_menu)
        db.session.commit()

        flash('New menu was added successfully.')   
        return redirect(url_for('cabinet.manage', current = 'menu_settings'))
    return render_template('admin/manage/site_figuration/add_menu.html',
        title = 'Internet market',
        parent = parent,
        form = form)

here is my forms.py:

class Add_menu_form(Form):
    """Add_menu_form is used to add/edit menu"""
    title = TextField('Title', [validators.Length(min=1, max=250), validators.Required()])
    title_eng = TextField('Title in English', [validators.Length(min=1, max=250), validators.Required()])
    alias = TextField('Alias')
    ordering = IntegerField('Order')
    check_out_time = DateField('Date of publication')
    content = TextAreaField('Content', [validators.Required()])
    content_eng = TextAreaField('Content in English', [validators.Required()] )
    image = TextField('Heading image')
    metakey = TextAreaField('Meta keywords')
    metades = TextAreaField('Meta description')
    menu_type = SelectField('Menu type', 
                choices=[('simple', u'обычное'),
                        ('blog', u'блог'),
                        ('products', u'продукция'),
                        ('gallery', u'галерея')])
    access = SelectField('Access', 
                choices=[('public', u'открытый'),
                        ('registered', u'для зарегистрированных'),
                        ('admin', u'для администратора')])
    published = SelectField('Published', 
                choices=[('1', u'да'),
                        ('0', u'нет')])

and html document:

<form action="" method="post" name="add_menu">
            <table class="table">
                <tr>
                    {{ form.hidden_tag() }}
                    <td>Название меню</td>
                    <td>{{ form.title }}</td>
                </tr>
                <tr>
                    <td>Название меню на английском </td>
                    <td>{{ form.title_eng}}</td>
                </tr>
                <tr>
                    <td>Короткое название</td>
                    <td>{{ form.alias}}</td>
                </tr>
                <tr>
                    <td>Тип меню</td>
                    <td>{{form.menu_type}}</td>
                </tr>
                <tr>
                    <td>Позиция</td>
                    <td>{{form.ordering}}</td>
                </tr>
                <tr>
                    <td>Дата публикации</td>
                    <td>{{form.check_out_time}}</td>
                </tr>
                <tr>
                    <td>Доступ</td>
                    <td>{{form.access}}</td>
                </tr>
                <tr>
                    <td>Опубликовать</td>
                    <td>{{form.published}}</td>
                </tr>
                <tr>
                    <td>Заглавная картинка</td>
                    <td>{{form.image}}</td>
                </tr>
                <tr>
                    <td>Содержание</td>
                    <td>{{form.content}}</td>
                </tr>
                <tr>
                    <td>Содержание на английском</td>
                    <td>{{form.content_eng}}</td>
                </tr>
                <tr>
                    <td>HTML описание</td>
                    <td>{{form.metades}}</td>
                </tr>
                <tr>
                    <td>HTML ключевые слова </td>
                    <td>{{form.metakey}}</td>
                </tr>
                <tr>
                    <td></td>
                    <td><input type="submit" name="submit" value="добавить меню" class="btn btn-default"/>
                        <a href="{{ url_for('cabinet.manage', current='menu_settings') }}" class="btn btn-default">cancel</a></td>
                </tr>
            </table>
        </form>

Upvotes: 0

Views: 291

Answers (2)

Sean Vieira
Sean Vieira

Reputation: 159955

Rather than manually mapping fields, if the names of the fields are the same (between Menu and Add_menu_form) you can just use wtforms.Forms#populate_obj method to update an existing object. Remove your custom __init__ method from your Menu model (class Menu(db.Model)) and then you can do this:

if form.validate_on_submit():
    new_menu = Menu()
    form.populate_obj(new_menu)

    db.session.add(new_menu)
    db.session.commit()

Upvotes: 3

okoboko
okoboko

Reputation: 4482

You'll want to check/confirm that the ordering is maintained in the new_menu variable.

In other words, ensure that the order of items is the same when you pass new_menu in the line db.session.add(new_menu).

Upvotes: 1

Related Questions