I have a question on where to put some logic inside a view.
CONCEPT: To create a social media app like Twitter. There is a user profile with follow or unfollow buttons, which depends on if you’re already following the user. If you already follow, the button says “unfollow” and “follow” otherwise.
The question is: where to put this following/unfollowing logic.
1. Models.
#models.py - Profile
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
follows = models.ManyToManyField(
"self", related_name="followed_by", symmetrical=False, blank=True
)
date_modified = models.DateTimeField(User, auto_now=True)
def __str__(self):
return self.user.username
2. HTML form
<!-- profile.html -->
<form method="POST">
{% csrf_token %}
{% if profile in user.profile.follows.all %}
<button class="btn btn-outline-danger" name="follow-btn" value="unfollow" type="submit">
Unfollow @{{profile.user.username|lower}}
</button>
{% else %}
<button class="btn btn-outline-success" name="follow-btn" value="follow" type="submit">
Follow @{{profile.user.username|lower}}
</button>
{% endif %}
</form>
3. View
Two approaches to the logic in the view.
Which one do you think is best?
A) OPTION 1: request the user profile and check the following state in the same function.
#views.py - OPTION 1
from django.shortcuts import get_object_or_404
def profile(request, pk):
if request.user.is_authenticated:
profile = get_object_or_404(Profile, user_id=pk)
context = {"profile": profile}
if request.method == "POST":
current_user_profile = request.user.profile
action = request.POST["follow-btn"]
if action == "unfollow":
current_user_profile.follows.remove(profile)
elif action == "follow":
current_user_profile.follows.add(profile)
current_user_profile.save()
return render(request, "profile.html", context)
else:
messages.success(request, "You must be logged in to view this page")
return redirect("home")
B) OPTION 2: request the user profile and check the followers state in separate functions.
#views.py - OPTION 2
from django.shortcuts import get_object_or_404
def profile(request, pk):
if request.user.is_authenticated:
profile = get_object_or_404(Profile, user_id=pk)
context = {"profile": profile}
handle_follow_action(request, request.user.profile, profile)
return render(request, "profile.html", context)
else:
messages.success(request, "You must be logged in to view this page")
return redirect("home")
def handle_follow_action(request, current_user_profile, profile):
if request.method == "POST":
action = request.POST.get("follow-btn")
if action == "unfollow":
current_user_profile.follows.remove(profile)
elif action == "follow":
current_user_profile.follows.add(profile)
current_user_profile.save()
My concern is: in this case the logic is small and maybe it is not too much of a deal to have it in one place. But what if I have to add tons of logic related to the profile request?
Maybe to put the logic somewhere else?
Well, thanks in advance!!