Simple Fields ============= django-pgfields exposes several new fields corresponding to data types available in PostgreSQL that are not available in other databases supported by Django. These fields are available on the ``django_pg.models`` module (see :doc:`usage` for more on this). Array Field ----------- PostgreSQL supports an array datatype. This is most similar to arrays in many statically-typed languages such as C or Java, in that you explicitly declare that you want an array of a specific type (for instance, an array of integers or an array of strings). django-pgfields exposes this by having the array field accept another field as its initial argument (or, alternatively, by using the ``of`` keyword argument).:: from django_pg import models class Hobbit(models.Model): name = models.CharField(max_length=50) favorite_foods = models.ArrayField(models.CharField(max_length=100)) created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) This will create an array of strings in the database (to be precise: ``character varying(100) []``). Assignment of values is done using standard Python lists:: pippin = Hobbit.objects.create( name='Peregrin Took', favorite_foods=['apples', 'lembas bread', 'potatoes'], ) As a note, do not attempt to store a full list of any hobbit's favorite foods. Your database server does not have sufficient memory or swap space for such a list. Lookups ^^^^^^^ When looking up data against an array field, the field supports three lookup types: ``exact`` (implied), ``contains``, and ``len``. **exact** The ``exact`` lookup type is the implied lookup type when doing a lookup in the Django ORM, and does not need to be explicitly specified. A straight lookup simply checks for array equality. Continuing the example immediately above:: >>> hobbit = Hobbit.objects.get( favorite_foods=['apples', 'lembas bread', 'potatoes'], ) >>> hobbit.name 'Peregrin Took' **contains** The ``contains`` lookup type checks to see whether *all* of the provided values exist in the array. If you only need to check for a single value, and the value is not itself an array (in a nested case, for instance), you may specify the lookup value directly:: >>> hobbit = Hobbit.objects.get(favorite_foods__contains='apples') >>> hobbit.name 'Peregrin Took' If you choose to do a ``contains`` lookup on multiple values, then be aware that *order is not relevant*. The database will check to ensure that each value is present, but ignore order of values in the array altogether:: >>> hobbit = Hobbit.objects.get( favorite_foods__contains=['lembas bread', 'apples'], ) >>> hobbit.name 'Peregrin Took' **len** The ``len`` lookup type checks the *length of* the array, rather than its contents. It maps to the array_length_ function in PostgreSQL (with the second argument set to ``1``). Such lookups are simple and straightforward:: >>> hobbit = Hobbit.objects.get(favorite_foods__len=3) >>> hobbit.name 'Peregrin Took' JSON Field ---------- .. versionadded:: 0.9.2 PostgreSQL 9.2 added initial support for a JSON data type. If you wish to store JSON natively in PostgreSQL, use the JSONField field:: from django_pg import models class Dwarf(models.Model): name = models.CharField(max_length=50) data = models.JSONField() created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) If you're using a version of PostgreSQL earlier than 9.2, this field will fall back to the ``text`` data type. .. warning:: As of PostgreSQL 9.2, *storing* JSON is fully supported, but doing any useful kind of lookup (including direct equality) on it is not. As such, django-pgfields supports storing JSON data, and will return the JSON fields' data to you when you lookup a record by other means, but it does *not* support *any* kind of lookup against JSON fields. Attempting *any* lookup will raise TypeError. Values ^^^^^^ The JSON field will return values back to you in the Python equivalents of the native JavaScript types: * JavaScript ``number`` instances will be converted to ``int`` or ``float`` as appropriate. * JavaScript ``array`` instances will be converted to Python ``list`` instances, and value conversion will be recursively applied to every item in the list. * JavaScript ``object`` instances will be converted to Python ``dict``, and value conversion will be recursively applied to the keys and values of the dictionary. * JavaScript ``string`` instances will be converted to Python 3 ``str``. * JavaScript ``boolean`` instances will be converted to Python ``bool``. * JavaScript ``null`` is converted to Python ``None``. * JavaScript special values (``NaN``, ``Infinity``) are converted to their Python equivalents. Use ``math.isnan`` and ``math.isinf`` to test for them. .. note:: Because field subclasses are called to convert values over and over again, there are a few cases where the conversion is not idempotent. In particular, strings that are also valid JSON (or look sufficiently close to valid JSON) will be deserialized again. The short version: write Python dictionaries, lists, and scalars, and the JSON field will figure out what to do with it. UUID Field ---------- In order to store UUIDs in the database under the PostgreSQL UUID type, use the UUIDField field:: from django_pg import models class Elf(models.Model): id = models.UUIDField(auto_add=True, primary_key=True) name = models.CharField(max_length=50) created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) Options ^^^^^^^ The UUID field implements the following field options in addition to the field options `available to all fields`_. .. note:: The UUID field interprets and writes blank values as SQL ``NULL``. Therefore, setting ``blank=True`` requires ``null=True`` also. Setting the former but not the latter will raise ``AttributeError``. **auto_add** Normally, the UUIDField works like any other Field subclass; you are expected to provide a value, and the value is saved to the database directly. If ``auto_add=True`` is set, then explicitly providing a value becomes optional. If no value is provided, then the field will auto-generate a random `version 4 UUID`_, which will be saved to the database (and assigned to the model instance). This is a particularly useful construct if you wish to store UUIDs for primary keys; they're a completely acceptable substitute for auto-incrementing integers:: >>> legolas = Elf(name='Legolas Greenleaf') >>> legolas.id '' >>> legolas.save() >>> legolas.id UUID('b1f12115-3337-4ec0-acb9-1bcf63e44477') Values ^^^^^^ The UUID field will return values from the database as Python `UUID`_ objects. If you choose to do so, you may assign a valid string to the field. The string will be converted to a ``uuid.UUID`` object upon assignment to the instance:: >>> legolas = Elf(name='Legolas Greenleaf') >>> legolas.id = '01234567-abcd-abcd-abcd-0123456789ab' >>> legolas.id UUID('01234567-abcd-abcd-abcd-0123456789ab') >>> type(legolas.id) Lookups can be performed using either strings or Python UUID objects. .. _array_length: http://www.postgresql.org/docs/9.2/static/functions-array.html#ARRAY-FUNCTIONS-TABLE .. _available to all fields: https://docs.djangoproject.com/en/dev/ref/models/fields/#field-options>`. .. _version 4 UUID: http://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29 .. _UUID: http://docs.python.org/3/library/uuid.html