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.
3 réponses
Pour l'OP, ou quelqu'un là-bas, entre ces utiles bits, vous devriez être bon d'aller:
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)
django-select2
offre un moyen de rendre l' ArrayField
en utilisant Select2. Dans leur documentation, l'exemple est pour ArrayField
:
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
}