Django 管理处理一对多关系

发布于 2024-09-12 11:53:12 字数 1095 浏览 3 评论 0原文

我有一个 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

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

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

I have a django model as following

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

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

I need to modify the admin form of the project to be able to assign multiple applications to the project, so in the admin.py I have created a ModelAdmin class for the project as following

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

and the project form as following

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

by doing this I have a multiple select in the create/edit project form.
what I need is to override the save method to save a reference for the project in the selected applications?

how can I get the selected applications ????

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烈酒灼喉 2024-09-19 11:53:12

不完全确定你想做什么,但也许这个?

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 中的多对多字段,将在管理中自动创建多选框。哒哒!

Not entirely sure what you're trying to do, but maybe this?

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

Now, I can't remember if in this case, self.cleaned_data['project_apps'] will actually contain a list of Application objects or not. I suspect it will, but if not this function will take care of that:

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

All in all I think this form is a bad idea though, because basically what is happening here is you're displaying all of the application records which doesn't make sense, since most of them will be associated with other projects.

Oh oh oh!!! Just noticed you wanted this to show up in a Multiple Select list!

You're (probably) doing it wrong

A multiple select means this isn't a one-to-many relationship. It's a many-to-many relationship.

This is what you want to do, easy peasy, doesn't require any custom forms or anything.

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)

Indicating that this is a many-to-many field in Project will automagically create the multiple select box in admin. Ta da!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文