Home > Net >  How to make a button show the appropriate message in Django?
How to make a button show the appropriate message in Django?

Time:07-08

I am trying to create asocial media type site that allows users to follow other users through a Django model. For some reason, the Follow Button says "Unfollow" when a user is not following the user and says "Follow" when the user is following the other user. Do you know how to display the appropriate message? (I have tried switching the True and False values but that just makes the button say "Follow" permanently.)

views.py

    def username(request, user):
    #get user
    user = get_object_or_404(User.objects, username=user)
    posts = Post.objects.filter(user=user).order_by('-date_and_time')

    #follow button code
    if user == request.user:
        followButton = False
    else:
        followButton = True

    follow_or_unfollow = ''
    try:
        following = get_object_or_404(Follower, Q(
            user=user) & Q(followers=request.user))
        print(following)
    except: 
        following = False

    if following:
        follow_or_unfollow = True
    else:
        follow_or_unfollow = False

    if request.method == "POST":
        if request.POST.get('follow'):
            follower = Follower.objects.create(user=user)
            follower.followers.add(request.user)
            #Follower.objects.create(user=user, followers.set()=request.user)
            follow_or_unfollow = False
        elif request.POST.get('unfollow'):
            follower = Follower.objects.get(followers=request.user)
            follow_or_unfollow = True
            follower.remove()
       
    return render(request, "network/username.html",{
        "user": user,
        "posts": posts,
        "follow_or_unfollow": follow_or_unfollow,
        "followButton": followButton
    })

code in html template

<form action = "{% url 'username' user %}" method = "POST">
            {% csrf_token %}
            {% if follow_or_unfollow == True %}
                <input type="submit" value = "Follow" name = "follow">
            {% else %}
                <input type="submit" value = "Unfollow" name = "unfollow">
            {% endif %}
        </form>

models.py

class User(AbstractUser):
    pass

class Follower(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, default="")
    followers = models.ManyToManyField(User, related_name="followers")

CodePudding user response:

You can do it so much simplier without Follower model:

models.py

class User(AbstractUser):
    following = models.ManyToManyField("self", related_name="followers")

template.html

<form action = "{% url 'username' user %}" method = "POST">
    {% csrf_token %}
    {% if user not in request.user.following.all %}
        <input type="submit" value="Follow" name="follow">
    {% else %}
        <input type="submit" value="Unfollow" name="unfollow">
    {% endif %}
</form>

views.py

def username(request, user):
    ...
    if request.method == "POST":
        if "follow" in request.POST:
            request.user.following.add(user)
        elif "unfollow" in request.POST:
            request.user.following.remove(user)
    ...

CodePudding user response:

you don't need user query, you can work only with post

<form action = "{% url 'username' post.user %}" method = "POST">
    {% csrf_token %}
    {% if request.user != post.user %}
        {% if request.user not in post.user.followers.all %}
            <input type="submit" value = "Follow" name = "follow">
        {% else %}
            <input type="submit" value = "Unfollow" name = "unfollow">
        {% endif %}
    {% endif %}
</form>

dont forget add request in context, if you don't have a request.context_processor:

def username(request, user):
    ...
    return render(request, "network/username.html",{"posts": posts, "post": posts.first(), "request": request})

CodePudding user response:

I like @NixonSparrow's answer very much. Along those same lines, I'll throw my answer into the mix.

accounts/views.py

import random
import string

from django.shortcuts import render, get_object_or_404
from accounts.models import Post
from django.contrib.auth import get_user_model

from django.contrib.auth import authenticate, login

def generate_fake_user():
    username = ''.join(random.choice(string.ascii_lowercase) for i in range(10))
    password = 'abc123'
    fake_user = get_user_model().objects.create(
        username=username
    )
    fake_user.set_password(password)
    fake_user.save()
    return fake_user

def username(request, user):
    # get user
    owner = get_object_or_404(get_user_model(), username=user)
    if not request.user.is_authenticated:
        visitor = generate_fake_user()
        login(request, visitor)
    else:
        visitor = request.user
    posts = Post.objects.filter(user=owner).order_by('-date_and_time')

    if request.method == 'POST' and request.user.is_authenticated:
        if 'follow' in request.POST:
            owner.followers.add(visitor)
        if 'unfollow' in request.POST:
            owner.followers.remove(visitor)

    context = {
        "owner"  : owner,
        "visitor": visitor,
        "posts"  : posts,
    }
    return render(request, "network/username.html", context)

generate_fake_user() is not necessary in your code. Neither is loging in the user within the view. This was necessary to create a re-usable example without a login page.

accounts/models.py

from django.db import models
from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    followers = models.ManyToManyField('self', related_name="followers")
    following = models.ManyToManyField('self', related_name="following")


class Post(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    date_and_time = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

Obviously, you probably have Post model somewhere else. Just here for example purposes.

accounts/urls.py

from django.urls import path
from .views import username

urlpatterns = [
    path('<str:user>/', username, name='username'),
]

network/username.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    <div style="margin-left:auto; margin-right:auto; width:50%;">

        {% for post in posts %}
        <h1>{{ post.title }}</h1>
        <div>
            <div>Owner: {{ owner }}</div>
            <div>Owner: {{ visitor }}</div>
        </div>
        <form action="{% url 'username' owner %}" method="POST">
            {% csrf_token %}
            {% if visitor not in owner.followers.all %}
                <input type="submit" value="Follow" name="follow">
            {% else %}
                <input type="submit" value="Unfollow" name="unfollow">
            {% endif %}
        </form>
        {% endfor %}
    </div>


</body>
</html>

Before following:

before following

After following:

after following

  • Related