如何安全地覆盖Django.contrib.admin管理员.utils quote()方法?

2024-05-04 00:44:03 发布

您现在位置:Python中文网/ 问答频道 /正文

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

如果我手动转到customers模型并找到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)

它们似乎是在管理模板呈现过程中的某个地方调用的,但我不知道在何处/多久调用一次/所有位置,因此,我决定做一个快速的monkey补丁来决定它是否值得作为一个解决方案:我将quote()unquote()中的所有下划线都改为点,除了quote中问题字符列表中的一个…例如:

  • ^quote()中的{}变成'.%02X'
  • ^unquote()中的{}变成split('.')
  • ^unquote()中的{}变成myappend('.' + item)

在这样做之后,管理员工作正常,并且似乎附加到相关字段上的编辑图标的链接指向正确的模型实例,因此我可以通过单击铅笔图标来编辑它们,而不会得到上面提到的错误消息。你知道吗

尽管如此,我似乎找不到安全地覆盖这两种方法的方法。我真的不想更改主键来消除下划线,因为我的数据库中有很多链接模型,看起来这将是一个巨大的痛苦。这个修复看起来更简单、更可靠,而且考虑到它在Django以前的版本上正常工作,我不认为实现它是个坏主意。你知道吗

那么,我如何重写这些方法?或者,作为一个相关的问题,我是否可以在我的模型的__str__方法中做些什么来缓解这个问题?我要比开始编写覆盖Django管理内部的自定义类快得多。如果没有其他解决方案,我将需要一些帮助来正确地重组数据库以调整主键,但我可以说,这些键在我正在工作的“旧”站点上运行得非常好,该站点运行Django 1.11.6和Python 2.7.9(与当前的Django 2.1.1和Python 3.6.5相比)

请让我知道如果我可以提供更多的信息。谢谢您!!你知道吗


Tags: thedjango方法模型编辑adminresitem