问题描述
我在sqlalchemy中解码/编码二进制列时遇到问题。我在MSSQL中有数据库,其中表中的主键是二进制。
class Kated(db.Model):
__tablename__ = 'T$KATED'
nrec = db.Column('F$nrec',db.Binary(8),primary_key=True)
abbr = db.Column('F$abbr',db.String(100),nullable=False)
name = db.Column('F$name',db.String(300),nullable=False)
def __repr__(self):
return '<T$KATED %r>' % self.nrec`
我在网页上打印值:
kated = Kated.query.all()
items = []
for el in kated:
items.append({
'nrec': el.nrec,'abbr': el.abbr,'name': el.name
})
return render_template("posts.html",kated=items)
以html
{% for el in kated %}
<div class ="alert alert-info">
<h2>{{ el.abbr }}</h2>
<p>{{ el.name }}</p>
<p>{{ el.nrec }}</p>
<a href="/post_detail?arg1={{el.nrec}}" class="btn btn-warning">Detail</a>
</div>
{% endfor %}
当我打印二进制值时,它看起来像 b'\ x80 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x02'
当我单击“详细信息”按钮时,它会生成请求
http://127.0.0.1:5000/post_detail?arg1=b%27\x80\x00\x00\x00\x00\x00\x00\x02%27
但是当我想按键记录时,值需要编码(否则为类型错误)
@app.route('/post_detail',methods=['GET'])
def post_detail():
arg1=request.args.get('arg1')
nrec1=arg1.encode('utf-8')
print(arg1)
print(nrec1)
print(type(nrec1))
print(nrec1.decode())
kated = Kated.query.get(nrec1)
return render_template("post_detail.html",kated=kated)
结果:
b'\x80\x00\x00\x00\x00\x00\x00\x02'
b"b'\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x02'"
<class 'bytes'>
b'\x80\x00\x00\x00\x00\x00\x00\x02'
没有encode('utf-8')返回错误,并且带有encode('utf-8')的值被修改。
怎么了?
解决方法
我不确定这是否是您的问题的一部分,但是您是否尝试过使用sqlalchemy的sql server data types?
import sqlalchemy as sa
class Kated(db.Model):
__tablename__ = 'T$KATED'
nrec = db.Column('F$nrec',sa.dialects.mssql.BINARY,primary_key=True)
abbr = db.Column('F$abbr',sa.dialects.mssql.STRING(length=100),nullable=False)
name = db.Column('F$name',sa.dialects.mssql.STRING(length=300),nullable=False)
def __repr__(self):
return '<T$KATED %r>' % self.nrec'
,
如果服务器正在接收此请求
http://127.0.0.1:5000/post_detail?arg1=b%27\x80\x00\x00\x00\x00\x00\x00\x02%27
然后似乎有人在输入字符串
"b'\x80\x00\x00\x00\x00\x00\x00\x02'"
转换为浏览器中的文本输入。如果是这样,那么获取字节的最简单方法是在字符串上调用ast.literal_eval。
import ast
@app.route('/post_detail',methods=['GET'])
def post_detail():
arg1 = request.args.get('arg1')
bytes_ = ast.literal_eval(arg1)
在输入中键入字节字面似乎是人类很容易犯错的任务,并且使用ast.literal_eval
是安全的,但有点笨拙。如果用户键入对应于字节的十六进制可能会更好
arg1 = request.args.get('arg1') # '8000000000000002'
bytes_ = bytes.from_hex(arg1) # b'\x80\x00\x00\x00\x00\x00\x00\x02'
他们甚至可以在字节的十六进制之间添加空格:
arg1 = request.args.get('arg1') # '80 00 00 00 00 00 00 02'
bytes_ = bytes.from_hex(arg1) # b'\x80\x00\x00\x00\x00\x00\x00\x02'