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

2024-03-28 14:27:55 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有这样的模型

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)

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


Tags: name模型modelmodelsredcarlengthmax
3条回答

使用一个单独的颜色表(红色,蓝色,绿色),然后,就像你说的,添加一个多对多的关系? 选择类型不是多项选择,只有一个添加了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')]

我已经用有意义的模型构建了一个完整的工作示例。它工作得很好。我在Python3.4.x和Django1.8.4上测试过。 首先,我运行管理面板并为Thema模型中的每个选项创建记录

模型.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)

表单.py

from django import forms

from .models import *

class BookForm(forms.ModelForm):
    themes = forms.ModelMultipleChoiceField(queryset=Thema.objects, widget=forms.CheckboxSelectMultiple(), required=False)

管理.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

一个Car可以有多个colors吗?在这种情况下color应该是many to many relationship,而不是CharField。另一方面,如果您想做类似Unix permissions(即红色+蓝色、红色+蓝色+绿色等)的事情,则将的数值赋给每个值,并使color成为integer field

更新

(阅读注释后)您可以使用custom form在管理中编辑模型,而不是使用默认的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.py里面:

class CarAdmin(admin.ModelAdmin):
    form = CarAdminForm

admin.site.register(Car, CarAdmin)

相关问题 更多 >