Python, как создать экземпляр класса из класса, хранящегося в базе данных? - PullRequest
2 голосов
/ 19 сентября 2010

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

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

РЕДАКТИРОВАТЬ: В ответ на идею злонамеренного __init__ в классе, это только для таких вещей, как формы или модели, где это тесноконтролируемый посредством проверки того, что происходит в классе, никогда не будет __init__ в классе, и было бы в принципе невозможно, так как я проверял бы все на стороне сервера, чтобы поместить что-нибудь вредоносное в класс.

Ответы [ 2 ]

5 голосов
/ 19 сентября 2010

Не храните код в базе данных !!!

Представьте себе класс с вредоносным методом __init__, который находит путь в вашем «хранилище классов» в базе данных.Это означает, что тот, кто имеет доступ на запись к этим таблицам базы данных, может прочитать любой файл с вашего веб-сервера и даже обработать его файловую систему, поскольку у него есть возможность выполнять любой код Python на нем.

2 голосов
/ 19 сентября 2010

Не храните сам класс, сохраняйте путь импорта в виде строки в базе данных (например, 'django.forms.CharField')

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

helpers.py

def get_class_from_concrete_classpath(class_path):
    # Unicode will throw errors in the __import__ (at least in 2.6)
    class_path = str(class_path)

    mod_list = class_path.split('.')
    module_path = '.'.join(mod_list[:-1])
    class_name = mod_list[-1]

    base_mod = __import__(module_path, fromlist=[class_name,])
    return getattr(base_mod, class_name)


def get_concrete_name_of_class(klass):
    """Given a class return the concrete name of the class.

    klass - The reference to the class we're interested in.

    Raises a `TypeError` if klass is not a class.
    """

    if not isinstance(klass, (type, ClassType)):
        raise TypeError('The klass argument must be a class. Got type %s; %s' %
                        (type(klass), klass))

    return '%s.%s' % (klass.__module__, klass.__name__)

fields.py

class ClassFormField(forms.Field):
    def to_python(self, value):
        return get_concrete_name_of_class(value)

class ClassField(models.CharField):
    __metaclass__ = models.SubfieldBase

    """Field used for storing a class as a string for later retrieval"""

    MAX_LENGTH = 255
    default_error_messages = {
        'invalid': _(u'Enter a valid class variable.'),
    }

    def __init__(self, *args, **kwargs):
        kwargs['max_length'] = kwargs.get('max_length', ClassField.MAX_LENGTH)
        super(ClassField, self).__init__(*args, **kwargs)

    def get_prep_value(self, value):
        if isinstance(value, (basestring, NoneType)):
            return value

        return get_concrete_name_of_class(value)


    def to_python(self, value):
        if isinstance(value, basestring):
            return get_class_from_concrete_classpath(value)

        return value

    def formfield(self, **kwargs):    
        defaults = {'form_class' : ClassFormField}
        defaults.update(kwargs)
    return super(ClassField, self).formfield(**defaults)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...