Pergunta

Eu preciso armazenar alguns dados em um modelo de Django. Estes dados não são iguais a todas as instâncias do modelo.

No começo eu pensei sobre subclassificação o modelo, mas eu estou tentando manter a aplicação flexível. Se eu usar subclasses, eu vou ter de criar toda uma classe cada vez que eu preciso de um novo tipo de objeto, e isso não é bom. Eu também vai acabar com um monte de subclasses apenas para armazenar um par de campos extras.

Eu realmente sinto que um dicionário seria a melhor abordagem, mas não há nada na documentação do Django sobre o armazenamento de um dicionário em um modelo de Django (ou eu não posso encontrá-lo).

Qualquer pistas?

Foi útil?

Solução

Se for realmente dicionário como dados arbitrários que você está procurando provavelmente você pode usar uma configuração de dois níveis com um modelo que é um recipiente e um outro modelo que é pares chave-valor. Você iria criar uma instância do recipiente, criar cada uma das instâncias de valor-chave, e associar o conjunto de instâncias de valor-chave com a instância recipiente. Algo como:

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)

Não é bonito, mas vai deixá-lo de acesso / pesquisar as entranhas do dicionário usando o DB enquanto uma solução picles / serialize não vai.

Outras dicas

Se você não precisa de consulta por qualquer um desses dados extra, então você pode armazená-lo como um dicionário serializado. Use repr para transformar o dicionário em um corda, e eval para virar as costas string em um dicionário. Tome cuidado com eval que não há dados de usuário no dicionário, ou usar uma implementação safe_eval.

Eu vim para este post por resultado 4rth do Google de "Django objeto de armazenamento"

Um pouco tarde, mas django-picklefield parece uma boa solução para mim.

Exemplo de ref:

Para usar, basta definir um campo no seu modelo:

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

e atribua o que quiser (desde que de picklable) para o campo:

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

Outra solução rápida e limpa pode ser encontrada aqui: https://github.com/bradjasper/django- jsonfield

Por conveniência Copiei as instruções simples.

Instalar

pip install jsonfield

Uso

from django.db import models
from jsonfield import JSONField

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

Como Ned respondida, você não será capaz de consulta "alguns dados" Se você usar a abordagem de dicionário.

Se você ainda precisa armazenar dicionários, em seguida, a melhor abordagem, de longe, é a classe PickleField documentado no novo livro de Marty Alchin Pro Django . Este método utiliza propriedades de classe Python para picles / unpickle um objeto python, somente sob demanda, que é armazenado em um campo de modelo.

Os fundamentos desta abordagem é usar Django contibute_to_class método para dinamicamente adicionar um novo campo para o seu modelo e usos getattr / setattr para fazer a serialização na demanda.

Um dos poucos exemplos on-line que eu poderia encontrar que é semelhante é esta definição de um JSONField .

Eu não sei exatamente certeza da natureza do problema que você está tentando resolver, mas soa curiosamente semelhante ao o Google App Engine BigTable Expando .

ExpandOS permitem especificar e armazenar campos adicionais em uma instância objeto lastreados em banco de dados em tempo de execução. Para citar os docs:

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.')

O Google App Engine suporta atualmente tanto Python eo framework Django. Pode valer a pena olhar em se esta é a melhor maneira de expressar seus modelos.

modelos de banco de dados relacionais tradicionais não têm este tipo de flexibilidade coluna da adição. Se os seus tipos de dados são suficientes simples você poderia romper com a filosofia RDBMS tradicional e cortar os valores em uma única coluna através de serialização como @ Ned Batchelder propõe; No entanto, se você Have usar uma herança modelo de RDBMS, Django é provavelmente o caminho a percorrer. Notavelmente, ele irá criar um one-to -um chave estrangeira relação para cada nível de derivação.

Eu concordo que você precisa abster-se enchendo de dados de outra forma estruturados em uma única coluna. Mas se você deve fazer isso, Django tem um XMLField build-in.

Há também JSONField em snipplets Django.

Ser "não é igual a todas as instâncias do modelo" Parece-me que um bom jogo para um "banco de dados de esquema-livre". CouchDB é a criança do poster para essa abordagem e você pode considerar isso.

Em um projeto que me mudei várias mesas que nunca jogaram muito agradável com o Django ORM sobre a CouchDB e eu estou muito feliz com isso. Eu uso couchdb-python sem qualquer um dos módulos do CouchDB Django específicas do. Uma descrição do modelo de dados podem ser encontrados aqui . O movimento de cinco "modelos" em Django 3 "modelos" em Django e um "banco de dados" CouchDB realmente reduziu ligeiramente as linhas totais de código na minha aplicação.

Esta questão é antiga, mas eu estava tendo o mesmo problema, terminou aqui e a resposta escolhida não poderia resolver o meu problema anymore.

Se você deseja armazenar dicionários em Django ou API REST, ou para ser usado como objetos em sua parte frontal, ou porque seus dados não vai necessariamente ter a mesma estrutura, a solução que eu usei pode ajudá-lo.

Ao salvar os dados em sua API, use json.dump () método para ser capaz de armazená-lo em um formato JSON adequada, conforme descrito nesta questão .

Se você usar essa estrutura, os dados já estarão no formato JSON apropriado para ser chamado na extremidade dianteira com JSON.parse () em sua ajax (ou qualquer outro) chamada.

Pense sobre isso e encontrar os pontos comuns de cada conjunto de dados ... então definir o seu modelo. Ela pode exigir o uso de subclasses ou não. chaves estrangeiras que representam semelhanças não estão a ser evitado, mas encorajado quando eles fazem sentido.

Encher dados aleatórios em uma tabela SQL não é inteligente, a menos que seja realmente dados não-relacionais. Se for esse o caso, definir o seu problema e nós pode ser capaz de ajuda.

Django-Geo inclui um "DictionaryField" que você pode encontrar útil:

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

Em geral, se você não precisa de consulta através dos dados usar uma abordagem desnormalizada para evitar consultas extras. configurações do usuário são um exemplo muito bom!

Se você estiver usando PostgreSQL, você pode usar um campo hstore: https://docs.djangoproject.com/en/1.10/ref/contrib/postgres/fields/#hstorefield .

Eu uso um campo de texto e 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)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top