我需要在Django模型中存储一些数据。这些数据不等于模型的所有实例。

起初我考虑过继承模型,但我试图保持应用程序的灵活性。如果我使用子类,我每次需要一种新类型的对象时都需要创建一个完整的类,并且这并不好。我最终只会使用很多子类来存储一对额外的字段。

我真的觉得字典是最好的方法,但在Django文档中没有关于在Django模型中存储字典的任何内容(或者我无法找到它)。

任何线索?

有帮助吗?

解决方案

如果它真的是像你想要的任意数据一样的字典,你可以使用一个两级设置,一个模型是一个容器,另一个模型是键值对。您将创建容器的实例,创建每个键值实例,并将键值实例集与容器实例相关联。类似的东西:

class Dicty(models.Model):
    name      = models.CharField(max_length=50)

class KeyVal(models.Model):
    container = models.ForeignKey(Dicty, db_index=True)
    key       = models.CharField(max_length=240, db_index=True)
    value     = models.CharField(max_length=240, db_index=True)

它不漂亮,但它可以让你使用数据库访问/搜索字典的内部,而pickle / serialize解决方案则不会。

其他提示

如果您不需要通过任何这些额外数据进行查询,则可以将其存储为序列化字典。使用 repr 将字典转换为字符串,使用 eval 将字符串转换回字典。请注意字典中没有用户数据,或者使用safe_eval实现。

我通过google的4rth结果来到这篇帖子“django store object”

有点晚了,但 django-picklefield 对我来说似乎是一个很好的解决方案。

doc:

中的示例

要使用,只需在模型中定义一个字段:

>>> from picklefield.fields import PickledObjectField
>>> class SomeObject(models.Model):
>>>     args = PickledObjectField()

并将您喜欢的任何内容(只要它可以选择)分配给该字段:

>>> obj = SomeObject()
>>> obj.args = ['fancy', {'objects': 'inside'}]
>>> obj.save()

另一个干净,快速的解决方案可以在这里找到: https://github.com/bradjasper/django- jsonfield

为方便起见,我复制了简单的说明。

安装

pip install jsonfield

<强>用法

from django.db import models
from jsonfield import JSONField

class MyModel(models.Model):
    json = JSONField()

正如Ned所说,你将无法查询“某些数据”。如果你使用字典方法。

如果你仍然需要存储词典,那么到目前为止,最好的方法是在Marty Alchin的新书 Pro Django 中记录的PickleField类。此方法使用Python类属性仅在需要时对存储在模型字段中的python对象进行pickle / unpickle。

这种方法的基础是使用django的 contibute_to_class 方法,动态地向模型添加新字段,并使用getattr / setattr按需序列化。

我能找到的为数不多的在线示例之一就是 JSONField

我不确定您要解决的问题的性质,但它听起来很奇怪地类似于 Google App Engine的BigTable Expando

Expandos允许您在运行时在数据库支持的对象实例上指定和存储其他字段。引用文档:

import datetime
from google.appengine.ext import db

class Song(db.Expando):
  title = db.StringProperty()

crazy = Song(title='Crazy like a diamond',
             author='Lucy Sky',
             publish_date='yesterday',
             rating=5.0)

crazy.last_minute_note=db.Text('Get a train to the station.')

Google App Engine目前支持Python和Django框架。如果这是表达模型的最佳方式,可能值得研究。

传统的关系数据库模型没有这种列添加灵活性。如果您的数据类型足够简单,您可以打破传统的RDBMS原则,并通过序列化将值破解为单个列,如 @ Ned Batchelder 提出;但是,如果 使用RDBMS,Django模型继承可能就是这样。值得注意的是,它将创建每个派生级别的一个外键关系。

我同意您需要将其他结构化数据填充到单个列中。但是如果你必须这样做,Django有一个 XMLField 集结英寸

Django snipplets还有 JSONField

“不等于模型的所有实例”听起来像是对“无架构数据库”的良好匹配。 CouchDB 是该方法的典型代表,您可能会考虑这一点。

在一个项目中,我移动了几个表格,这些表格从未与Django ORM一起玩到CouchDB,我很满意。我使用 couchdb-python 而没有任何特定于Django的CouchDB模块。可以找到数据模型的描述这里。从五个“模型”的运动在Django到3“模型”在Django和一个CouchDB“数据库”中实际上我的应用程序中的代码总数略有减少。

这个问题很老了,但我遇到了同样的问题,在这里结束了,所选择的答案再也无法解决我的问题。

如果你想在Django或REST Api中存储字典,要么用作前端的对象,要么因为你的数据不一定具有相同的结构,我使用的解决方案可以帮助你。

在API中保存数据时,请使用 json.dump()能够以适当的json格式存储它的方法,如问题

如果您使用此结构,您的数据将已经采用适当的json格式在前端调用 JSON.parse()

仔细考虑,找出每个数据集的共性......然后定义你的模型。它可能需要使用子类。代表共性的外键不可避免,但在有意义时鼓励。

将随机数据填充到SQL表中并不聪明,除非它是真正的非关系数据。如果是这种情况,请定义您的问题,我们也许可以提供帮助。

Django-Geo包含一个“DictionaryField”。你可能会觉得有帮助:

http:/ /code.google.com/p/django-geo/source/browse/trunk/fields.py?r=13#49

通常,如果您不需要跨数据查询,请使用非规范化方法来避免额外查询。用户设置就是一个很好的例子!

如果您使用的是Postgres,则可以使用hstore字段: https://docs.djangoproject.com/en/1.10/ref/contrib/postgres/fields/#hstorefield

我使用textfield和 json.loads() / json.dumps()

models.py

import json
from django.db import models

class Item(models.Model):
    data = models.TextField(blank=True, null=True, default='{}')

    def save(self, *args, **kwargs):
        ## load the current string and
        ## convert string to python dictionary
        data_dict = json.loads(self.data)

        ## do something with the dictionary
        for something in somethings:
            data_dict[something] = some_function(something)

        ## if it is empty, save it back to a '{}' string,
        ## if it is not empty, convert the dictionary back to a json string
        if not data_dict:
            self.data = '{}'
        else:
            self.data = json.dumps(data_dict)


        super(Item, self).save(*args, **kwargs)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top