首页 > 解决方案 > 如何安全地覆盖 django.contrib.admin.utils quote() 方法?

问题描述

看起来里面的quote()andunquote()方法django.contrib.admin.utils并不能有效地处理主键中的下划线。具体来说,我有一些字符串类型的主键,cus_C2xVQnht当我使用 django 管理界面通过小铅笔图标编辑它们时,弹出窗口将显示一个错误,例如Customer with ID "cusÂxVQnht" doesn't exist. Perhaps it was deleted?(它将C2转换为代码点00C2,又名Â . 对于其他有效代码点也是如此(00C7、00C6、001B 等)

如果我手动转到客户模型并找到 ID,我可以将其拉起并进行编辑,但当主键中有下划线时,URL 编码似乎无法正常工作。

经过大量挖掘后,我设法找到了这两个深埋在里面的功能django.contrib.admin.utils

def quote(s):
    """
    Ensure that primary key values do not confuse the admin URLs by escaping
    any '/', '_' and ':' and similarly problematic characters.
    Similar to urllib.parse.quote(), except that the quoting is slightly
    different so that it doesn't get automatically unquoted by the Web browser.
    """
    if not isinstance(s, str):
        return s
    res = list(s)
    for i in range(len(res)):
        c = res[i]
        if c in """:/_#?;@&=+$,"[]<>%\n\\""":
            res[i] = '_%02X' % ord(c)
    return ''.join(res)


def unquote(s):
    """Undo the effects of quote(). Based heavily on urllib.parse.unquote()."""
    mychr = chr
    myatoi = int
    list = s.split('_')
    res = [list[0]]
    myappend = res.append
    del list[0]
    for item in list:
        if item[1:2]:
            try:
                myappend(mychr(myatoi(item[:2], 16)) + item[2:])
            except ValueError:
                myappend('_' + item)
        else:
            myappend('_' + item)
    return "".join(res)

它们似乎在管理模板渲染过程中的某个地方被调用,但我无法弄清楚在哪里/多久/所有位置,所以我决定做一个快速的猴子补丁来决定它是否值得作为一个解决方案:我改变了所有的下划线quote()unquote()将除问题字符列表中的下划线以外的所有quote为点...例如:

执行此操作后,管理员可以正常工作,并且似乎附加到相关字段上的编辑图标的链接指向正确的模型实例,因此我可以通过单击铅笔图标来编辑它们,并且不会收到上述错误消息。

尽管如此,我似乎无法找到一种安全地覆盖这两种方法的方法。我真的宁愿不改变主键来消除下划线,因为我的数据库中有很多链接模型,看起来它会变成一个巨大的痛苦。这个修复似乎更容易和更可靠,并且鉴于它在以前版本的 Django 上正常工作,我不认为实施它是一个坏主意。

那么,我怎样才能覆盖这些方法呢?或者,作为一个相关问题,我可以在__str__来缓解这个问题?我会比开始编写覆盖 Django 管理内部的自定义类早得多。如果没有其他解决方案,我需要一些帮助来正确重组我的数据库以调整主键,但我可以说这些键在我正在处理的“旧”站点上完美运行,该站点运行 Django 1.11.6和 Python 2.7.9(与当前的 Django 2.1.1 和 Python 3.6.5 相比)

如果我可以提供更多信息,请告诉我。谢谢!!

标签: pythondjangodjango-admin

解决方案



推荐阅读