web-dev-qa-db-ja.com

Djangoデータベースモデルのフィールドに辞書を保存する方法

モデルのフィールドに辞書を保存する必要があります。それ、どうやったら出来るの?

たとえば、私はこのコードを持っています:

def create_random_bill(self):
    name_chars = re.compile("[a-zA-Z0-9 -_]")
    bill_name = "".join(random.choice(name_chars for x in range(10)))
    Rand_products = random.randint(1,100)
    for x in Rand_products:
        bill_products = 
    new_bill = Bill.new(name=bill_name, date=datetime.date, products=bill_products)
    new_bill.save()

「bill_products =」に対して何を書くと、製品モデルからこの請求書まで、ランダムな製品が保存されますか?

これは法案のモデルの説明です:

class Bill(models.Model):
    name = models.CharField(max_length=255)
    date = models.DateTimeField(auto_now_add=True)
    products = models.ManyToManyField(Product, related_name="bills")

また、製品のモデルの説明:

class Product(models.Model):
    name = models.CharField(max_length=255)
    price = models.IntegerField()

他に何かあれば、コメントを残してください。ありがとう!

24
Radu Gheorghiu

おそらく最もクリーンなことは、別の「Products」テーブルを作成し、多対多の関係を持つことです。 (こちらを参照してください: https://docs.djangoproject.com/en/dev/topics/db/models/#many-to-many-relationships 。ドキュメントでは、ピザの例を使用しています多くのトッピングがあります。)

もう1つのオプションは、bill_productsをシリアル化することです。その場合、次のようなことをします。

bill_products = json.dumps([Rand_products])

これはforループの外側になります(ただし、上記の例では、Rand_productsは単一の値であるため、修正する必要があります)。

6
gdw2

Django-jsonfield パッケージを発見しました。

再利用可能なDjangoフィールドで、検証済みのJSONをモデルに保存できます。

あなたが望むものを達成するための実行可能なオプションのように見えます。

20
ramiro

モデルにJSON表現を保存する便利な方法の1つは、カスタムフィールドタイプを使用することです。

class JSONField(models.TextField):
    """
    JSONField is a generic textfield that neatly serializes/unserializes
    JSON objects seamlessly.
    Django snippet #1478

    example:
        class Page(models.Model):
            data = JSONField(blank=True, null=True)


        page = Page.objects.get(pk=5)
        page.data = {'title': 'test', 'type': 3}
        page.save()
    """

    __metaclass__ = models.SubfieldBase

    def to_python(self, value):
        if value == "":
            return None

        try:
            if isinstance(value, basestring):
                return json.loads(value)
        except ValueError:
            pass
        return value

    def get_db_prep_save(self, value, *args, **kwargs):
        if value == "":
            return None
        if isinstance(value, dict):
            value = json.dumps(value, cls=DjangoJSONEncoder)
        return super(JSONField, self).get_db_prep_save(value, *args, **kwargs)

このutils/fields.pyをモデルに保存しましたfrom utils.fields import JSONFieldDjango-annoying アプリにはさらに多くの便利な機能があります。

11

カスタムフィールドタイプを使用するのが私の推奨ソリューションです。単一のフィールドタイプに対してサードパーティライブラリ全体をサポートするよりも、数行のカスタムコードが必要です。 Tony Abou-Assalehには優れたソリューションがありますが、Djangoの新しいバージョンでは動作しません。

これは、Django 1.10.4

import json

from Django.db import models
from Django.core.serializers.json import DjangoJSONEncoder


class JSONField(models.TextField):
    """
    JSONField is a generic textfield that neatly serializes/unserializes
    JSON objects seamlessly.
    Django snippet #1478

    example:
        class Page(models.Model):
            data = JSONField(blank=True, null=True)


        page = Page.objects.get(pk=5)
        page.data = {'title': 'test', 'type': 3}
        page.save()
    """

    def to_python(self, value):
        if value == "":
            return None

        try:
            if isinstance(value, str):
                return json.loads(value)
        except ValueError:
            pass
        return value

    def from_db_value(self, value, *args):
        return self.to_python(value)

    def get_db_prep_save(self, value, *args, **kwargs):
        if value == "":
            return None
        if isinstance(value, dict):
            value = json.dumps(value, cls=DjangoJSONEncoder)
        return value
9
Rico

Pickleモジュールからのシリアライゼーション/デシリアライゼーションを使用できます:

http://docs.python.org/library/pickle.html

Postgresがバックエンドの場合、Djangoからネイティブサポートされているhstoreフィールドを検討してください

3
wjin

私は、フィールドをmodels.CharField()として作成し、辞書をJSON文字列としてエンコードし、その文字列をデータベースに保存すると思います。その後、JSON文字列を読み取ったときにデコードして辞書に戻すことができます。

2
brian buck