Django模型设计 - 多对多字段

时间:2015-03-13 15:37:24

标签: python django django-models django-forms

来自php背景,我知道我将如何做到这一点'手工'但我似乎无法理解如何使用Django ORM构建我的数据库。

该应用以核对清单为中心。清单有一些识别功能,例如NameDateOfBirthChecklistType

有几个ChecklistType,每个都有ChecklistOption个。{ ChecklistOption可能包含或不包含多个ChecklistType

我最初的想法是为ChecklistTypeChecklistTypeOptions创建一个模型来存储“配置”。检查表的列表,以及ChecklistRequirements(分别)的单独模型,以链接到Customer模型。我以为我会手动查找配置并在创建Customer的视图中创建后面的模型条目。然后我意识到这个失败指向了ORM!

我确信通过正确理解模型中使用多对多字段的方法可以解决这个问题,但Django Documentation似乎只处理这个问题的简单应用。如果我在ChecklistChecklistOptionChecklistType作为ChoiceField)中创建了ManyTomany字段,则我将无法指定哪些选项适用于该类型。

我确定这类事情必须经常进行,但我无法理解它。

提前致谢,

澄清 - 示例数据

ChecklistOptions

Cheese {boolean}
Tomato {boolean}
Bacon {boolean}
Chicken {boolean}
Coffee {boolean}
Pepperoni {boolean}
Salami {boolean}
Mushrooms {boolean}
Eggs {boolean}

ChecklistTypes

ThingsToPutOnPizza: {options: Cheese, Tomato, Bacon, Chicken, Salami, Mushrooms}
ThingsToEatAtBreakfast: {options: Cheese, Bacon, Coffee, Eggs}

客户

John Smith: {Name: "John Smith", DOB: 1984-12-17, Checklist: ThingsToEatAtBreakfast}
Jane Jones: {Name: "Jane Jones", DOB: 1987-07-22, Checklist: ThingsToPutOnPizza}
Frank Allen {Name: "Frank Allen", DOB: 1990-04-01, Checklist: ThingsToPutOnPizza}

工作流

用户创建客户,并选择清单类型。另一位用户必须完成'清单,因此从列表中选择客户,并显示该清单类型中的选项的复选框列表,以及这些选项可以勾选一些而不是其他选项。在保存表单/模型时,将用户和时间记录在核对表中以将其标记为完成。

2 个答案:

答案 0 :(得分:1)

这可能是最简单的解决方案:

models.py

from django.db import models

class CheckList(models.Model):
    name = models.CharField(max_length=255)
    checklist_type = models.ForeignKey('CheckListType')
    options = models.ManyToManyField('CheckListOption', blank=True)

    def __unicode__(self):
        return self.name

class CheckListType(models.Model):
    name = models.CharField(max_length=255)
    options = models.ManyToManyField('CheckListOption')

    def __unicode__(self):
        return self.name

class CheckListOption(models.Model):
    name = models.CharField(max_length=255)

    def __unicode__(self):
        return self.name

forms.py

from django import forms

from .models import CheckList, CheckListOption

class CheckListForm(forms.ModelForm):
    class Meta:
        model = CheckList
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super(CheckListForm, self).__init__(*args, **kwargs)
        if self.instance.pk:
            self.fields['options'].queryset = CheckListOption.objects.filter(
                checklisttype=self.instance.checklist_type_id
            )
        else:
            self.fields['options'].queryset = CheckListOption.objects.none()

admin.py

from django.contrib import admin

from .forms import CheckListForm
from .models import CheckList, CheckListType, CheckListOption

class CheckListAdmin(admin.ModelAdmin):
    form = CheckListForm

admin.site.register(CheckList, CheckListAdmin)
admin.site.register(CheckListType)
admin.site.register(CheckListOption)

只有一个缺点 - 如果您已经有一个已保存的CheckList实例并且想要更改checklist_type,那么目前您将无法获得新的options。执行更改的用户应取消选择所选选项(这是一种可选项,但如果没有完成,所选选项将保留到下一次保存),保存模型并再次编辑以选择新的选择。

答案 1 :(得分:0)

让我们从基本要求开始:

  

该应用以核对清单为中心。 Checklist有一些识别   功能,让我们说NameDateOfBirthChecklistType

     

有几个ChecklistType,每个都有很多   ChecklistOption秒。 ChecklistOption可能有几个,也可能没有   ChecklistTypeŠ

以下型号可满足您的初始要求:

class CheckListOption(models.Model):
    name = models.CharField(max_length=200)

class CheckListType(models.Model):
    name = models.CharField(max_length=200)
    options = models.ManyToManyField(CheckListOption)

class Checklist(models.Model):
    name = models.CharField(max_length=200)
    dob = models.DateField()
    type = models.ForeignKey(CheckListType)

现在,考虑到这些;让我们看看你打算如何使用这些模型:

  

用户创建客户,并选择清单类型。另一个   用户必须“完成”清单,因此从中选择客户   列表,并显示选项的复选框列表   清单类型,以及那些选项,他们可能会勾选一些而不是   其他。在保存表单/模型时,会记录用户和时间   根据清单将其标记为完整。

要管理您的跟踪,您需要在Checklist模型中添加更多字段:

class Checklist(models.Model):
    name = models.CharField(max_length=200)
    dob = models.DateField()
    type = models.ForeignKey(CheckListType)
    created_by = models.ForeignKey(User, name='creator')
    created_on = models.DateTimeField(auto_now_add=True)
    completed_by = models.ForeignKey(User,
                                     name='maker', blank=True, null=True)
    completed_on = models.DateTimeField(blank=True, null=True)

    def is_complete(self):
        return self.completed_on

为了满足您对“以及他们可能勾选某些选项而非其他选项的要求,您需要通过创建自定义{修改CheckListType模型{3}};这将允许您指定关系的选项:

class CheckListOptionConfig(models.Model):
    checklisttype = models.ForeignKey('CheckListType')
    optiontype = models.ForeignKey('CheckListOption')
    is_required = models.BooleanField(default=False)

class CheckListType(models.Model):
    name = models.CharField(max_length=200)
    options = models.ManyToManyField(CheckListOption, through='CheckListOptionConfig')

工作流程的其余部分描述了用户界面;如果没有勾选正确的选项,可以很容易地配置显示警报/警告的所有方式。