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})
CodePudding user response:
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 useget_object_or_404()
instead ofget()
as it calls get() on a given model manager, but it raises Http404 instead of the model’s DoesNotExist exception.