Как избежать повторения набора запросов в Django views.py
как лучше всего избежать повторения фрагмента кода, который используется более чем в одном представлении класса?
Я повторяю эти 2 строки в нескольких классах
moderator = ServerModerator.objects.get(user=request.user)
server = Server.objects.get(Q(creator=request.user) | Q(moderators=moderator), Q(tag=server_tag))
Я пытался создать функцию внутри models.py
следующим образом:
class Server(models.Model):
...
creator = models.ForeignKey(User , on_delete=models.CASCADE, related_name='user_servers')
moderators = models.ManyToManyField('ServerModerator', related_name='server')
def moderator_checker(self, current_user):
moderator = ServerModerator.objects.get(user=current_user)
server = Server.objects.get(Q(creator=current_user) | Q(moderators=moderator),Q(tag=self.tag))
return server
но это не работает
views.py:
class TagsAndFlairsView(LoginRequiredMixin, View):
form_class = CreatePostTagForm
form_class_2 = CreateUserTagForm
def get(self, request, server_tag):
...
# moderator = ServerModerator.objects.get(user=request.user)
# server = Server.objects.get(Q(creator=request.user) | Q(moderators=moderator), Q(tag=server_tag))
check = Server.moderator_checker(request.user)
server_post_tags = check.post_tags.all()
server_user_tags = check.user_tags.all()
return render(request, 'servers/tags-flairs.html', {"server":check, "server_post_tags":server_post_tags, "server_user_tags":server_user_tags, "create_post_tag_form":create_post_tag_form, "create_user_tag_form":create_user_tag_form})
Вы можете создать пользовательский набор запросов:
class ServerQuerySet(models.QuerySet):
def check_moderator(self, current_user, tag):
moderator = get_object_or_404(ServerModerator, user=current_user)
self = self.get(Q(creator=current_user) | Q(moderators=moderator),Q(tag=tag))
return self
Затем в модели сервера определите:
objects = ServerQuerySet.as_manager()
Теперь вы можете сделать:
server = Server.objects.check_moderator(request.user, tag) # EXAMPLE OF USER
Наборы запросов также позволяют делать несколько других вещей. Например, теперь вы можете отфильтровать результаты перед тем, как проверить, является ли пользователь модератором.
Это очень удобно, например, если у вас есть поле "активный" или что-то в этом роде. Server.objects.filter(server_is_active=True).check_moderator(request.user, tag)
.
Note:
Вообще, лучше использоватьget_object_or_404()
вместоget()
, поскольку он вызывает get() на данном менеджере модели, но вызывает Http404 вместо исключения DoesNotExist.