Как избежать повторения набора запросов в 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.

Вернуться на верх