Как можно безопасно переопределить метод quote () django.contrib.admin.utils? - PullRequest
0 голосов
/ 09 октября 2018

Похоже, что методы 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 и т. Д.)

Если я вручную перейду к модели клиентов и найду идентификатор, то смогу его просто отредактировать и отредактировать, но кажется, что кодировка 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 в точках ... например:

  • '_%02X' в quote() становится '.%02X'
  • split('_') в unquote()становится split('.')
  • myappend('_' + item) в unquote() становится myappend('.' + item)

После этого администратор работает правильно, и кажется, что ссылки, прикрепленные к значкам редактирования насвязанные поля относятся к правильным экземплярам модели, поэтому я могу отредактировать их, щелкнув значки карандаша, и не получить сообщение об ошибке, указанное выше.

Все, что сказано, не могу найтиспособ безопасно переопределить эти два метода.Я действительно не хотел бы менять первичные ключи, чтобы исключить подчеркивания , потому что в моей базе данных много связанных моделей, и кажется, что это станет огромной болью.Это исправление кажется намного проще и надежнее, и, учитывая, что оно работало должным образом в предыдущих версиях Django, я не понимаю, как это плохая идея для реализации.

Итак, как я могу переопределить эти методы? Или, как связанный вопрос, есть ли что-то, что я могу сделать в __str__ методах моих моделей, чтобы облегчить эту проблему?Я бы сделал это гораздо раньше, чем начал бы писать пользовательские классы, которые переопределяли бы внутренности администратора Django.Если нет другого решения, мне потребуется некоторая помощь в правильной реструктуризации базы данных для настройки первичных ключей, но я могу сказать, что эти ключи отлично работают на «старом» сайте, на котором я работаю, на котором работает Django 1.11.6и Python 2.7.9 (по сравнению с текущими Django 2.1.1 и Python 3.6.5)

Пожалуйста, дайте мне знать, если я могу предоставить больше информации.Спасибо !!

1 Ответ

0 голосов
/ 05 мая 2019

Это исправлено в Django 2.2.Смотри https://github.com/django/django/commit/e4df8e6dc021fa472fa77f9b835db74810184748

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...