Django 在 save() 上自动压缩模型字段,并在访问字段时自动解压缩

发布于 2024-08-27 10:05:52 字数 964 浏览 7 评论 0原文

给定一个像这样的 Django 模型:

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__ ?)。

或者更好的方法是使用 自定义字段类型

我确信我见过一个几乎完全一样的例子,但可惜我最近找不到它。

感谢您的阅读 - 以及您能够提供的任何意见。

Given a Django model likeso:

from django.db import models

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

How can one automatically compress textfield (e.g. with zlib) on save() and decompress it when the property textfield is accessed (i.e. not on load), with a workflow like this:


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

I'd be inclined to think that you would overload MyModel.save, but I don't know the pattern for in-place modification of the element when saving. I also don't know the best way in Django to decompress when the field when it's accessed (overload __getattr__?).

Or would a better way to do this be to have a custom field type?

I'm certain I've seen an example of almost exactly this, but alas I've not been able to find it recently.

Thank you for reading – and for any input you may be able to provide.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

如梦 2024-09-03 10:05:52

您需要实现 to_python 和 get_prep_value 在您的自定义字段中输入分别解压缩和压缩数据。

You need to implement to_python and get_prep_value in your custom field type to respectively decompress and compress your data.

无法言说的痛 2024-09-03 10:05:52

自定义字段类型绝对是这里的最佳选择。这是确保字段在保存时压缩并在加载时解压缩的唯一可靠方法。确保按照链接中的描述设置元类。

Custom field types are definitely the way to go here. This is the only reliable way to ensure that the field is compressed on save and decompressed on load. Make sure you set the metaclass as described in your link.

沉溺在你眼里的海 2024-09-03 10:05:52

我想值得一提的是,PostgreSQL 默认压缩所有字符串类型: Text Compression in PostgreSQL

所以也许答案是:不?

I guess it's worth mentioning that PostgreSQL compresses by default for all string types: Text compression in PostgreSQL

So maybe the answer is: Don't?

雄赳赳气昂昂 2024-09-03 10:05:52

另请参阅 https://djangosnippets.org/snippets/2014/
看起来更容易一些......仍然只是引擎盖下的一个文本字段。

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

Also see https://djangosnippets.org/snippets/2014/
Seems a bit easier... Still just a TextField under the hood.

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文