Я работаю над созданием проекта форумов Django, и у меня есть приложение «настройки», которое обращается к базе данных для таблицы, называемой настройками.

Таблица настроена со столбцами verbose_name, name и value. Первое - это просто имя, которое будет отображаться для администраторов, второе - это имя, к которому осуществляется доступ к настройке (и это первичный ключ в таблице.)

Теперь у меня есть некоторые настройки, которые являются логическими, некоторые из которых являются целыми числами, а некоторые являются строковыми. Однако value является типом TEXT в базе данных, поэтому Django возвращает его в виде строки. Прямо сейчас у меня есть эта реализация для преобразования логических значений в логический тип Python:

class SettingsMiddleware:
    def process_request(self, request):
        request.settings = {}
        settings = Setting.objects.all()

        for setting in settings:
            if setting.value == ("True" or "1"):
                setting.value = True
            if setting.value == ("False" or "0"):
                setting.value = False

            request.settings[setting.name] = setting.value

        return None

Итак, у меня есть два вопроса:

  1. Есть ли лучший способ сделать это?
  2. Как я могу определить, содержит ли строка целое число? Я знаю, что могу преобразовать его в целое число с int(), если оно допустимо, но как я могу определить, действительно ли он действителен?

Очевидно, что в отношении вопроса номер два, я бы удалил биты «1» и «или» 0 текущей оценки.

0
John M. 1 Фев 2013 в 19:52

3 ответа

Лучший ответ

Мне кажется, что ast.literal_eval может быть полезным тебе.

>>> import  ast
>>> ast.literal_eval("1")
1
>>> ast.literal_eval("0")
0
>>> ast.literal_eval("True")
True
>>> ast.literal_eval("False")
False
>>> ast.literal_eval("'foobar'")
'foobar'
>>> ast.literal_eval("1.2")
1.2
>>> ast.literal_eval("1.2e3")
1200.0
>>> ast.literal_eval("1,2")
(1, 2)
>>> ast.literal_eval("[1,2]")
[1, 2]
>>> ast.literal_eval("[1,2,(1,2)]")
[1, 2, (1, 2)]
>>> ast.literal_eval("1f")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/ast.py", line 49, in literal_eval
    node_or_string = parse(node_or_string, mode='eval')
  File "/usr/local/lib/python2.7/ast.py", line 37, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
  File "<unknown>", line 1
    1f
     ^
SyntaxError: unexpected EOF while parsing
2
mgilson 1 Фев 2013 в 15:59

Если вы хотите ограничить его до 0,1, True, False, я бы сделал

boolmapping = {'0':False, 'False': False, '1':True, 'True':True}
...
setting = boolmapping.get(setting, setting)

Однако это может ошибочно преобразовать целое число, равное 1, в значение True, если в действительности имелось значение 1, поэтому лучше сопоставить «1» с 1, а не True.

Чтобы преобразовать строку в int, если она одна, выполните

try:
    setting = int(setting)
except ValueError:
    pass
1
Martin v. Löwis 1 Фев 2013 в 16:01

Вы можете просто использовать:

if setting.value in ["true", "True", 1, "1"]:
    setting.value = True
0
Lukasz Koziara 1 Фев 2013 в 16:01