How to avoid repeating a chunk of code in Django views.py

Question:

What is the best way to avoid repeating a chunk of code that is being used in more than one class view?

I’m repeating these 2 lines in couple of classes.

moderator = ServerModerator.objects.get(user=request.user)
server = Server.objects.get(Q(creator=request.user) | Q(moderators=moderator), Q(tag=server_tag))

I’ve tried to create a function inside models.py like this:

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

but this doesn’t work.

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})
Asked By: Navid Azimi

||

Answers:

You can create a custom queryset:

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

Then in your Server model, define:

objects = ServerQuerySet.as_manager()

Now you can do:

server = Server.objects.check_moderator(request.user, tag) # EXAMPLE OF USER

QuerySets also allow you to do a few other things. You can now for example; filter down the results before checking if the user is a moderator.
This is great for example, if you have an ‘active’ field or anything of the sorts. Server.objects.filter(server_is_active=True).check_moderator(request.user, tag).

Note: Generally, it is better to use get_object_or_404() instead of get() as it calls get() on a given model manager, but it raises Http404 instead of the model’s DoesNotExist exception.

Answered By: nigel239