Meilleur widget Admin ArrayField?

y a-t-il un moyen de faire en sorte que le widget administrateur de ArrayField autorise l'ajout et la suppression d'objets? Il semble que par défaut, il est affiché juste un champ de texte, et utilise la séparation de virgule pour ses valeurs.

en plus d'être gênant, AFAICT dans le cas où le champ de base du tableau est un Char/TextField, cela ne permet pas d'inclure des virgules dans aucun des textes du tableau.

17
demandé sur Danra 2015-07-15 12:05:57

3 réponses

Je ne prends aucun crédit pour cela ( source originale), mais une option encore plus facile est la sous-classe ArrayField sur le modèle et Outrepasser le widget administrateur par défaut. Une implémentation de base suit (testée en Django 1.9 et 1.10):

models.py

from django import forms
from django.db import models
from django.contrib.postgres.fields import ArrayField


class ChoiceArrayField(ArrayField):
    """
    A field that allows us to store an array of choices.
    Uses Django's Postgres ArrayField
    and a MultipleChoiceField for its formfield.
    """

    def formfield(self, **kwargs):
        defaults = {
            'form_class': forms.MultipleChoiceField,
            'choices': self.base_field.choices,
        }
        defaults.update(kwargs)
        # Skip our parent's formfield implementation completely as we don't
        # care for it.
        # pylint:disable=bad-super-call
        return super(ArrayField, self).formfield(**defaults)


FUNCTION_CHOICES = (
    ('0', 'Planning'),
    ('1', 'Operation'),
    ('2', 'Reporting'),
)

class FunctionModel(models.Model):
    name = models.CharField(max_length=128, unique=True)
    function = ChoiceArrayField(
        base_field=models.CharField(max_length=256, choices=FUNCTION_CHOICES),
        default=list)
11
répondu ropable 2018-04-29 12:21:13

django-select2 offre un moyen de rendre l' ArrayField en utilisant Select2. Dans leur documentation, l'exemple est pour ArrayField:

http://django-select2.readthedocs.io/en/latest/django_select2.html#django_select2.forms.Select2TagWidget

pour rendre les valeurs déjà sélectionnées:

class ArrayFieldWidget(Select2TagWidget):

    def render_options(self, *args, **kwargs):
        try:
            selected_choices, = args
        except ValueError:  # Signature contained `choices` prior to Django 1.10
            choices, selected_choices = args
        output = ['<option></option>' if not self.is_required and not self.allow_multiple_selected else '']
        selected_choices = {force_text(v) for v in selected_choices.split(',')}
        choices = {(v, v) for v in selected_choices}
        for option_value, option_label in choices:
            output.append(self.render_option(selected_choices, option_value, option_label))
        return '\n'.join(output)

    def value_from_datadict(self, data, files, name):
        values = super().value_from_datadict(data, files, name)
        return ",".join(values)

Pour ajouter le widget à votre formulaire:

class MyForm(ModelForm):

    class Meta:
        fields = ['my_array_field']
        widgets = {
            'my_array_field': ArrayFieldWidget
        }
1
répondu Risadinha 2016-09-05 09:05:59