【问题标题】:Python sqlalchemy encode/decode binary key in MSSQLPython sqlalchemy 在 MSSQL 中编码/解码二进制密钥
【发布时间】:2020-12-10 13:49:16
【问题描述】:

我在 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')的值被修改。

怎么了?

【问题讨论】:

  • 看起来arg1是字节对象的字符串化reprstr(b'\xnn\xnn')的结果。你可以通过调用ast.literal_eval(arg1)来解决这个问题,但如果客户端会更好正确编码数据(urlencoding 或 base64)。
  • 你能说得更详细些吗?我是 Python 的大三学生。谢谢。
  • 我尝试使用 urllib。 Arg1 看起来像二进制,但它是一个 str,我不知道如何处理它。
  • 你能不能edit这个问题来显示传入请求是如何创建的?
  • 我按照你说的编辑了问题。感谢您的帮助!

标签: python sql-server sqlalchemy flask-sqlalchemy encode


【解决方案1】:

我不确定这是否是您的问题的一部分,但是您是否尝试过使用 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'

【讨论】:

  • 谢谢你很匹配,但结果是一样的
【解决方案2】:

如果服务器正在接收这个请求

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 的使用是安全的,但有点 hacky。如果用户输入与字节对应的十六进制可能会更好

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'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 2014-08-09
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多