How to store a dictionary on a Django model?

I need to save some data in a Django model. This data is not equal to all instances of the model.

At first I thought about subclassing the model, but Im trying to keep the application flexible. If I use subclasses, I need to create an entire class every time I need a new kind of object, and this is not good. Ill also end up with a lot of subclasses just to store a couple of extra fields.

I really feel that a dictionary would be a better approach, but there is nothing in the Django documentation about storing a dictionary in a Django model (or I can't find it).

Any clues?

+50
python django orm django-models persistence
Dec 31 '09 at 3:18
source share
13 answers

If this is really a dictionary, like any data that you are looking for, perhaps you can use a two-level setup with one model, which is a container and another model, which are key-value pairs. You must create an instance of the container, create each instance of the key value and associate a set of key instances with the container instance. Something like:

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) 

This is not very, but it will allow you to access the internal words of the dictionary using DB, while the pickle / serialize solution will not.

+37
Dec 31 '09 at 8:19
source share

If you do not need to request any of this additional data, then you can save it as a serialized dictionary. Use repr to turn a dictionary into a string, and eval to turn a string into a dictionary. Be careful with eval so that there is no user data in the dictionary, or use the safe_eval implementation.

For example, in the create and update methods of your views you can add:

 if isinstance(request.data, dict) == False: req_data = request.data.dict().copy() else: req_data = request.data.copy() dict_key = 'request_parameter_that_has_a_dict_inside' if dict_key in req_data.keys() and isinstance(req_data[dict_key], dict): req_data[dict_key] = repr(req_data[dict_key]) 
+15
Dec 31 '09 at 3:39
source share

I came to this post using google 4th result for "django storage object"

A bit late, but django-picklefield looks like a good solution for me.

Example from doc doc:

To use, simply define a field in your model:

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

and assign whatever you like (as long as it fits) in the field:

 >>> obj = SomeObject() >>> obj.args = ['fancy', {'objects': 'inside'}] >>> obj.save() 
+11
Sep 19 '11 at 10:10
source share

Another clean and quick solution can be found here: https://github.com/bradjasper/django-jsonfield

For convenience, I copied simple instructions.

Install

 pip install jsonfield 

Using

 from django.db import models from jsonfield import JSONField class MyModel(models.Model): json = JSONField() 
+11
Jul 31 '13 at 12:50
source share

As Ned said, you won’t be able to request “some data” if you use a dictionary.

If you still need to keep dictionaries, then the best approach is by far the PickleField class, documented in Marty Alchin Pro Django's new book. This method uses the properties of the Python class to mark / unpack a python object only by request, which is stored in the model field.

The basis of this approach is to use the django contibute_to_class method to dynamically add a new field to your model and use getattr / setattr to do serialization on demand.

One of the few online examples that I could find is similar to this JSONField definition.

+7
Dec 31 '09 at 7:44
source share

I'm not sure exactly the nature of the problem you're trying to solve, but it sounds curious like the Google App Engine BigTable Expando .

Expandos allows you to specify and store additional fields for an instance of an object with database support at run time. Quote from the 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.') 

The Google App Engine currently supports both Python and Django. It may be worth a look if this is the best way to express your patterns.

Traditional relational database models do not have the flexibility to add columns. If your data types are simple enough, you can abandon the traditional RDBMS philosophy and hack values ​​into a single column through serialization, as @Ned Batchelder suggests; however, if you need to use an RDBMS, inheriting a Django model is probably the way out. Notably, it will create a one-to-one foreign key relationship for each output level.

+5
Dec 31 '09 at 7:09
source share

Being "not equal to all instances of the model" sounds to me like a good match for a "database without schemas." CouchDB is a child poster for this approach, and you can think about it.

In the project, I moved some tables that never played very well from Django ORM to CouchDB, and I'm quite happy with that. I am using couchdb-python without any Django-specific CouchDB modules. A description of the data model can be found here . Moving from five “models” in Django to 3 “models” in Django and one CouchDB database actually slightly reduced the total lines of code in my application.

+3
04 Jan '09 at 12:28
source share

I agree that you need to refrain from overlaying other structured data in one column. But if you have to do this, Django has an XMLField .

There are also JSONField in Djipo snipplets.

+3
May 13 '09 at 18:05
source share

This question is old, but I had the same problem and it ended and the selected answer could no longer solve my problem.

If you want to store dictionaries in Django or REST Api that will be used as objects in your interface, or because your data will not necessarily have the same structure, then the solution I used can help you.

When saving data to your API, use the json.dump () method to be able to save it in the correct json format, as described in this question .

If you use this structure, your data will already be in the appropriate json format, which will be called in the frontend using JSON.parse () in your ajax call (or whatever).

+3
Aug 2 '18 at 8:56
source share

Think about it and find common features of each data set ... then define your model. This may require the use of subclasses or not. Foreign keys representing common features should not be avoided, but encouraged when they make sense.

Pulling random data into an SQL table is not reasonable, if only it is really non-relational data. If this is the case, identify your problem and we can help.

+2
Dec 31 '09 at 5:54
source share

Django-Geo includes a DictionaryField, which may come in handy:

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

In general, if you do not need to request data, use a denormalized approach to avoid additional requests. User preferences are a pretty good example!

+2
May 13, '09 at 16:50
source share

If you use Postgres, you can use the hstore field: https://docs.djangoproject.com/en/1.10/ref/contrib/postgres/fields/#hstorefield .

+1
Aug 30 '16 at 19:36
source share

I am using a text box and 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) 
0
May 05 '19 at 4:55
source share



All Articles