【发布时间】:2010-10-26 13:44:33
【问题描述】:
给定一个具有 ForeignKeyField (FKF) 或 ManyToManyField (MTMF) 字段的模型,其中外键为“self”,我如何防止在 Django Admin (admin) 中进行 self(递归)选择。
简而言之,应该可以防止在管理员中自我(递归)选择模型实例。这适用于编辑模型的现有实例,而不是创建新实例。
例如,新闻应用中的文章采用以下模型;
class Article(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField()
related_articles = models.ManyToManyField('self')
如果有 3 个 Article 实例(标题:a1-3),当通过管理员编辑现有的 Article 实例时,related_articles 字段默认由 html(多个)选择框表示,该框提供所有文章列表 (Article.objects.all())。用户应该只能看到并能够选择 Article 实例而不是它自己,例如编辑时Article a1, related_articles 可供选择= a2, a3。
我目前可以看到 3 种可能的方法来做到这一点,按偏好递减的顺序排列;
- 提供一种方法来设置查询集,在管理表单字段中为
related_articles提供可用选项(通过排除查询过滤器,例如Article.objects.filter(~Q(id__iexact=self.id)),以从用户可以看到的相关文章列表中排除当前正在编辑的实例并从中选择。要使用的查询集的创建/设置可能发生在自定义Article ModelForm的构造函数 (__init__) 中,或者通过某种动态limit_choices_to Model选项发生。这需要一种获取实例的方法正在编辑以用于过滤。 - 覆盖
Article Model或ModelAdmin类的save_model函数以在保存实例之前检查并从related_articles中删除自身。这仍然意味着管理员用户可以查看和选择所有文章,包括正在编辑的实例(对于现有文章)。 - 当需要在管理员之外使用时过滤掉自我引用,例如模板。
理想的解决方案 (1) 目前可以通过管理外部的自定义模型表单来完成,因为可以将正在编辑的实例的过滤查询集变量传递给模型表单构造函数。问题是,您能否访问 Article 实例,即在创建表单之前正在编辑“自我”以执行相同的操作。
这可能是我的处理方式错误,但如果您允许将 FKF / MTMF 定义为同一模型,那么应该有一种方法让管理员 - 做正确的事 - 并通过将用户排除在可用选项列表中来防止用户选择自己。
注意:现在可以执行解决方案 2 和 3,并且提供解决方案 2 和 3 是为了尽量避免将这些作为答案,理想情况下我希望得到解决方案 1 的答案。
【问题讨论】:
标签: django django-models django-admin foreign-keys many-to-many