# Followers / following with AbstractUser model

**URL:** https://forum.djangoproject.com/t/followers-following-with-abstractuser-model/19200
**Category:** Forms & APIs
**Created:** [March 1, 2023, 6:19pm UTC](https://forum.djangoproject.com/t/followers-following-with-abstractuser-model/19200 "2023-03-01T18:19:35Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![yvon\_bike](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/yvon_bike/32/12466_2.png) [@yvon\_bike](https://forum.djangoproject.com/u/yvon_bike)
#### Post date: [March 1, 2023, 6:19pm UTC](https://forum.djangoproject.com/t/followers-following-with-abstractuser-model/19200/1 "2023-03-01T18:19:35Z")

</div>

Hello, new to django and here…

I’m finding it difficult to implement a follower – following system with an Abstractuser model.

I can update followers for each user profile in the backend which is reflected and shows the right button (follow / unfollow) on the users profile — so the logic is working.

However when I try to create my views.py file so that the user can follow / unfollow themselves nothing I’ve tried works (granted I know nothing) but if anyone can point me in the right direction would be greatly appreciated.

Here are snippets of my code;

```auto
# models.py

class NewUser(AbstractUser):
    
    birthdate = models.DateField(max_length=8, null=True, blank=True)
    portrait = models.ImageField(upload_to='portrait', default="../static/portrait/portrait_placeholder.png", null=True, blank=True)
    bio = models.TextField(verbose_name='Biography', max_length=600, null=True, blank=True)
    slug = AutoSlugField(populate_from='first_name', unique_with='last_name')
    follows = models.ManyToManyField("self", related_name="followed_by", symmetrical=False, blank=True)

    def count_followers(self):
        return self.follows.count()
    
    def count_following(self):
        return NewUser.objects.filter(follows=self).count()

    def __str__ (self):
        return self.username

class Product(models.Model):
    
    creator = models.ForeignKey(NewUser, on_delete=models.CASCADE, null=True, blank=True)
    name = models.CharField("Product Name", max_length=100, default="", help_text="This is the help text")
    concept = models.TextField(verbose_name='Concept', max_length=600, blank=True)
    created_date = models.DateTimeField(auto_now_add=True)
    updated_date = models.DateTimeField(auto_now=True)
    likes = models.ManyToManyField(NewUser, related_name='product_likes', blank=True)

    def total_likes (self):
        return self.likes.count()

    class Meta:
        ordering = ['-created_date']

```

```auto
# views.py

# view of populated profile detail view with associated profile products
class ProfileDetailView(DetailView):
    model = NewUser
    def get_context_data(self, **kwargs):
    # Call the base implementation first to get a context
        context = super().get_context_data(**kwargs)
        # Add in a QuerySet of all the users products
        context['object_list'] = Product.objects.filter(creator=self.object)
        return context

def follow_user(request, pk):
    follow_user = NewUser.objects.get(pk=request.user.id)

    if request.method == "POST":
        current_user_profile = request.user
        action = request.POST['follow']
        if action == "unfollow":
            current_user_profile.follows.remove(follow_user)
        elif action == "follow":
            current_user_profile.follows.add(follow_user)
        
    return render(request, 'authenticate/profile_detail.html', {"follow_user":follow_user})

```

```auto
# newuser_detail.html

<div class="row">
    <div class="col-md-auto p-3">
        <div class="button mt d-flex flex-row align-items-center">
            <a href="" class="h6">
                Following {{ newuser.count_followers }}
                <br>
                {% for username in newuser.follows.all %}
                    <a href="{% url 'profile' username.slug %}"> @{{ username }} </a><br/>
                {% endfor %}
        </div>
    </div>
    <div class="col-md-auto p-3">
        <div class="button mt d-flex flex-row align-items-center">
            <a href="" class="h6">
                Followers {{ newuser.count_following }}
                <br>
                {% for username in newuser.followed_by.all %}
                    <a href="{% url 'profile' username.slug %}"> @{{ username }} </a><br/>
                {% endfor %}
        </div>
    </div>
  </div>

<form method=POST>
  {% csrf_token %}
  {% if newuser in user.follows.all %}
      <button class = "btn btn-outline-danger" name="follow" value="unfollow" type="submit">unfollow {{ newuser.first_name }}</button>
  {% else %}
      <button class = "btn btn-outline-success" name="follow" value="follow" type="submit">follow {{ newuser.first_name }}</button>
  {% endif %}
</form>

```

---

<div class="post-metadata">

### Author: ![CodenameTim](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/codenametim/32/31507_2.png) [@CodenameTim](https://forum.djangoproject.com/u/CodenameTim)
#### Post date: [March 1, 2023, 6:46pm UTC](https://forum.djangoproject.com/t/followers-following-with-abstractuser-model/19200/2 "2023-03-01T18:46:11Z")

</div>

> [@yvon\_bike](#):
>
> However when I try to create my views.py file so that the user can follow / unfollow themselves nothing I’ve tried works (granted I know nothing) but if anyone can point me in the right direction would be greatly appreciated.

Can you provide more details around what exactly you’re doing, what you expect to happen and what is actually happening?

---

<div class="post-metadata">

### Author: ![yvon\_bike](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/yvon_bike/32/12466_2.png) [@yvon\_bike](https://forum.djangoproject.com/u/yvon_bike)
#### Post date: [March 1, 2023, 6:58pm UTC](https://forum.djangoproject.com/t/followers-following-with-abstractuser-model/19200/3 "2023-03-01T18:58:21Z")

</div>

Yes sorry, I’m aiming to create a follow / following system similar to twitter or instagram. Each user has their own profile page, this includes portrait, bio, contact info etc, and products they’ve created — this part I’ve achieved.

A user can follow someone by clicking follow on their profile, updating their profile number of followers / following etc, same as twitter or instagram.

Additionally, I’d like to be able to create a page which shows only products from the users you follow.

---

<div class="post-metadata">

### Author: ![yvon\_bike](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/yvon_bike/32/12466_2.png) [@yvon\_bike](https://forum.djangoproject.com/u/yvon_bike)
#### Post date: [March 1, 2023, 7:01pm UTC](https://forum.djangoproject.com/t/followers-following-with-abstractuser-model/19200/4 "2023-03-01T19:01:48Z")

</div>

Right now, it looks like the model is ok, and the logic in the html is working, when I add a follow through the admin panel, I see the correct button to either follow or unfollow a user on their profile.

However, when I click on the follow or unfollow button (same happens for both) I receive a HTTP ERROR 405 page in browser, instead of updating the follows model, and the error in terminal looks like this;  
[01/Mar/2023 19:00:19] “POST /user/newuser HTTP/1.1” 405 0

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [March 1, 2023, 7:20pm UTC](https://forum.djangoproject.com/t/followers-following-with-abstractuser-model/19200/5 "2023-03-01T19:20:19Z")

</div>

An HTTP 405 is a “Method not allowed” error. You’re trying to POST to a URL that will only allow a GET.

Since your `form` tag doesn’t define an action, it’s going to try to post to the same view that rendered the original page. Is that the right URL?

---

<div class="post-metadata">

### Author: ![yvon\_bike](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/yvon_bike/32/12466_2.png) [@yvon\_bike](https://forum.djangoproject.com/u/yvon_bike)
#### Post date: [March 1, 2023, 7:33pm UTC](https://forum.djangoproject.com/t/followers-following-with-abstractuser-model/19200/6 "2023-03-01T19:33:28Z")

</div>

ah, yes the idea is that when you press ‘follow’ it updates the model which is reflected in the button then showing ‘unfollow’ so it should be posting to the same view, not redirecting elsewhere, so it is the right url.

I did wonder if the slug in the newuser model is causing an issue, this is an example user profile page url; [http://127.0.0.1:8000/user/thomas](http://127.0.0.1:8000/user/thomas)

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [March 1, 2023, 7:39pm UTC](https://forum.djangoproject.com/t/followers-following-with-abstractuser-model/19200/7 "2023-03-01T19:39:00Z")

</div>

What view is creating the page containing these buttons? Is it the `ProfileDetailView`?

What view is supposed to handle the “follow” processing, isn’t it `follow_user`?

---

<div class="post-metadata">

### Author: ![yvon\_bike](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/yvon_bike/32/12466_2.png) [@yvon\_bike](https://forum.djangoproject.com/u/yvon_bike)
#### Post date: [March 1, 2023, 7:46pm UTC](https://forum.djangoproject.com/t/followers-following-with-abstractuser-model/19200/8 "2023-03-01T19:46:19Z")

</div>

yes that’s correct on both

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [March 1, 2023, 7:47pm UTC](https://forum.djangoproject.com/t/followers-following-with-abstractuser-model/19200/9 "2023-03-01T19:47:44Z")

</div>

So those are two different views - two different URLs. You need to define the action attribute of your form to submit to the url for `follow_user`, not `ProfileDetailView`.

---

<div class="post-metadata">

### Author: ![yvon\_bike](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/yvon_bike/32/12466_2.png) [@yvon\_bike](https://forum.djangoproject.com/u/yvon_bike)
#### Post date: [March 1, 2023, 10:59pm UTC](https://forum.djangoproject.com/t/followers-following-with-abstractuser-model/19200/10 "2023-03-01T22:59:23Z")

</div>

ok, understood they’re two different URLS, I have the url for ‘follow’ here;

```auto
path('user/<slug>', views.follow_user, name='follow'),

```

and the profile detail view here;

```auto
path('user/<slug>', ProfileDetailView.as_view(), name='profile'),

```

I thought I was passing in the POST action through the views here, but maybe that is not correct.

```auto
#views.py 
def follow_user(request, pk, slug):
    follow_user = NewUser.objects.get(id=request.user.id)

    if request.method == "POST":
        current_user_profile = request.user.follow_user
        action = request.POST['follow']
        if action == "unfollow":
            current_user_profile.follows.remove(follow_user)
        elif action == "follow":
            current_user_profile.follows.add(follow_user)
    
    return render(request, 'follow', {"follow_user":follow_user})
    

```

If I change html to include;

```auto
<form action="{% url 'follow' username.slug %}" method="POST">

```

I then get:  
Reverse for ‘follow’ with arguments ‘(’‘,)’ not found. 1 pattern(s) tried: [‘follow/(?P[^/]+)\Z’]

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [March 2, 2023, 12:31am UTC](https://forum.djangoproject.com/t/followers-following-with-abstractuser-model/19200/11 "2023-03-02T00:31:22Z")

</div>

> [@yvon\_bike](#):
>
> ok, understood they’re two different URLS, I have the url for ‘follow’ here;
> 
> ```auto
> path('user/<slug>', views.follow_user, name='follow'),
> 
> ```
> 
> and the profile detail view here;
> 
> ```auto
> path('user/<slug>', ProfileDetailView.as_view(), name='profile'),
> 
> ```

Those two are the same url. The second view (in order of being defined) will never be called. See [URL dispatcher | Django documentation | Django](https://docs.djangoproject.com/en/4.1/topics/http/urls/#how-django-processes-a-request)

Since you’re calling `ProfileDetailView` both times, I’m going to assume that it actually appears before the other in your urls.py file.

In that situation, `follow_user` will never be called.

The name assigned to the url has nothing to do with the resolution of the request being received.

> [@yvon\_bike](#):
>
> If I change html to include; …

That error is telling you that `username.slug` has no value in the context at the time the template is being rendered. (And, even if you do get that right, the generated URL is still going to resolve to the other view.)
