【问题标题】:Django admin handling one to many relationDjango 管理员处理一对多关系
【发布时间】:2010-08-01 08:30:44
【问题描述】:

我有一个如下的 django 模型

class Project(models.Model)
      name=models.CharField(max_length=200)

class Application(models.Model)
      proj=models.ForeignKey(Project, null=True, blank=True)

我需要修改项目的管理表单,以便能够为项目分配多个应用程序,因此在 admin.py 中我为项目创建了一个 ModelAdmin 类,如下所示

class ProjectAdmin(ModelAdmin)
      form=projectForm
      project_apps=[]

项目形式如下

class ProjectForm(forms.ModelForm):
    class Meta:
       model = Project

    project_apps =forms.ModelMultipleChoiceField(queryset=Application.objects.all(),required=False,)
def __init__(self, *args, **kwargs):
    super(ProjectForm, self).__init__(*args, **kwargs)
    if self.instance.id is not None:
        selected_items = [ values[0] for values in Application.objects.filter(project=self.instance) ]
        self.fields['project_apps'].initial = selected_items

def save(self,commit=True):
    super(ProjectForm,self).save(commit)
    return self.instance

通过这样做,我可以在创建/编辑项目表单中进行多项选择。 我需要的是覆盖保存方法以在所选应用程序中保存项目的引用?

我怎样才能获得选定的应用程序????

【问题讨论】:

  • 你为什么不直接使用内联管理员?
  • 我使用了它,但它添加了 3 个组合框,我希望它在多个选择列表中

标签: django django-admin django-forms


【解决方案1】:

不完全确定您要做什么,但也许是这个?

def save(self,commit=True):
    kwargs.pop('commit') # We're overriding this with commit = False
    super(ProjectForm,self).save(commit)
    if self.instance:
        for a in self.cleaned_data['project_apps']:
            a.proj = self.instance
            a.save()
    return self.instance

现在,我不记得在这种情况下,self.cleaned_data['project_apps'] 是否实际上包含Application 对象的列表。我怀疑它会,但如果不是,这个函数会解决这个问题:

def clean_project_apps(self):
    app_list = self.cleaned_data['project_apps']
    result = []
    for a in app_list:
        try:
            result.append(Application.objects.get(pk=a)
        except Application.DoesNotExist:
            raise forms.ValidationError("Invalid application record") # to be safe
    return result

总而言之,我认为这种形式是个坏主意,因为基本上这里发生的情况是您正在显示 所有 没有意义的应用程序记录,因为它们中的大多数将与其他项目相关联。

哦哦哦!!!刚刚注意到您希望它显示在多选列表中!

你(可能)做错了

多选意味着这不是一对多的关系。 这是多对多的关系。

这就是您想要做的,简单易行,不需要任何自定义表单或任何东西

class Project(models.Model)
      name=models.CharField(max_length=200)
      project_apps = models.ManyToMany('Application', null=True, blank=True)

class Application(models.Model)
      # nothing here (NO foreign key, you want more than one App/Proj and vice versa)

表示这是 Project 中的多对多字段将自动在 admin 中创建多选框。哒哒!

【讨论】:

  • 我想补充一点,如果不是,你真的希望它是一对多的关系,那么多选框是错误的界面。这就像制造一辆汽车,右转意味着加速,而左转意味着减速。多选字段的意思是“看,对于任何给定的记录,您可以选择一个或多个这些选项!”那是多对多的关系。如果您的意思是“这些是这个主要项目的潜在子项”,那么这不是正确的界面,尽管您个人不喜欢它,但内联管理员是正确的界面。
猜你喜欢
  • 2010-12-14
  • 2012-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-01
  • 2010-10-14
相关资源
最近更新 更多