Модели в 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/, а не переопределять мои собственные методы подготовки и проверки классов форм.