Opened 9 years ago

Closed 9 years ago

#26654 closed New feature (needsinfo)

Better forms for django.contrib.postgres.fields

Reported by: Paul Martin Owned by: Paul Martin
Component: contrib.postgres Version: dev
Severity: Normal Keywords: postgres, array, hstore, json, forms
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I'm working on a pull request which provides the following features to django.contrib.postgres:

django.contrib.postgres.fields.array.ArrayField:

1) Currently the Array Field uses a SimpleArrayField. New feature is to accepts a form_size argument in which case a Split Array Field will be used.

2) If the choices argument is given to an ArrayField, the choices would now expect to be of the BaseField Type and a TypedMultipleChoiceField will be used. The array value will be composed of the choices given in this field.

django.contrib.postgres.forms.nested_form:

1) A NestedFormWidget and NestedFormField (subclassed from MultiWidget and MultiValueField) which can be used to create a nested form. Unlike with MultiWidget, each widget has a label and the widgets are presented in list form. The form compress and widget decompress methods work with data as a dictionary of field names and values.

The NestedFormField accept either a list of tuples, with each tuple containing a field name and field instance, or a tuple of field names ("keys" keyword argument), in which case the NestedForm will consist of a charfield for each given field name.

NestedFormFields can contain other NestedFormFields.

django.contrib.postgres.fields.hstore.HStoreField:

1) Now accepts a "fields" keyword argument which is the same format as the NestedFormField fields keyword argument. If given, a NestedFormField will be used consisting of the given fields. The NestedFormField will return a dictionary which can then be used to populate the HStore Field. The fields argument should only contain field types which have string values.

2) Accepts a keys argument. If given a NestedFormField will be created consisting only of CharFields, one for each key.

3) Accepts a require_all_fields argument in which case all fields in the NestedForm will be required (default is False).

4) Accepts a max_value_length argument - if given with the keys argument, this will be the max length of each CharField.

JSONField:

1) Now accepts a "fields" keyword argument which is the same format as the NestedFormField fields keyword argument. If given, a NestedFormField will be used consisting of the given fields. The NestedFormField will return a dictionary which can then be used to populate the JSON Field. The fields can consist of any form field types, including another NestedFormField or a SplitArrayField.

2) Accepts a require_all_fields argument in which case all fields in the NestedForm will need to be not blank (default is False).

I've written the first revision of the patch and also tests in tests.postgres_tests. All the above features have been verified. This includes some Selenium tests. I need to start working on documentation but I will upload a branch today.

Would love to have some feedback on what people think of these features.

Example usage:

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.IntegerField(),default=[], blank=True, choices=(
        (0, 'Football'), (1, 'Tennis'), (2, 'Golf'), (3, 'Basketball'),
        (4, 'Hurling'), (5, 'Baseball')))
    shipping = HStoreField(keys=('Address', 'City', 'Region', 'Country'), blank=True, default={})
    details = JSONField(blank=True, default={}, 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)),
        )
    )

    def __str__(self):
        return self.name

I will attach an image showing how the above would look in the admin add form.

Attachments (1)

admin.jpg (65.6 KB ) - added by Paul Martin 9 years ago.
How the Product model would look in the admin add view

Download all attachments as: .zip

Change History (4)

by Paul Martin, 9 years ago

Attachment: admin.jpg added

How the Product model would look in the admin add view

comment:1 by Paul Martin, 9 years ago

Owner: set to Paul Martin
Status: newassigned

comment:2 by Marc Tamlyn, 9 years ago

Two main problems I have with this:

  • That level of form declaration does not belong in the model. Even if we have form fields capable of this, we should define them as form fields.
  • These declarations imply to me a concrete specification of what your data looks like. This begs the question - why would you use an HStore or a JSON field in that case anyway?

comment:3 by Tim Graham, 9 years ago

Resolution: needsinfo
Status: assignedclosed

I raised similar concerns on the django-developers thread. I think we also need separate tickets for each enhancement (if the discussion yields consensus to move forward with any of the proposals) rather than a single ticket.

Note: See TracTickets for help on using tickets.
Back to Top