This is a pre-production deployment of Warehouse, however changes made here WILL affect the production instance of PyPI.
Latest Version Dependencies status unknown Test status unknown Test coverage unknown
Project Description
Django Postgres Extensions!
===================

Django Postgres Extensions adds a lot of functionality to Django.contrib.postgres, specifically in relation to ArrayField, HStoreField and JSONField. The app also includes an Array Many To Many Field, so you can store the relationship in an array column instead of requiring an extra database table.

----------

Getting Started
-------------

In your settings.py, add 'django.contrib.postgres' and 'django_postgres_extensions' to the list of INSTALLED APPS and configure the database to use the included backend (subclassed from the default Django Postgres backend):

```python
INSTALLED_APPS = [
'django.contrib.contenttypes',
'django.contrib.auth',
'django.contrib.sites',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.admin.apps.SimpleAdminConfig',
'django.contrib.staticfiles',
'django.contrib.postgres',
'django_postgres_extensions'
]

DATABASES = {
'default': {
'ENGINE': 'django_postgres_extensions.backends.postgresql',
'NAME': 'db',
'USER': 'postgres',
'PASSWORD': 'postgres',
'HOST': '127.0.0.1',
'PORT': 5432,
}
}
```
Here is an overview of the available features:

Custom Postgres backend
-------------
The customized Postgres backend adds the following features:


> - HStore Extension is automatically activated when a test database is created so you don't need to create a separate migration which is useful especially when building re-usable apps
> - Uses a different update compiler which adds some functionality outlined in the ArrayField section below
> - If db_index is set to True for an ArrayField, a GIN index will be created which is more useful than the default database index for arrays.
> - Adds some extra operators to enable ANY and ALL lookups

ArrayField
-------------
The included ArrayField has been subclassed from django.contrib.postgres.fields.ArrayField to add extra features and is a drop-in replacement. To use this ArrayField:

```python
from django.db import models
from django_postgres_extensions.models.fields import ArrayField
class Product(models.Model):
tags = ArrayField(models.CharField(max_length=15), null=True, blank=True)
moretags = ArrayField(models.CharField(max_length=15), null=True, blank=True)
````
The customized Postgres ArrayField adds the following features:

> - Get array values by index:
```python
from django_postgres_extensions.models.expressions import Index, SliceArray
obj = Product.objects.annotate(Index('tags', 1)).get()
print(obj.tags__1)
obj = Product.objects.annotate(tag_1=Index('tags', 1)).get()
print(obj.tag_1)
obj = Product.objects.annotate(SliceArray('tags', 0, 1)).get()
print(obj.tags__0_1)
```
> - Update array values by index:
```python
Product.objects.update(tags__2='Heavy Metal')
```
> - Many database functions are included for interacting with Arrays. These functions handle the provided arguments by automatically converting them to the required expressions:
```python
from django_postgres_extensions.models.functions import *
obj = Product.objects.queryset.annotate(tags_length=ArrayLength('tags', 1)).get()
obj = Product.objects.annotate(position=ArrayPosition('tags', 'Rock')).get()
obj = Product.objects.annotate(positions=ArrayPositions('tags', 'Rock')).get()
Product.objects.update(tags = ArrayAppend('tags', 'Popular'))
Product.objects.update(tags = ArrayPrepend('Popular', 'tags'))
Product.objects.update(tags = ArrayRemove('tags', 'Album'))
Product.objects.update(tags = ArrayReplace('tags', 'Rock', 'Heavy Metal'))
```
>- ArrayCat function can combine the values of two separate ArrayFields:
```python
Product.objects.update(tags = ArrayCat('tags', 'moretags'))
```
Or alternatively, add an array of values to an existing field. In this case the output_field is required to tell Django what db type to use for the array:

```python
Product.objects.update(tags=ArrayCat('tags', ['Popular', '8'], output_field=Product._meta.get_field('tags')))
```
django.contrib.postgres includes two possible array form fields: SimpleArrayField (the default) and SplitArrayField. To use the SplitArrayField automatically when generating a ModelForm, add the form_size keyword argument to the ArrayField:

```python
class Product(models.Model):
keywords = ArrayField(models.CharField(max_length=20), default=[], form_size=10, blank=True)
```

Additional lookups have been added to the ArrayField to enable queries using the ANY and ALL database functions:

```python
qs = Product.objects.filter(tags__any = 'Popular')
qs = Product.objects.filter(tags_all__isstartof = 'Popular')
```
Any lookups check if any value in the array meets the lookup criteria.
All lookups check is all values in an array meet the lookup criteria.
The full list of additional lookups are:

> - any
> - any_exact
> - any_gt
> - any_gte
> - any_lt
> - any_lte
> - any_in
> - any_isstartof
> - any_isendof
> - any_contains (for 2d arrays)
> - all
> - all_exact
> - all_gt
> - all_gte
> - all_lt
> - all_lte
> - all_in
> - all_isstartof
> - all_isendof
> - all_regex

HStoreField
-------------
The included HStoreField has been subclassed from django.contrib.postgres.fields.HStoreField to add extra features and is a drop-in replacement. To use this HStoreField:

```python
from django.db import models
from django_postgres_extensions.models.fields import HStoreField
class Product(models.Model):
description = HStoreField(null=True, blank=True)
````
The customized Postgres HStoreField adds the following features:

> - Get hstore values by key:
```python
from django_postgres_extensions.models.expressions import Key, Keys
obj = Product.objects.annotate(Key('description', 'Release')).get()
obj = Product.objects.annotate(Keys('description', ['Industry', 'Release'])).get()
```
> - Update hstore by specific keys, leaving any others untouched
```python
Product.objects.update(description__ = {'Genre': 'Heavy Metal', 'Popularity': 'Very Popular'})
```
> - Many database functions are included for interacting with HStores, these functions handle the arguments by converting them to the correct expressions automatically.
```python
from django_postgres_extensions.models.functions import *
obj = Product.objects.queryset.annotate(description_slice=Slice('description', ['Industry', 'Release'])).get()
obj = Product.objects.update(description = Delete('description', 'Genre'))
obj = Product.objects.update(description = Delete('description', ['Industry', 'Genre']))
Product.objects.update(description=Delete('description', {'Industry': 'Music', 'Release': 'Song', 'Genre': 'Rock'}))
Product.objects.annotate(description_keys=AKeys('description')).get()
Product.objects.annotate(description_values=AVals('description')).get()
Product.objects.annotate(description_array=HStoreToArray('description')).get()
Product.objects.annotate(description_matrix=HStoreToMatrix('description')).get()
Product.objects.annotate(description_jsonb=HstoreToJSONB('description')).get()
Product.objects.annotate(description_jsonb=HstoreToJSONBLoose('description')).get()
```
django.contrib.postgres includes a HStoreField for forms where you have to enter a hstore value programatically. Django Postgres Extensions adds a NestedFormField and NestedFormWidget for use with a HStore Field. To use it specify a list of fields or a list of keys as a keyword argument to the Hstore Model field, but not both:

```python
class Product(models.Model):
shipping = HStoreField(keys=('Address', 'City', 'Region', 'Country'), blank=True, default={})
```
JSONField
-------------
The included JSONField has been subclassed from django.contrib.postgres.fields.JSONField to add extra features and is a drop-in replacement. To use this JSONField:

```python
from django.db import models
from django_postgres_extensions.models.fields import JSONField

class Product(models.Model):
description = JSONField(null=True, blank=True)
````
The customized Postgres JSONField adds the following features:

> - Get json values by key or key path:
```python
from django_postgres_extensions.models.expressions import Key
obj = Product.objectsannotate(Key('description', 'Details')).get()
obj = Product.objects.annotate(Key('description', 'Details__Rating')).get()
obj = Product.objects.annotate(Key('description', 'Tags__1')).get()
```
> - Update JSON Field by specific keys, leaving any others untouched
```python
Product.objects.update(description__ = {'Industry': 'Movie', 'Popularity': 'Very Popular'})
```
> - Delete JSONField by key or key path:
```python
Product.objects.update(description__del ='Details')
Product.objects.update(description__del = 'Details__Release')
Product.objects.update(description__del='Tags__1')
```
> - Some database functions are included for interacting with JSONFields. These functions handle the arguments by converting them to the correct expressions automatically.
```python
from django_postgres_extensions.models.functions import *
from psycopg2.extras import Json
obj = Product.objects.update(description = JSONBSet('description', ['Details', 'Genre'], Json('Heavy Metal'), True))
obj = Product.objects.update(description=JSONBSet('description', ['1', 'c'], Json('g')))
obj = Product.objects.queryset.annotate(tags_length=JSONBArrayLength('tags', 1)).get()
```
django.contrib.postgres includes a JSONField for forms where you have to enter a hstore value programatically. The same NestedFormField and NestedFormWidget referred to above for HStore can also be used with a JSON Field. To use it give the fields keyword argument:

```python
details_fields = (
NestedFormField(label='Brand', keys=('Name', 'Country')),
forms.CharField(label='Type', max_length=25, required=False),
SplitArrayField(label='Colours', base_field=forms.CharField(max_length=10, required=False), size=10),
)

class Product(models.Model):
details = JSONField(fields=details_fields, blank=True, default={})
```

Array Many To Many Field
-------------
The Array Many To Many Field is designed be a drop-in replacement of the normal Django Many To Many Field and thus replicates many of its features. To use this field, it is required to set ENABLE_ARRAY_M2M = True in settings.py (to enable the required monkey-patching). In general, write queries are much faster than the traditional M2M however select queries are typically slower. To use this field:

```python
from django.db import models
from django_postgres_extensions.models.fields import ArrayManyToManyField

class Publication(models.Model):
title = models.CharField(max_length=30)

def __str__(self):
return self.title

class Meta:
ordering = ('title',)

class Article(models.Model):
headline = models.CharField(max_length=100)
publications = ArrayManyToManyField(Publication, name='publications')

def __str__(self):
return self.headline

class Meta:
ordering = ('headline',)
````
The Array Many To Many field supports the following features which replicate the API of the regular Many To Many Field:

> - Descriptor queryset with add, remove, clear and set for both forward and reverse relationships
> - Prefetch related for both forward and reverse relationships
> - Lookups across relationships with filter for both forward and reverse relationships
> - Lookups across relationships with exclude for for forward relationships only

You can find more information on how these features work in the Django documentation for the regular Many To Many Field:

https://docs.djangoproject.com/en/1.9/topics/db/examples/many_to_many/

ModelAdmin
----------

The django admin uses a JS-based widget for many to many fields. To enable this for array many to many fields also, you need to use django_postgres_extensions.admin.options.PostgresAdmin:

```python
from django.contrib import admin
from django_postgres_extensions.admin.options import PostgresAdmin
from models import Product, Buyer

class ProductAdmin(PostgresAdmin):
filter_horizontal = ('buyers',)
fields = ('name', 'keywords', 'sports', 'shipping', 'details', 'buyers')
list_display = ('name', 'keywords', 'shipping', 'details', 'country')

admin.site.register(Buyer)
admin.site.register(Product, ProductAdmin)
```


Take the following models.py:

```python
from django.db import models
from django_postgres_extensions.models.fields import HStoreField, JSONField, ArrayField
from django_postgres_extensions.models.fields.related import ArrayManyToManyField
from django import forms
from django.contrib.postgres.forms import SplitArrayField
from django_postgres_extensions.forms.fields import NestedFormField

details_fields = (
('Brand', NestedFormField(keys=('Name', 'Country'))),
('Type', forms.CharField(max_length=25, required=False)),
('Colours', SplitArrayField(base_field=forms.CharField(max_length=10, required=False), size=10)),
)

class Buyer(models.Model):
time = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=20)

def __str__(self):
return self.name

class Product(models.Model):
name = models.CharField(max_length=15)
keywords = ArrayField(models.CharField(max_length=20), default=[], form_size=10, blank=True)
sports = ArrayField(models.CharField(max_length=20),default=[], blank=True, choices=(
('football', 'Football'), ('tennis', 'Tennis'), ('golf', 'Golf'), ('basketball', 'Basketball'), ('hurling', 'Hurling'), ('baseball', 'Baseball')))
shipping = HStoreField(keys=('Address', 'City', 'Region', 'Country'), blank=True, default={})
details = JSONField(fields=details_fields, blank=True, default={})
buyers = ArrayManyToManyField(Buyer)

def __str__(self):
return self.name

@property
def country(self):
return self.shipping.get('Country', '')
```

With admin.py:

```python
from django.contrib import admin
from django_postgres_extensions.admin.options import PostgresAdmin
from models import Product, Buyer

class ProductAdmin(PostgresAdmin):
filter_horizontal = ('buyers',)
fields = ('name', 'keywords', 'sports', 'shipping', 'details', 'buyers')
list_display = ('name', 'keywords', 'shipping', 'details', 'country')

admin.site.register(Buyer)
admin.site.register(Product, ProductAdmin)
```
The form field would look like this:

![Image of Admin form](http://s33.postimg.org/e8f5x0fdr/postgres_form.jpg)

The list display would look like this:

![Image of Admin form](http://s33.postimg.org/e2ui1kicf/admin_list.jpg)


Benchmarks
---------

A set of benchmark tests have been included to compare performance of the traditional M2M Field with the Array M2M Field.

Additional Queryset Methods
---------------------------
This app adds the format method to all querysets. This will defer a field and add an annotation with a different format.
For example to return a hstorefield as json.

```python
qs = Model.objects.all().format('description', HstoreToJSONBLoose)
```
Release History

Release History

0.91

This version

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.9

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

Download Files

Download Files

TODO: Brief introduction on what you do with files - including link to relevant help section.

File Name & Checksum SHA256 Checksum Help Version File Type Upload Date
django_postgres_extensions-0.91-py2-none-any.whl (40.1 kB) Copy SHA256 Checksum SHA256 2.7 Wheel Nov 28, 2016
django_postgres_extensions-0.91.tar.gz (26.1 kB) Copy SHA256 Checksum SHA256 Source Nov 28, 2016

Supported By

WebFaction WebFaction Technical Writing Elastic Elastic Search Pingdom Pingdom Monitoring Dyn Dyn DNS HPE HPE Development Sentry Sentry Error Logging CloudAMQP CloudAMQP RabbitMQ Heroku Heroku PaaS Kabu Creative Kabu Creative UX & Design Fastly Fastly CDN DigiCert DigiCert EV Certificate Rackspace Rackspace Cloud Servers DreamHost DreamHost Log Hosting