Flask/SQLite 和 WTF 表单的日期字段错误

Error in date field with Flask/SQLite and WTF Forms

我有一个烧瓶形式,试图使用 SQLAlchemy 保存到 SQLite 数据库。但是我收到关于数据类型不是 datetimedate 格式的错误。

这里是错误:

sqlalchemy.exc.StatementError: (builtins.TypeError) SQLite Date type only accepts Python date objects as input.
[SQL: UPDATE draw SET modified_on=?, draw_date=? WHERE draw.id = ?]
[parameters: [{'draw_date': (datetime.date(2020, 2, 10),), 'modified_on': datetime.datetime(2020, 10, 2, 19, 20, 24, 594698), 'draw_id': 1}]]

我的routes.py中设置的modified_on值是正常的python。正在从 WTF 表单中检索 draw_date 字段。

我认为问题是 draw_date 值周围有一组额外的括号?所以 'draw_date': (datetime.date(2020, 2, 10),), 实际上应该是 'draw_date': datetime.date(2020, 2, 10),

但我看不出这是从哪里来的。在我的路线中,如果我输入(form.draw_date.data),它会告诉我它是一个日期时间对象。

这是我的路线:

@app.route('/organization/<orgid>/draw/<id>', methods=['GET', 'POST'])
@login_required
def draw_edit(orgid, id):

    draw = Draw.query.filter_by(id=id).first_or_404()
    drawform = DrawForm(draw.name, obj=draw)

    if drawform.validate_on_submit():

        app.logger.debug(drawform.draw_date.data, type(drawform))

        draw.name = drawform.name.data
        draw.draw_date = drawform.draw_date.data,
        draw.modified_by = current_user.id
        draw.modified_on = datetime.utcnow()
        draw.total_tickets = drawform.total_tickets.data
        draw.tickets_start_at = drawform.tickets_start_at.data
        draw.ticket_price = drawform.ticket_price.data
        draw.draw_status = drawform.draw_status.data
        db.session.commit()
        flash('Changes Saved')

    tickets = Ticket.query.filter_by(draw_id=id).all()
    return render_template("draw_edit.jinja", title='Setup Draw', id=id,
                           draw=draw, drawform=drawform,
                           tickets=tickets,
                           )

这是我的表格

class DrawForm(FlaskForm):

    name = StringField("Name", validators=[DataRequired(), Length(min=0, max=100)],
                       description="Provide a descriptive name for this draw.")
    draw_date = DateField('Draw Date', format="%Y-%m-%d")
    total_tickets = IntegerField(
        "Number of Tickets", validators=[DataRequired()],
        description="Total number of tickets being sold in this fund raiser?")
    tickets_start_at = IntegerField(
        "First number of first ticket", validators=[DataRequired()],
        description="What is the first number in the series of tickets?")
    ticket_price = FloatField(
        "Individual Ticket Price", validators=[DataRequired()],
        description="Individual ticket price for one ticket purchased")
    draw_status = SelectField("Draw Status",
                              choices=[('draft', 'Draft'),
                                       ('sales', 'Sales'),
                                       ('scheduled', 'Scheduled'),
                                       ('finished', 'Finished')
                                       ],
                              validators=[DataRequired()])
    save_draw = SubmitField('Save Draw')

    def __init__(self, original_name, *args, **kwargs):
        super(DrawForm, self).__init__(*args, **kwargs)
        self.original_name = original_name

    def validate_name(self, name):
        app.logger.info(self.original_name)
        app.logger.info(self.name.data)
        if name.data != self.original_name:
            name = Draw.query.filter_by(name=name.data).first()
            if name is not None:
                raise ValidationError(
                    'Please use a different fundraiser name, this name is already used')

模特

class Draw(Base):
    name = db.Column(db.String(100), index=True, unique=True)
    org_id = db.Column(db.Integer, db.ForeignKey(
        'organization.id'), index=True)
    draw_date = db.Column(db.Date)
    total_tickets = db.Column(db.Integer)
    tickets_start_at = db.Column(db.Integer)
    ticket_price = db.Column(db.Float)
    draw_status = db.Column(db.String(20))
    created_by = db.Column(db.Integer, db.ForeignKey('user.id'))
    modified_by = db.Column(db.Integer, db.ForeignKey('user.id'))

    prizes = db.relationship('Prize', backref='draw', lazy=True)
    tickets = db.relationship('Ticket', backref='draw', lazy=True)
    organization = db.relationship('Organization', backref='draws', lazy=True)
    sponsors = db.relationship(
        'Sponsor', foreign_keys='Sponsor.draw_id', backref='draw', lazy=True)

    def __repr__(self):
        return f"<Draw {self.name} [{self.id}] {self.draw_date} >"

以及 Jinja/HTML

的片段
   <form method="POST"">
        {{ drawform.csrf_token }}
        {% if drawform.errors %}
            {{ drawform.errors }}
        {% endif %}

        <div class="form-group form-row">
            <div class="input-group col-8">
                {{ drawform.name.label(for="name") }}
                {{ drawform.name(class="form-control",
                    placeholder='Name of the Draw') }}
            </div>
            <div class="input-group col-2">
                {{ drawform.draw_date.label(for="draw_date") }}
                {{ drawform.draw_date(class="form-control", type="date",
                    min="2020-01-01", max="2022-12-31",
                    placeholder='Date of the Draw') }}
            </div>
        </div>

作业后有一个逗号 draw.draw_date = drawform.draw_date.data,。这会将分配的值转换为您提到的元组 draw.draw_date = drawform.draw_date.data。删除逗号,它应该可以工作。

    draw.name = drawform.name.data
    draw.draw_date = drawform.draw_date.data,  # There is a comma here
    # This will make draw_date a tuple like (datetime.date(2020, 2, 10),)
    draw.modified_by = current_user.id
    draw.modified_on = datetime.utcnow()
    draw.total_tickets = drawform.total_tickets.data
    draw.tickets_start_at = drawform.tickets_start_at.data
    draw.ticket_price = drawform.ticket_price.data
    draw.draw_status = drawform.draw_status.data
    db.session.commit()
    flash('Changes Saved')