[英]Django's Generic Views: how to filter get_queryset based on foreign class attributes?
[英]Django get_queryset has different signature for Admin and Generic views, how to prevent code duplication
我想編寫簡單的代碼來根據請求信息(例如用戶所屬的組織)過濾視圖中的記錄。
我開始將它實現為管理視圖的 Mixin。
class OrganizationPermissionMixin:
def get_queryset(self, request):
query = super().get_queryset(request)
if request.user.is_superuser:
return query
return query.filter(
organization__in=request.user.organization_set.all()
)
這工作正常,但是當我嘗試在通用視圖上應用此 Mixin 時,出現簽名錯誤,因為沒有請求參數傳遞給get_queryset
方法:
TypeError: OrganizationPermissionMixin.get_queryset() missing 1 required positional argument: 'request'
如果我將 Mixin 調整為:
class OrganizationPermissionMixin:
def get_queryset(self):
query = super().get_queryset()
if self.request.user.is_superuser:
return query
return query.filter(
organization__in=self.request.user.organization_set.all()
)
它適用於ListView
等通用視圖,但現在它確實無法用於ModelAdmin
視圖:
OrganizationPermissionMixin.get_queryset() takes 1 positional argument but 2 were given
簽名中的這種不一致在某種程度上非常令人沮喪,因為它需要復制代碼只是因為通用視圖和管理視圖之間的請求傳遞機制不同。
我的問題是:如何讓這個 Mixin 同時適用於通用視圖和管理視圖。 在 Django 中有什么准備好嗎? 它的行為是正常的還是不幸的設計選擇?
該request
不會作為基於類的視圖中的查詢集傳遞。 然而,它在ModelAdmin
中,您可以通過以下方式協調兩者:
class OrganizationPermissionMixin:
def get_queryset(self, *args, **kwargs):
request = args[0] if args else kwargs.get('request') or self.request
query = super().get_queryset(*args, **kwargs)
if request.user.is_superuser:
return query
return query.filter(organization__user=request.user)
因此它將首先嘗試從kwargs
獲取請求。 如果返回None
,它將“回退” self.request
,這是基於類的視圖的情況。
ModelAdmin
的建模非常糟糕。 例如,它重用了相同的 object,因此沒有在 object 中編碼的請求。它還將各種視圖組合在一起。 已經有人提議重新設計 modeladmin,但不幸的是,由於向后兼容,這些目前尚未實施。
也許是這樣的:
...
def get_queryset(self, *args, **kwargs):
request = kwargs.get("request", None)
if request:
query = super().get_queryset(request)
else:
query = super().get_queryset()
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.