我正在使用一个不太简单的数据库构建一个相对简单的Flask应用程序。我有很多模型可以处理和关联数据库中所有必需的信息。
由于某种原因,我遇到标题错误。
我开始考虑与我的数据库模型/关系有什么联系。
因此,模型的实现如下:
from app import db, login
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
import datetime
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
password = db.Column(db.String(128))
def set_password(self, password):
self.password = generate_password_hash(password)
def check_password(self, passwd):
return check_password_hash(self.password, passwd)
def __repr__(self):
return '<User {}>'.format(self.username)
class airFeedVariator(db.Model):
variatorID = db.Column(db.Integer, db.ForeignKey('variator.id',onupdate='RESTRICT',ondelete='RESTRICT'), primary_key=True)
airFeedID = db.Column(db.Integer, db.ForeignKey('air_feed.id',onupdate='RESTRICT',ondelete='RESTRICT'), primary_key=True)
variatorRel = db.relationship('Variator', backref='variators',lazy='joined')
freq = db.Column(db.Integer)
class Variator(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(30))
machineID = db.Column(db.Integer)
baudrate = db.Column(db.Integer)
addedAt = db.Column(db.DateTime, default=datetime.datetime.utcnow) # the current timestamp
class Air_feed(db.Model):
id = db.Column(db.Integer, primary_key=True)
timeOn = db.Column(db.Integer)
timeOff = db.Column(db.Integer)
desc = db.Column(db.String)
digital = db.relationship('Pin_function', backref='analog_or_digital', lazy=True)
airFeedTypeId = db.relationship('Air_feed_type', backref='air_feed_type_id', lazy=True, uselist=False) #This allow the usage for a single element. 1-1 Rel.
#variators = db.relationship('Variator', secondary=airFeedVariator, lazy='subquery',backref=backref('airfeedvariators', lazy=True))
variators = db.relationship('airFeedVariator', lazy='dynamic')
表格如下:
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField, IntegerField, DateTimeField
from wtforms.validators import ValidationError, DataRequired, Email, EqualTo
from flask_babel import lazy_gettext as _l #compile in runtime only.
#Utilizado para converter directamente os modelos em forms.
#from wtforms_alchemy import ModelForm
from app import models
from wtforms_alchemy import model_form_factory
BaseModelForm = model_form_factory(FlaskForm)
class ModelForm(BaseModelForm):
@classmethod
def get_session(self):
print('Session: ', db.session)
return db.session
class LoginForm(FlaskForm):
username = StringField(_l('Utilizador'), validators=[DataRequired()])
password = PasswordField(_l('Password'), validators=[DataRequired()])
remember_me = BooleanField(_l('Lembrar-me'))
submit = SubmitField(_l('Submeter'))
class RegistrationForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
password2 = PasswordField(
'Repetir Password', validators=[DataRequired(), EqualTo('password')])
submit = SubmitField(l_('Registo'))
#Validate on submit check for this. The rise allow to write a message directly on the webpage!
def validate_username(self, username):
user = models.User.query.filter_by(username=username.data).first()
if user is not None:
raise ValidationError(_l('Utilizador já existente!'))
def validate_email(self, email):
user = models.User.query.filter_by(email=email.data).first()
if user is not None:
raise ValidationError(_l('Email já existente!'))
class VariatorForm(FlaskForm):
name = StringField(_l('Nome'), validators=[DataRequired()])
machineID = IntegerField(_l('Identificador'), validators=[DataRequired()])
baudrate = IntegerField(_l('Valocidade Comm'), validators=[DataRequired()])
addedAt = DateTimeField(_l('Preenchimento automatico')) # the current timestamp
def validate_machineID(self, machineID):
user = models.Variator.query.filter_by(machineID=machineID.data).first()
if user is not None:
raise ValidationError(_l('Já existente um variador registado neste endereço!'))
我确实意识到我只是在测试其他的FlaskForm表单和ModelForm。
我的问题如下:
File "c:\app\routes.py", line 49, in SaveVariator
db.session.add(var) File "c:\gburner\lib\site-packages\sqlalchemy\orm\scoping.py", line 153, in do
return getattr(self.registry(), name)(*args, **kwargs) File "c:\gburner\lib\site-packages\sqlalchemy\orm\session.py", line 1833, in add
raise exc.UnmappedInstanceError(instance) sqlalchemy.orm.exc.UnmappedInstanceError: Class 'app.forms.VariatorForm' is not mapped
*添加了Problatic route.py部分*
@app.route('/savevariator', methods=['POST'])
def SaveVariator():
var = VariatorForm(request.form)
if var.validate_on_submit():
print('Variator form submit accepted!')
### I was doing this ### Trying to add the FORM to the session!
db.session.add(var)
db.session.commit()
#############################
### INSTEAD I Should be doing this: ######
variator = Variator(name=var.name, machineID=var.machineID, baudrate=var.baudrate)
db.session.add(variator)
db.session.commit()
##############################
resp = jsonify(success=True)
else:
print('Variator form submit NOT accepted!')
resp = jsonify(success=False)
return resp
我认为html代码不是必需的,因为一切正常,直到调用将信息保存到数据库的那一刻。
我是否缺少有关数据库中映射关系的信息,因为我有3个多对多关系表?
任何帮助解决问题的人将不胜感激。 谢谢。
*编辑* 感谢Joost为我指出了这个简单而又难以实现的观点! (我可能应该更频繁地暂停)。
答案 0 :(得分:0)
问题出在路线部分:
@app.route('/savevariator', methods=['POST'])
def SaveVariator():
var = VariatorForm(request.form)
if var.validate_on_submit():
print('Variator form submit accepted!')
### I was doing this ### Trying to add the FORM to the session!
db.session.add(var)
db.session.commit()
#############################
### INSTEAD I Should be doing this: ######
variator = Variator(name=var.name, machineID=var.machineID, baudrate=var.baudrate)
db.session.add(variator)
db.session.commit()
##############################
resp = jsonify(success=True)
else:
print('Variator form submit NOT accepted!')
resp = jsonify(success=False)
return resp
感谢Joost,我能够理解问题出在哪里。再次感谢!
我意识到这是一个简单的错误,但是我找不到关于该错误和解决方案的太多信息。但是,如果管理员认为不值得保留它,请随时将其删除。
谢谢。