我知道模型没有MultipleChoiceField
,您只能在表单上使用它。
今天,在分析与多项选择相关的新项目时,我遇到了一个问题。
我希望有CharField
字段和choices
字段,可以选择多项选项。
我通过创建CharField
来解决此问题,并使用forms.MultipleChoiceField
管理表单中的多个选项,并以逗号分隔选项。
在这个项目中,由于配置问题,我不能像上面提到的那样去做,我需要在模型中进行,我更喜欢 NOT 来编辑 Django管理表单< / em> 既不也使用表单。 我需要一个具有多个选项的模型字段选项
也许覆盖一些模型功能或使用自定义小部件......我不知道,我有点迷失在这里。
我知道简单选择,我希望有类似的内容:
class MODEL(models.Model):
MY_CHOICES = (
('a', 'Hola'),
('b', 'Hello'),
('c', 'Bonjour'),
('d', 'Boas'),
)
...
...
my_field = models.CharField(max_length=1, choices=MY_CHOICES)
...
但能够保存多项选择,而不仅仅是一种选择。
答案 0 :(得分:45)
您需要考虑如何在数据库级别存储数据。这将决定您的解决方案。
据推测,您希望表中存储多个值的单个列。这也会强迫您考虑如何序列化 - 例如,如果您需要存储可能包含逗号的字符串,则不能简单地用逗号分隔。
但是,您最好使用如下之一的解决方案:
答案 1 :(得分:8)
从这两个中,https://pypi.python.org/pypi/django-select-multiple-field/看起来更圆润,更完整。它甚至有一套很好的单元测试。
我发现的问题是它在实现模型字段的类中抛出了Django 1.10弃用警告。
我修好了这个并发了PR。最新的代码,直到他们合并我的PR(如果他们决定嘿嘿)是在我的回购分支中,在这里:https://github.com/matiasherranz/django-select-multiple-field
干杯!
中号.-
答案 2 :(得分:2)
在您的情况下,我使用了ManyToManyField
会是这样的:
class MY_CHOICES(models.Model)
choice = models.CharField(max_length=154, unique=True)
class MODEL(models.Model):
...
...
my_field = models.ManyToManyField(MY_CHOICES)
所以,现在您可以选择多个选择
答案 3 :(得分:0)
如果您希望窗口小部件看起来像文本输入,并且仍然可以从建议中选择多个选项,那么您可能正在寻找Select2。还有django-select2将它与Django Forms和Admin集成。
答案 4 :(得分:0)
您可以将IntegerField
用于模型,将2的幂用于选择(位图字段)。我不确定为什么Django尚未内置此功能。
class MyModel(models.Model):
A = 1
B = 2
C = 4
MY_CHOICES = ((A, "foo"), (B, "bar"), (C, "baz"))
my_field = models.IntegerField(default=0)
from functools import reduce
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
# it can be set to required=True if needed
my_multi_field = forms.TypedMultipleChoiceField(
coerce=int, choices=MyModel.MY_CHOICES, required=False)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['my_multi_field'].initial = [
c for c, _ in MyModel.MY_CHOICES
if self.instance.my_field & c
]
def save(self, *args, **kwargs):
self.instance.my_field = reduce(
lambda x, y: x | y,
self.cleaned_data.get('my_multi_field', []),
0)
return super().save(*args, **kwargs)
可以像这样查询:MyModel.objects.filter(my_field=MyModel.A | MyModel.C)
以获取所有设置了A和C的记录。
答案 5 :(得分:0)
from django.db import models
class KarModel(models.Model):
choose_gender = (
(True, 'Male'),
(False, 'Female'),
)
fullname= models.CharField(max_length=200)
gender = models.BooleanField(default=True, choices=choose_gender)
def __str__(self):
return self.fullname
简单方法
答案 6 :(得分:-1)
我发现的最简单的方法(只是我使用eval()将从输入中获取的字符串转换为元组,以再次读取表单实例或其他位置)
这个技巧很好用
#model.py
class ClassName(models.Model):
field_name = models.CharField(max_length=100)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.field_name:
self.field_name= eval(self.field_name)
#form.py
CHOICES = [('pi', 'PI'), ('ci', 'CI')]
class ClassNameForm(forms.ModelForm):
field_name = forms.MultipleChoiceField(choices=CHOICES)
class Meta:
model = ClassName
fields = ['field_name',]
#view.py
def viewfunction(request, pk):
ins = ClassName.objects.get(pk=pk)
form = ClassNameForm(instance=ins)
if request.method == 'POST':
form = form (request.POST, instance=ins)
if form.is_valid():
form.save()
...