Django管理界面:使用horizo​​ntal_filter和ManyToMany字段和中间表

时间:2017-06-23 06:24:39

标签: python django django-admin many-to-many

我正在尝试增强django管理界面,类似于this SO post中接受的答案。我在User表和Project表之间存在多对多关系。在django管理员中,我希望能够将用户分配到项目,如下图所示: Widget to use in Project admin interface

使用简单的ManyToManyField工作正常但问题是我的模型使用through的{​​{1}}参数来使用中间表。我无法使用ManyToManyFieldsave_m2m()函数,我对如何调整下面的代码以使其工作无能为力。

模特:

set()

class UserProfile(models.Model): user = models.OneToOneField(User, unique=True) projects = models.ManyToManyField(Project, through='Membership') class Project(models.Model): name = models.CharField(max_length=100, unique=True) application_identifier = models.CharField(max_length=100) type = models.IntegerField(choices=ProjectType) ... class Membership(models.Model): project = models.ForeignKey(Project,on_delete=models.CASCADE) user = models.ForeignKey(UserProfile,on_delete=models.CASCADE) # extra fields rating = models.IntegerField(choices=ProjectType) ... 中用于窗口小部件的代码:

admin.py

注意:中间模型中的所有额外字段不需要在Project Admin视图中更改(它们是自动计算的),并且它们都具有默认值。

感谢您的帮助!

1 个答案:

答案 0 :(得分:4)

我能找到解决这个问题的方法。这个想法是:

  1. 当且仅当它们是新的时,在Membership表中创建新条目(否则它将擦除Membership表中其他字段的现有数据)
  2. 删除从“成员资格”表中取消选择的条目
  3. 要做到这一点,我换了:

    if project.pk:
        project.userprofile_set = self.cleaned_data['userprofiles']
        self.save_m2m()
    

    通过:

    if project.pk:
        # Get the existing relationships
        current_project_selections = Membership.objects.filter(project=project)
        current_selections = [o.userprofile for o in current_project_selections]
    
        # Get the submitted relationships
        submitted_selections = self.cleaned_data['userprofiles']
    
        # Create new relation in Membership table if they do not exist
        for userprofile in submitted_selections :
            if userprofile not in current_selections:
                Membership(project=project,userprofile=userprofile).save()
    
        # Remove the relations that were deselected from the Membership table
        for project_userprofile in current_project_selections:
            if project_userprofile.userprofile not in submitted_selections :
                project_userprofile.delete()