2015-07-15 8 views
12

C'è un modo per rendere il widget di amministrazione di ArrayField consentire l'aggiunta e l'eliminazione di oggetti? Sembra che, per impostazione predefinita, venga invece visualizzato solo un campo di testo e utilizza la separazione virgola per i suoi valori.Meglio il widget di amministrazione di ArrayField?

Oltre ad essere inopportuno, AFAICT nel caso in cui il campo base dell'array è un campo Char/Text, questo non consente alcun modo di includere virgole in nessuno dei testi dell'array.

risposta

1

django-select2 offre un modo per rendere il ArrayField utilizzando Select2. Nella loro documentazione, l'esempio è per ArrayField:

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

per rendere i valori già selezionati:

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) 

Per aggiungere il widget al modulo:

class MyForm(ModelForm): 

    class Meta: 
     fields = ['my_array_field'] 
     widgets = { 
      'my_array_field': ArrayFieldWidget 
     } 
6

Colgo nessun credito per questo (original source), ma un'opzione ancora più semplice è quella di sottoclasse ArrayField sul modello e sostituisci il widget di amministrazione predefinito. Un'implementazione base segue (testato in Django 1.9 e 1.10):

models.py

from django import forms 
from django.contrib.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) 
+0

Mi sto perdendo qualcosa? Dove stai sovrascrivendo il widget di amministrazione predefinito? Il frammento citato dal weblog trasforma l'ArrayField piuttosto limitato in qualcosa di utile e funziona molto bene. Tuttavia, sarebbe stato bello vedere che widget di amministrazione hai trovato fa il miglior uso di questo. Potrei dare Select2 a go. – Marakai

+2

Ho ampliato l'esempio per essere più completo. – ropable

Problemi correlati