nbe*_*hat 5 python django many-to-many django-admin
我正在尝试增强 django 管理界面,类似于在此 SO 帖子的已接受答案中所做的工作。我有一张User桌子和一张Project桌子之间的多对多关系。在 Django 管理员中,我希望能够将用户分配到一个项目,如下图所示:

它在一个简单的情况下工作正常,ManyToManyField但问题是我的模型使用 的through参数ManyToManyField来使用中间表。我无法使用save_m2m()andset()函数,而且我对如何调整下面的代码以使其工作一无所知。
该模型:
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)
...
Run Code Online (Sandbox Code Playgroud)
用于小部件的代码admin.py:
from django.contrib.admin.widgets import FilteredSelectMultiple
class ProjectAdminForm(forms.ModelForm):
class Meta:
model = Project
fields = "__all__" # not in original SO post
userprofiles = forms.ModelMultipleChoiceField(
queryset=UserProfile.objects.all(),
required=False,
widget=FilteredSelectMultiple(
verbose_name='User Profiles',
is_stacked=False
)
)
def __init__(self, *args, **kwargs):
super(ProjectAdminForm, self).__init__(*args, **kwargs)
if self.instance.pk:
self.fields['userprofiles'].initial = self.instance.userprofile_set.all()
def save(self, commit=True):
project = super(ProjectAdminForm, self).save(commit=False)
if commit:
project.save()
if project.pk:
project.userprofile_set = self.cleaned_data['userprofiles']
self.save_m2m()
return project
class ProjectAdmin(admin.ModelAdmin):
form = ProjectAdminForm
...
Run Code Online (Sandbox Code Playgroud)
注意:中间模型中的所有额外字段都不需要在项目管理视图中更改(它们是自动计算的)并且它们都有一个默认值。
谢谢你的帮助!
我可以找到解决这个问题的方法。这个想法是:
为此,我替换了:
if project.pk:
project.userprofile_set = self.cleaned_data['userprofiles']
self.save_m2m()
Run Code Online (Sandbox Code Playgroud)
经过:
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()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1358 次 |
| 最近记录: |