Как заставить кнопку показывать соответствующее сообщение в Django?
Я пытаюсь создать сайт типа социальной сети, который позволяет пользователям следовать за другими пользователями через модель Django. По какой-то причине кнопка Follow Button говорит "Unfollow", когда пользователь не следует за пользователем, и говорит "Follow", когда пользователь следует за другим пользователем. Не знаете ли вы, как вывести соответствующее сообщение? (Я пробовал менять значения True и False, но это просто заставляет кнопку постоянно говорить "Follow")
views.py
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()
код в html-шаблоне
<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")
вам не нужен пользовательский запрос, вы можете работать только с 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>
не забудьте добавить запрос в context
, если у вас нет request.context_processor:
def username(request, user):
...
return render(request, "network/username.html",{"posts": posts, "post": posts.first(), "request": request})
Вы можете сделать это намного проще без Follower
модели:
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)
...
Мне очень нравится ответ @NixonSparrow. В том же духе, я добавлю свой ответ.
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()
не является необходимым в вашем коде. Также как и вход пользователя в систему внутри представления. Это было необходимо для создания повторно используемого примера без страницы входа в систему.
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
Очевидно, что у вас, вероятно, есть модель Post
где-то еще. Просто здесь для примера.
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>
Прежде чем следовать:
После этого: