Django:如何为不同的用户提供同一个ManyToManyField的不同选项子集 问题是:
如何在管理中为不同用户提供同一ManyToManyField的不同选项子集,并让每个用户的选择仅影响其选项 情景: 我正在构建一个交互式地图web应用程序。可以有很多地图。可以有许多MapItem。 地图项目可以位于多个地图上,并且地图可以有多个地图项目。因此,有很多关系 每个地图都有一个所有者,我只希望地图的所有者能够从其地图中添加或删除地图项 以下是我的模型的相关部分:Django:如何为不同的用户提供同一个ManyToManyField的不同选项子集 问题是:,django,django-admin,Django,Django Admin,如何在管理中为不同用户提供同一ManyToManyField的不同选项子集,并让每个用户的选择仅影响其选项 情景: 我正在构建一个交互式地图web应用程序。可以有很多地图。可以有许多MapItem。 地图项目可以位于多个地图上,并且地图可以有多个地图项目。因此,有很多关系 每个地图都有一个所有者,我只希望地图的所有者能够从其地图中添加或删除地图项 以下是我的模型的相关部分: class Map(models.Model): # Omit owner = models.Foreig
class Map(models.Model):
# Omit
owner = models.ForeignKey(User, default=1)
class MapItem(models.Model):
# Omit
map = models.ManyToManyField(Map, default=None, blank=True)
MapItem.map由MapItem管理界面上的
表示:
<select multiple="multiple" id="id_map" name="map">
<option value="1">Bob's Map</option>
<option value="2">Sally's Map</option>
</select>
到目前为止还不错。这使我可以选择只包含所需选项的选项:
<select multiple="multiple" id="id_map" name="map">
<option value="1">Bob's Map</option>
</select>
鲍勃的地图
当鲍勃储蓄时,问题就来了。当Bob保存时,它会清除Sally地图的所有保存值。因此,如果选择了Sally的地图,当Bob保存时(即使Bob看不到),Sally的地图将被取消选择
有没有更好的办法解决这个问题?是否有办法确保保存时保持不变的值(如选择了Sally的映射)?尝试覆盖ModelAdmin的
save\u model
方法
在其中,您需要删除属于当前用户的所有关系(而不是删除作为当前行为的所有关系),并保存所有提交的关系(您知道它属于当前用户,因为您过滤了选项,但您可能应该在上一步中重新验证它,因为HTTP请求可能会被篡改)。@lufte的答案很接近,但不是我所需要的。但它确实让我找到了正确的答案。以下是我的解决方案:
save\u model
非常适合调整非多个字段的值。但是,多个字段
在这种方法中不会受到影响,因为无论进行了什么更改
另一方面,save_related
正是我所需要的。我能够确定我的用户应该能够在get_form
中影响哪些地图,并将任何其他地图传递到save_related
中保存
以下是一些代码供参考:
def get_form(self, request, obj=None, **kwargs):
form = super(MapItemAdmin, self).get_form(request, obj, **kwargs)
# Filter already selected maps
# and create a list of map current user can't touch
self.existing_maps = [m.id for m in obj.map.all() \
if not m.owner == request.user and not \
m.groups.filter(id__in=request.user.groups.all())]
# Filter the options that will be displayed in the admin <select>
form.base_fields['map'].queryset = \
form.base_fields['map'].queryset.filter(Q(owner=request.user) \
| Q(groups__in=request.user.groups.all()))
return form
def save_related(self, request, form, formsets, change):
super(MapItemAdmin, self).save_related(request, form, formsets, change)
# Re-add any previously selected maps that the current user can't touch
for em in self.existing_maps:
form.instance.map.add(em)
def get_表单(self、request、obj=None、**kwargs):
form=super(MapItemAdmin,self).获取表单(请求,对象,**kwargs)
#筛选已选择的地图
#并创建当前用户无法触摸的地图列表
self.existing_maps=[obj.map.all()中m的m.id]\
如果不是,则m.owner==request.user,而不是\
m、 groups.filter(id\uu in=request.user.groups.all())]
#筛选将显示在“管理”对话框中的选项
form.base_字段['map']。queryset=\
form.base_字段['map'].queryset.filter(Q(owner=request.user)\
|Q(groups\uu in=request.user.groups.all())
报税表
def保存相关(自我、请求、表单、表单集、更改):
super(MapItemAdmin,self)。与保存相关(请求、表单、表单集、更改)
#重新添加当前用户无法触摸的所有以前选择的地图
对于自存_映射中的em:
form.instance.map.add(em)
如果试图保存无效值,则需要验证输入数据并给出错误。
def get_form(self, request, obj=None, **kwargs):
form = super(MapItemAdmin, self).get_form(request, obj, **kwargs)
# Filter already selected maps
# and create a list of map current user can't touch
self.existing_maps = [m.id for m in obj.map.all() \
if not m.owner == request.user and not \
m.groups.filter(id__in=request.user.groups.all())]
# Filter the options that will be displayed in the admin <select>
form.base_fields['map'].queryset = \
form.base_fields['map'].queryset.filter(Q(owner=request.user) \
| Q(groups__in=request.user.groups.all()))
return form
def save_related(self, request, form, formsets, change):
super(MapItemAdmin, self).save_related(request, form, formsets, change)
# Re-add any previously selected maps that the current user can't touch
for em in self.existing_maps:
form.instance.map.add(em)