django模型选择选项作为多选框

时间:2010-08-27 08:41:36

标签: python django django-models

假设我有这样的模特

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)

它在管理面板中显示为选择框但是我希望我的管理员用户多选择那些颜色,如多对多关系,如何在没有('RB', 'Red&Blue'),类型逻辑的情况下实现这一点

5 个答案:

答案 0 :(得分:10)

Car可以有多个color吗?在这种情况下,color应该是many to many relationship而不是CharField。另一方面,如果你想做Unix permissions之类的事情(即红+蓝,红+蓝+绿等),则为每一项分配数值,并使color成为{{3 }}。

<强>更新

(阅读评论后)您可以使用integer field在管理员中修改模型,而不是默认的ModelForm。此自定义表单可以使用多选小部件,用户可以选择多种颜色。然后,您可以覆盖表单的clean()方法以返回适当连接的值('RB'等)。

更新2

以下是一些代码:

首先,从模型字段中删除选项。同时将其最大尺寸增加到2.我们不想在这里做出选择 - 如果我们这样做,那么我们必须为每种颜色组合添加一个选择。

class Car(models.Model):
    ...
    color= models.CharField(max_length=2)

第二次添加自定义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

请注意,我只添加了几个验证。您可能需要更多和/或自定义验证。

最后,使用admin注册此表单。在admin.py

class CarAdmin(admin.ModelAdmin):
    form = CarAdminForm

admin.site.register(Car, CarAdmin)

答案 1 :(得分:4)

我用有意义的模型构建了一个完整的工作示例。它完美无缺。我在Python 3.4.x和Django 1.8.4上测试过它。 首先,我运行管理面板并为Thema模型中的每个选项创建记录

models.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

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

答案 2 :(得分:1)

使用带有颜色(红色,蓝色,绿色)的单独表格,如您所说,添加多对多关系? 选择类型不是多项选择,只是添加了UI和检查的字符串。

或者,使用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')]

答案 3 :(得分:1)

对于颜色元组,如果使用整数而不是字符,则可以对模型使用 commaseparatedintegerfield 。 但不要忘记,commaseparatedintegerfield是一个数据库级结构,因此您的DBMS必须支持它。

Documentation link...

答案 4 :(得分:0)

我发现的最简单的方法(只是我使用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()
            ...
相关问题