在Django中隐藏非当前用户创建的条目的更好方法?



我对Django很陌生,现在我已经创建了一个网站,允许用户注册/登录,通过"user"创建与该用户相关的条目。字段。

通过添加只返回当前用户条目的get_queryset()方法,我们成功地获得了隐藏其他用户条目的所有功能。

但是我觉得这是一种不好的方式。我觉得我重用了很多代码,而且可能有后门来显示其他用户的条目。

是否有一种方法可以完全禁用当前用户的其他用户条目,而不仅仅是不显示它?

views.py

class EntryListView(LockedView, ListView):
model = Entry
def get_queryset(self):
return super().get_queryset().filter(user=self.request.user).order_by("-date_created")
class EntryDetailView(LockedView, DetailView):
model = Entry
def get_queryset(self):
return super().get_queryset().filter(user=self.request.user)
class EntryCreateView(LockedView, SuccessMessageMixin, CreateView):
model = Entry
fields = ["title", "content"]
success_url = reverse_lazy("entry-list")
success_message = "Your new entry was created!"
def form_valid(self, form):
user = self.request.user
form.instance.user = user
return super(EntryCreateView, self).form_valid(form)

def get_queryset(self):
return super().get_queryset().filter(user=self.request.user)
class EntryUpdateView(LockedView, SuccessMessageMixin, UpdateView):
model = Entry
fields = ["title", "content"]
success_message = "Your entry was updated!"
def get_success_url(self):
return reverse_lazy(
"entry-detail",
kwargs={"pk": self.object.pk}
)
def get_queryset(self):
return super().get_queryset().filter(user=self.request.user)

创建,详细信息和更新视图是指一个单一的条目(与这个条目的关系是由url kwarg(它可以是通用的'pk'或'slug'等),所以get_queryset在这3个视图实际上并没有帮助。

如果你在浏览器中打开一个条目,你会看到url类似于/Entry/如果你改变那个值你将访问不同的对象。如果你想阻止用户访问不属于他们的条目,你可以创建这样的mixin:

class EntryMixin:
"""
Prevent users to access entries that has different author
"""
def dispatch(self, request, *args, **kwargs):
if not self.get_object().user == request.user:
raise PermissionError
return super().dispatch(request, *args, **kwargs)

这里发生的事情是,每次当用户访问某个视图时,它将检查他是否被分配给该对象(注意,这个mixin只适用于单个对象视图(detail, update, delete),因为list需要修改。

Entry模型创建序列化器,并提供您想要显示的字段。将user字段设置为read_only,以便。

serializers.py

from rest_framework import serializers
class EntriesSerializer(serializers.ModelSerializer):
class Meta:
model = Entry
fields = '__all__'
extra_kwargs = {
'user': {'read_only': True}
}

然后为可以轻松执行crud操作的条目创建一个Viewset。覆盖get_queryset方法来获取当前用户记录。也覆盖perform_create方法,在创建新记录时提供当前用户作为条目用户。

views.py

from rest_framework import viewsets, mixins
from .serializers import EntriesSerializer
class EntriesViewSet(
mixins.CreateModelMixin,
mixins.ListModelMixin,
mixins.RetrieveModelMixin,
mixins.DestroyModelMixin,
mixins.UpdateModelMixin,
viewsets.GenericViewSet
):
serializer_class = EntriesSerializer
def get_queryset(self):
queryset = Entry.objects.filter(user=self.request.user)
return queryset
def perform_create(self, serializer):
serializer.save(user=self.request.user)

为viewset创建一个路由器,并将其注册到路由器。然后在urlpatterns中包含路由器的url。

urls . py

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views
router = DefaultRouter()
router.register('entries', EntriesViewSet, basename='entries')
urlpatterns = [
path('', include(router.urls)),
]

现在您可以通过/entries/访问当前用户创建的所有条目的列表,并使用/entries/<entry_id>/获取单个条目的详细信息。

最新更新