Python django 模型选择选项作为多选框
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3582544/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
django model choice option as a multi select box
提问by Hellnar
Assuming that I have such model
假设我有这样的模型
COLORS= (
('R', 'Red'),
('B', 'Yellow'),
('G', 'White'),
)
class Car(models.Model):
name = models.CharField(max_length=20)
color= models.CharField(max_length=1, choices=COLORS)
It displays as a selectbox in the admin panel however I would like my admin-user to multi select those colors like many-to-many relationship, how can this be achieved without a ('RB', 'Red&Blue'),type of logic
它在管理面板中显示为一个选择框,但是我希望我的管理员用户多选择那些颜色,如多对多关系,如何在没有('RB', 'Red&Blue'),逻辑类型的情况下实现
采纳答案by Manoj Govindan
Can a Carhave multiple colors? In that case colorought to be a many to many relationshiprather than a CharField. If on the other hand you want to do something like Unix permissions(i.e. Red + Blue, Red + Blue + Green etc.) then assign numeric values of to each of them and make coloran integer field.
a 可以Car有多个colors 吗?在那种情况下color应该是多对多关系而不是CharField. 另一方面,如果您想执行诸如Unix 权限之类的操作(即红色 + 蓝色、红色 + 蓝色 + 绿色等),则为它们中的每一个分配数值并创建color一个整数字段。
Update
更新
(After reading comment) You can use a custom formto edit your model in Admin instead of the default ModelForm. This custom form can use a multiple choice widget that lets users select multiple colors. You can then override the clean()method of the form to return a suitably concatenated value ('RB' etc.).
(阅读评论后)您可以使用自定义表单在 Admin 中编辑您的模型,而不是默认的ModelForm. 此自定义表单可以使用多项选择小部件,让用户可以选择多种颜色。然后,您可以覆盖clean()表单的方法以返回适当连接的值('RB' 等)。
Update 2
更新 2
Here is some code:
这是一些代码:
First, remove the choices from the model field. Also increase its maximum size to 2. We don't want choices here - if we do, then we'll have to add a choice for each combination of colors.
首先,从模型字段中删除选项。还将其最大大小增加到 2。我们不希望这里有选择——如果我们这样做了,那么我们将不得不为每种颜色组合添加一个选择。
class Car(models.Model):
...
color= models.CharField(max_length=2)
Second add a custom ModelFormto use in admin app. This form will override color and instead declare it as a multiple choice field. We doneed choices here.
其次添加一个自定义ModelForm以在管理应用程序中使用。此表单将覆盖颜色并将其声明为多选字段。我们在这里确实需要选择。
COLORS= (
('R', 'Red'),
('B', 'Yellow'),
('G', 'White'),
)
class CarAdminForm(ModelForm):
color = forms.MultipleChoiceField(choices = COLORS)
class Meta:
model = Car
def clean_color(self):
color = self.cleaned_data['color']
if not color:
raise forms.ValidationError("...")
if len(color) > 2:
raise forms.ValidationError("...")
color = ''.join(color)
return color
Note that I have added only a couple of validations. You may want more and/or customize the validations.
请注意,我只添加了几个验证。您可能需要更多和/或自定义验证。
Finally, register this form with admin. Inside your admin.py:
最后,向管理员注册此表单。在您的admin.py:
class CarAdmin(admin.ModelAdmin):
form = CarAdminForm
admin.site.register(Car, CarAdmin)
回答by makapuf
Use a separate table with colors (Red, Blue, Green), and, as you said, add a many to many relationship ? Choice type is not multiple choice, only a string with added UI and checkings.
使用带有颜色(红色、蓝色、绿色)的单独表格,并且如您所说,添加多对多关系?选择类型不是多项选择,只是添加了 UI 和检查的字符串。
Or, generate procedurally your choices with itertools.combinations, example:
或者,使用 itertools.combinations 程序生成您的选择,例如:
choices = zip(
[''.join(x) for x in itertools.combinations(['','B','R','G'],2)],
[' '.join(x) for x in itertools.combinations(['','Blue','Red','Green'],2)],
)
# now choices = [(' Blue', 'B'), (' Red', 'R'), (' Green', 'G'), ('Blue Red', 'BR'), ('Blue Green', 'BG'), ('Red Green', 'RG')]
回答by FallenAngel
For colors tuple, if you use integers instead of chars, you may use commaseparatedintegerfieldfor your model. But Do not forget, commaseparatedintegerfield is a database level structure,so your DBMS must support it.
对于颜色元组,如果使用整数而不是字符,则可以为模型使用逗号分隔整数字段。但是不要忘记,commaseparatedintegerfield 是一个数据库级别的结构,所以你的DBMS 必须支持它。
回答by Serjik
I've constructed a complete working example with meaningful models. It works perfect. I've tested it on Python 3.4.x and Django 1.8.4. At first I run admin panel and create records for each option in Thema model
我已经用有意义的模型构建了一个完整的工作示例。它完美无缺。我已经在 Python 3.4.x 和 Django 1.8.4 上测试过它。首先我运行管理面板并为 Thema 模型中的每个选项创建记录
models.py
模型.py
from django.db import models
class Author(models.Model):
fname = models.CharField(max_length=50)
lname = models.CharField(max_length=80)
def __str__(self):
return "{0} {1}".format(self.fname, self.lname)
class Thema(models.Model):
THEME_CHOICES = (
('tech', 'Technical'),
('novel', 'Novel'),
('physco', 'Phsycological'),
)
name = models.CharField(max_length=20,choices=THEME_CHOICES, unique=True)
def __str__(self):
return self.name
class Book(models.Model):
name = models.CharField(max_length=50)
author = models.ForeignKey(Author)
themes = models.ManyToManyField(Thema)
def __str__(self):
return "{0} by {1}".format(self.name,self.author)
forms.py
表格.py
from django import forms
from .models import *
class BookForm(forms.ModelForm):
themes = forms.ModelMultipleChoiceField(queryset=Thema.objects, widget=forms.CheckboxSelectMultiple(), required=False)
admin.py
管理文件
from django.contrib import admin
from .models import *
from .forms import *
@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
pass
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
form = BookForm
@admin.register(Thema)
class ThemaAdmin(admin.ModelAdmin):
pass
回答by younesfmgtc
The easiest way I found (just I use eval() to convert string gotten from input to tuple to read again for form instance or other place)
我找到的最简单的方法(只是我使用 eval() 将从输入获得的字符串转换为元组以再次读取表单实例或其他地方)
This trick works very well
这个技巧效果很好
#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()
...

