我的models.py
就像这样:
class Category(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=256, db_index=True)
class Todo(models.Model):
user = models.ForeignKey(User)
category = models.ForeignKey(Category)
...
我想将Category
Todo
的选择仅限于那些Todo.user
= Category.user
我发现的每个解决方案都是为表单内的ModelForm
或实现方法设置查询集。 (与limit_choices_to
一样,不可能(?))
问题在于我不仅有一个具有此类限制问题的模型(例如Tag
等)。
另外,我正在使用django REST框架,因此我必须在添加或编辑Category
时检查Todo
。
因此,我还需要序列化程序中的函数validate
来正确限制模型(因为它不会调用模型的clean
,full_clean
方法,也不会检查limit_choices_to
)< / p>
所以,我正在寻找一个简单的解决方案,它将适用于django Admin和REST框架。
或者,如果不可能以简单的方式实现它,我正在寻找如何以最无痛的方式编写代码的建议。
答案 0 :(得分:1)
这是我迄今为止所发现的:
要在管理员中显示Foreignkey
权限,您必须在ModelAdmin
class TodoAdminForm(ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['category'].queryset = Category.objects.filter(user__pk=self.instance.user.pk)
@admin.register(Todo)
class TodoAdmin(admin.ModelAdmin):
form = TodoAdminForm
...
要让ManyToManyField
显示在InlineModelAdmin
(例如TabularInline
),这里会出现更多脏问题(可以做得更好吗?)
您必须从对象中保存您的quiring字段值,然后在字段中手动设置queryset。我的through
模型有两个成员todo
和tag
我想过滤tag
字段(指向模型Tag
):
class MembershipInline(admin.TabularInline):
model = Todo.tags.through
def get_formset(self, request, obj=None, **kwargs):
request.saved_user_pk = obj.user.pk # Not sure if it can be None
return super().get_formset(request, obj, **kwargs)
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
if db_field.name == 'tag':
kwargs['queryset'] = Tag.objects.filter(user__pk=request.saved_user_pk)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
最后,为了将元素仅限于Django REST框架中的相关元素,我必须实现自定义Field
class PrimaryKeyRelatedByUser(serializers.PrimaryKeyRelatedField):
def get_queryset(self):
return super().get_queryset().filter(user=self.context['request'].user)
并在我的序列化工具中使用它,如
class TodoSerializer(serializers.ModelSerializer):
category = PrimaryKeyRelatedByUser(required=False, allow_null=True, queryset=Category.objects.all())
tags = PrimaryKeyRelatedByUser(required=False, many=True, queryset=Tag.objects.all())
class Meta:
model = Todo
fields = ('id', 'category', 'tags', ...)
不确定它是否按计划在所有情况下实际运行。我将继续这个小调查。
问题仍然存在。可以简化吗?