I’m trying to add a follow / unfollow button for user profiles. I’ve gone through several tutorials/forum posts which have gotten me this far, and I’m pretty sure my view is now where I’m going wrong the most. If helpful to note, I also suspect a bit of the problem is me not fully understanding how to convert and/or combine FBVs and CBVs because I started with a CBV and a lot of tutorials are using FBVs.
The button currently shows as follow/unfollow correctly on different user profiles. When the follow or unfollow button is clicked, it returns this error in the terminal:
Method Not Allowed (POST): /profiles/7429138d-699c-48c9-97f2-5698b59ff946
Method Not Allowed: /profiles/7429138d-699c-48c9-97f2-5698b59ff946
[22/Jun/2023 14:55:22] “POST /profiles/7429138d-699c-48c9-97f2-5698b59ff946 HTTP/1.1” 405 0
Questions
- I read that the HTTP 405 Method Not Allowed “indicates that the server knows the request method, but the target resource doesn’t support this method” — what is the “target resource”?
- In the view, should the
# Trying to follow / unfollow profiles
part be separated out into its own function withinProfileDetailView
instead of part ofget_context_data
?
2a. If yes to Q2, what should I be looking at to try to connect what’s in the template with that function of the view? Am I supposed to name the form?
2b. If no to Q2, what am I supposed to try and add as context to be sent to the template?
Models
class Profile(models.Model):
id = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False)
user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
following = models.ManyToManyField(CustomUser, related_name="followed_by", symmetrical=False, blank=True)
class CustomUser(AbstractUser):
pass
View
class ProfileDetailView(DetailView):
model = Profile
context_object_name = "profile"
template_name = "profiles/profile_detail.html"
def get_object(self, **kwargs):
pk = self.kwargs.get('pk')
view_profile = Profile.objects.get(pk=pk)
return view_profile
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
view_profile = self.get_object()
my_profile = Profile.objects.get(user=self.request.user)
context["view_profile_user"] = view_profile.user
# Giving the context to show follow / unfollow in the template button
if view_profile.user in my_profile.following.all():
follow = True
else:
follow = False
context["follow"] = follow
# Trying to follow / unfollow profiles
if self.request.method=="POST":
action = self.request.POST['follow_or_unfollow']
if action == "unfollow":
my_profile.follows.remove(view_profile)
elif action == "follow":
my_profile.follows.add(view_profile)
my_profile.save()
return context
Template
{% if user.is_authenticated %}
{% if profile %}
<div class="container">
<div class="row">
<div class="col-8">
<h1>{{ profile.user.username }}'s Profile</h1>
<form method="POST">
{% csrf_token %}
{% if follow %}
<button class="btn btn-outline-danger" name="follow_or_unfollow" value="unfollow" type="submit">unfollow</button>
{% else %}
<button class="btn btn-outline-success" name="follow_or_unfollow" value="follow" type="submit">follow</button>
{% endif %}
</form>
</div>
<!-- there's more HTML but I believe above is the only relevant excerpt -->