到目前为止我发现了什么:
要让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),这里有更多肮脏的技巧(可以做得更好吗?)
您必须从对象中保存查询字段值,然后在字段中手动设置查询集。我的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', ...)
不确定它是否真的按计划在所有情况下都有效。我会继续这个小调查。
问题仍然存在。能不能简单点?