Flask/SQLite 和 WTF 表单的日期字段错误
Error in date field with Flask/SQLite and WTF Forms
我有一个烧瓶形式,试图使用 SQLAlchemy 保存到 SQLite 数据库。但是我收到关于数据类型不是 datetime
或 date
格式的错误。
这里是错误:
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')
我有一个烧瓶形式,试图使用 SQLAlchemy 保存到 SQLite 数据库。但是我收到关于数据类型不是 datetime
或 date
格式的错误。
这里是错误:
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')