Модели в Django.CommaSeparatedIntegerField с формами.Виджет CheckboxSelectMultiple

у меня есть приложение Django и хочу отображать флажки с несколькими вариантами в интерфейсе администратора Django. Я не хочу создавать отдельную модель для моего выбора, используя ManyToManyField.

models.py

from django.db import models

STAFF_BUSINESS_TYPES = {
    (1, "Foo"),
    (2, "Bar"),
    (3, "Cat"),
    (4, "Dog")
}

class Business(models.Model):
    name = models.CharField(max_length=255, unique=True)
    business_types = models.CommaSeparatedIntegerField(max_length=32, choices=STAFF_BUSINESS_TYPES)

forms.py

from business.models import Business, STAFF_BUSINESS_TYPES
from django.forms import CheckboxSelectMultiple, ModelForm, MultipleChoiceField

class BusinessForm(ModelForm):
    business_types = MultipleChoiceField(required=True, widget=CheckboxSelectMultiple, choices=STAFF_BUSINESS_TYPES)

    class Meta:
        model = Business
        fields = ['name', 'business_types']

    def clean_business_types(self):
        data = self.cleaned_data['business_types']
        cleaned_data = ",".join(data)
        return cleaned_data

admin.py

from django.contrib import admin
from business.models import Business
from business.forms import BusinessForm

@admin.register(Business)
class BusinessAdmin(admin.ModelAdmin):
    form = BusinessForm

однако, когда я пытаюсь добавить бизнес с типом "Bar":

Выберите правильный выбор. 1 не один из доступных вариантов.

аналогично, когда я пытаюсь добавить бизнес с несколькими выбранными значениями:

Выберите правильный выбор. 1,2 не является одним из доступных вариантов.

как 1 не является допустимым выбором, учитывая, что (1," Foo") находится в пределах моего выбора? Недопустимо ли использовать встроенное целое поле Django, разделенное запятыми?

2 ответов


Я работал в аналогичной проблеме, и вот мое решение:

# coding: utf-8
# python2 / django1.6.5

""" 
    That's a first solution I got to use CommaSeparatedIntegerFields with SelectMultiple widget. 
    My intension is to change this solution to a custom Widget that inherits from SelectMultiple.
    *** It still needs refactoring ***
"""

models.py

from django.db import models

MY_CHOICES = (
    (1, 'escolha1'),
    (2, 'escolha2'),
    (3, 'escolha3'),
    (4, 'escolha4'),
    (5, 'escolha5'),
)

class MeuConteudo(models.Model):
    meu_campo = models.CommaSeparatedIntegerField(
        blank=True, max_length=255,
    )

forms.py

from django import forms
from minhaapp.models import MeuConteudo, MY_CHOICES


class CommaSeparatedSelectInteger(forms.MultipleChoiceField):
    def to_python(self, value):
        if not value:
            return ''
        elif not isinstance(value, (list, tuple)):
            raise ValidationError(
                self.error_messages['invalid_list'], code='invalid_list'
            )
        return ','.join([str(val) for val in value])

    def validate(self, value):
        """
        Validates that the input is a string of integers separeted by comma.
        """
        if self.required and not value:
            raise ValidationError(
                self.error_messages['required'], code='required'
            )

        # Validate that each value in the value list is in self.choices.
        for val in value.split(','):
            if not self.valid_value(val):
                raise ValidationError(
                    self.error_messages['invalid_choice'],
                    code='invalid_choice',
                    params={'value': val},
                )

    def prepare_value(self, value):
        """ Convert the string of comma separated integers in list"""
        return value.split(',')


class MeuConteudoMultipleForm(forms.ModelForm):
    meu_campo = CommaSeparatedSelectInteger(
        choices=MY_CHOICES,
        widget=forms.SelectMultiple
    )

    class Meta:
        model = MeuConteudo

admin.py

from forms import MeuConteudoMultipleForm
from minhaapp.models import MeuConteudo
from minhaapp.forms import MeuConteudoMultipleForm


class MeuConteudoAdmin(admin.ModelAdmin):
    form = MeuConteudoMultipleForm


admin.site.register(MeuConteudo, MeuConteudoMultipleForm)

https://gist.github.com/romulocollopy/bffe38fa72af5bc427e1

Я закончил использование фрагмента Django, найденного в https://djangosnippets.org/snippets/1200/, а не переопределять мои собственные методы подготовки и проверки классов форм.