Группировка много-много вариантов по типу в форме - PullRequest
1 голос
/ 22 марта 2012

У меня есть Песочница, которая содержит множество предметов, состоящих из одного или больше атрибутов. Каждый атрибут принадлежит определенному типу атрибута (например, цвет, форма и т. Д.) Я в растерянности от того, как визуализировать форму с атрибутами, сгруппированными вместе с их типами атрибутов.

Модель

class Sandbox(models.Model):
    item = models.ForeignKey('Item')

class Item(models.Model):
    name = models.CharField()
    sandbox = models.ForeignKey(Sandbox)
    attributes = models.ManyToManyField('Attribute')

class Attribute(models.Model):
    name = models.CharField()
    type = models.ForeignKey('AttributeType')

class AttributeType(models.Model):
    name = models.CharField()

class ItemAttribute(models.Model):
    # intermediary model to hold references
    item = models.ForeignKey(Item)
    type = models.ForeignKey(AttributeType)
    attribute = models.ForeignKey(Attribute)

ModelForm

class Sandbox(ModelForm):
    class Meta:
        model = Sandbox

Для каждого типа атрибута может быть только один выбор. Например, что-то может иметь только один цвет или одна форма.

    AttributeType   Attribute       Users choice
    color
                    red
                    blue            [x]
                    green
                    shape

    shape
                    triangular
                    squared         [x]
                    spherical

Это я застрял. Как мне сгруппировать эти атрибуты вместе в форме и как с помощью переключателей выбрать только один атрибут для каждого типа? Возможно, моя оригинальная идея иметь простое представление модели здесь не подходит? Я пробовал документацию, StackOverflow и Google, но не повезло.

Любые советы и идеи приветствуются.

Мое решение

Я создал решение, которое удовлетворяет моим потребностям. @bmihelac указал мне хорошее направление на эту статью о том, как создать фабричный метод для создания пользовательской формы. [см. ниже]

def make_sandbox_form(item):

    def get_attributes(item):
        item_attributes = ItemAttribute.objects.filter(item=item)
        # we want the first attribute type
        _attr_type = item_attributes[0].attribute.all()[0].attribute_type

        choices = []        # holds the final choices
        attr_fields = {}    # to hold the final list of fields
        for item_attrs in item_attributes.all():
            attributes = item_attrs.attribute.all().order_by('attribute_type')
            for attr in attributes:
                print attr.attribute_type, ' - ' , _attr_type
                if attr.attribute_type == _attr_type:
                    choices.append( ( attr.pk, attr.value ) )
                else:
                    d = {u'%s' % _attr_type : fields.ChoiceField(choices=choices, widget=RadioSelect)}
                    attr_fields = dict(attr_fields.items() + d.items() )
                    # set the _attr_type to new type and start over with next attribute type
                    _attr_type = attr.attribute_type
                    choices = []

        return attr_fields

    form_fields = {
        'item' : fields.IntegerField(widget=HiddenInput),
    }
    form_fields = dict(form_fields.items() + get_attributes(item).items())

    return type('SandboxForm', (forms.BaseForm, ), { 'base_fields' : form_fields})

Вызвать форму моего вызова этого фабричного метода как: form = make_sandbox_form ()

http://www.b -list.org / блог / 2008 / Ноябрь / 09 / динамические-формы /

(Хотелось бы, чтобы я проголосовал против всех, кроме того, что я новичок в StackOverflow, и мне не хватает на это репутации.)

Ответы [ 2 ]

1 голос
/ 22 марта 2012

Я бы создал динамическую форму, создав одно поле выбора для каждого AttributeType.

Затем вы можете легко заменить виджет переключателями.

Эта статья может быть полезна:

http://www.b -list.org / weblog / 2008 /ноябре / 09 / динамическая-форма /

1 голос
/ 22 марта 2012

Может ли одна песочница иметь много предметов, или у одного предмета много песочниц?Может ли элемент принадлежать нескольким песочницам одновременно?

Я думаю, вы хотите, чтобы в одной песочнице содержалось много элементов:

class Sandbox(models.Model):
    name = models.CharField()

class Item(models.Model):
    name = models.CharField()
    sandbox= models.ForeignKey(Sandbox)
    attributes = models.ManyToManyField('Attribute')

Тот же самый анализ верен здесь:

один атрибут имеет много типов атрибутов, или один тип атрибута имеет много атрибутов?

Здесь у вас есть правильное отношение, я просто изменил порядок моделей

class AttributeType(models.Model):
    name = models.CharField()

class Attribute(models.Model):
    name = models.CharField()
    type = models.ForeignKey(AttributeType)

Таким образом, у каждого элемента естьатрибут, и они всегда наделены этими атрибутами, цветом и формой.

Хотя у вас может быть таблица с данными, которые выглядят так:

pk type
1 green
2 circular
etc

Лично я бы этого не сделал,потому что я думаю, что данные, которые логически одинаковы, должны быть сгруппированы вместе.Фигуры имеют разные атрибуты, чем цвета.Например, чтобы проиллюстрировать мою точку зрения, что если вы хотите RGB цвета?Тогда у вас будут дополнительные столбцы для фигур, когда они не нужны, и это сбивает с толку.То же самое верно в обратном, цвета не имеют размерности.

Вместо этого я мог бы сделать что-то вроде:

class Color(models.Mode):
     #info about colors

class Shape(models.Mode):
     #info about shapes

class Item(models.Model):
    name = models.CharField()
    sandbox= models.ForeignKey(Sandbox)
    color= models.ForeignKey(Color)
    shape= models.ForeignKey(Shape)

Это также гарантирует, что у вас есть только один выбор, потому что ForeignKey вdjango.Forms по умолчанию использует ChioceField (iirc).

Что касается переопределения этого и создания его радиокнопки, просто просмотрите документы здесь:

https://docs.djangoproject.com/en/dev/ref/forms/widgets/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...