Опция выбора модели Django в виде мультиселектора - PullRequest
10 голосов
/ 27 августа 2010

Предполагая, что у меня есть такая модель

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'),

Ответы [ 4 ]

11 голосов
/ 27 августа 2010

Может ли Car иметь несколько color с?В этом случае color должно быть отношением ко многим , а не CharField.Если, с другой стороны, вы хотите сделать что-то вроде Unix-разрешения (т.е. красный + синий, красный + синий + зеленый и т. Д.), Присвойте числовые значения каждому из них и сделайте color целочисленное поле .

Обновление

(После прочтения комментария) Вы можете использовать пользовательскую форму для редактирования модели в Admin вместо значения по умолчанию ModelForm.Эта пользовательская форма может использовать виджет с множественным выбором, который позволяет пользователям выбирать несколько цветов.Затем вы можете переопределить метод clean() формы для возврата подходящего каскадного значения ('RB' и т. Д.).

Update 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)
4 голосов
/ 31 октября 2015

Я построил полный рабочий пример со значимыми моделями.Работает отлично.Я тестировал его на Python 3.4.x и Django 1.8.4.Сначала я запускаю панель администратора и создаю записи для каждой опции в Thema model

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
1 голос
/ 27 августа 2010

Для кортежа цветов, если вы используете целые числа вместо символов, вы можете использовать commaseparatedintegerfield для вашей модели.Но не забывайте, что commaseparatedintegerfield - это структура уровня базы данных, поэтому ваша СУБД должна поддерживать ее.

Документация ссылка ...

1 голос
/ 27 августа 2010

Использовать отдельную таблицу с цветами (красный, синий, зеленый) и, как вы сказали, добавить отношения многие ко многим?Тип выбора не множественный выбор, только строка с добавленным пользовательским интерфейсом и проверками.

Или сгенерируйте процедурный выбор с помощью itertools.combinsk, например:

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')]
...