title: Transparently storing Django model field as JSON data
body: <p>Say I have an object, "Order," a field of which, "items," holds a list of order items. The list of items will never be searched or individually selected in the database so I just want to store it in a DB field as a JSON string.</p>
  
  <p>I'm trying to figure out the best way to embed this functionality so it's fairly transparent to anyone using the model. I think saving the model is pretty easy - just override the save method and serialize the "items" list into an internal "_items" field, and then write that to the db. I'm confused about how to deserialize, though. Having looked into possibly some kind of classmethod for creation, or creating a custom manger, or something to do with signals, I've thoroughly confused myself. I'm sure this has been solved a hundred times over and I'm curious what people consider to be best practice. </p>
  
  <p>Example classes:</p>
  
  <pre><code>class OrderItem():
      def __init__(self, desc="", qty=0):
          self.desc = desc
          self.qty = qty
  
  
  class Order(Model):
      user = ForeignKey(User)
      _items = TextField() 
  
      def save(self, *args, **kwargs):
          self._items = jsonpickle.encode(self.items)
          super(Order, self).save(*args, **kwargs)
  </code></pre>
  
  <p>Example usage:</p>
  
  <pre><code>order = Order()
  order.items = [OrderItem("widget", 5)]
  order.save()
  </code></pre>
  
  <p>This would create a record in the DB in which</p>
  
  <pre><code>_items = [{"desc":"widget", "qty":5}]
  </code></pre>
  
  <p>Now I want to be able to later select the object </p>
  
  <pre><code>order = Order.objects.get(id=whatever)
  </code></pre>
  
  <p>and have order.items be the unpacked array of items, not the stored JSON string.</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>The solution turned out to be quite simple, and I'm posting here in case it helps any other newbies. Based on Daniel's suggestion, I went with this custom model field:</p>
  
  <pre><code>class JSONField(with_metaclass(SubfieldBase, TextField)):
      def db_type(self, connection):
          return 'JSONField'
  
      def to_python(self, value):
          if isinstance(value, basestring):
              return jsonpickle.decode(value)
          else:
              return value
  
      def get_prep_value(self, value):
          return jsonpickle.encode(value)
  </code></pre>