Django автоматически сжимает поле модели при сохранении () и распаковывает при доступе к полю - PullRequest
3 голосов
/ 31 марта 2010

Учитывая модель Django Likeo:

from django.db import models

class MyModel(models.Model):
    textfield = models.TextField()

Как можно автоматически сжимать textfield (например, с помощью zlib) на save() и распаковывать его при обращении к свойству textfield (т. Е. Не при загрузке) с помощью рабочего процесса, подобного это:


m = MyModel()
textfield = "Hello, world, how are you?"
m.save() # compress textfield on save
m.textfield # no decompression
id = m.id()

m = MyModel.get(pk=id) # textfield still compressed
m.textfield # textfield decompressed

Я был бы склонен думать, что вы перегружаете MyModel.save, но я не знаю шаблон для изменения элемента по месту при сохранении. Я также не знаю лучшего способа распаковки в Django, когда к полю обращаются (перегрузка __getattr__?).

Или лучший способ сделать это - иметь тип настраиваемого поля ?

Я уверен, что я видел пример почти точно этого, но, увы, я не смог найти его в последнее время.

Спасибо за чтение & ndash; и для любого ввода вы можете предоставить.

Ответы [ 4 ]

2 голосов
/ 04 апреля 2010

Вам необходимо внедрить to_python и get_prep_value в свой тип настраиваемого поля, чтобы соответственно распаковать и сжать данные.

2 голосов
/ 31 марта 2010

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

1 голос
/ 20 мая 2010
0 голосов
/ 04 мая 2016

Также см. https://djangosnippets.org/snippets/2014/ Кажется, немного проще ... Все еще только TextField под капотом.

class CompressedTextField(models.TextField):
    """
    model Fields for storing text in a compressed format (bz2 by default)
    """
    __metaclass__ = models.SubfieldBase

    def to_python(self, value):
        if not value:
            return value

        try:
            return value.decode('base64').decode('bz2').decode('utf-8')
        except Exception:
            return value

    def get_prep_value(self, value):
        if not value:
            return value

        try:
            value.decode('base64')
            return value
        except Exception:
            try:
                tmp = value.encode('utf-8').encode('bz2').encode('base64')
            except Exception:
                return value
            else:
                if len(tmp) > len(value):
                    return value

                return tmp
...