DJango - два разных представления из разных приложений в одном шаблоне
Здесь начинающий Джанго.
Я пытаюсь сделать приложение, в котором пользователи могут устанавливать связи, размещать материалы, общаться в чате и т.д. Есть два типа пользователей - Parents
и Child
. Для этого я расширил модель AbstractBaseUser
и создал две другие модели - Parent
и Child
с OneToOne
ссылкой на User
.
#accounts/models.py
class User(AbstractBaseUser, PermissionsMixin):
REQUIRED_FIELDS = []
EMAIL_FIELD = "email"
USERNAME_FIELD = 'email'
objects = UserManager()
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=DefaultModel.MAX_LENGTH, unique=False)
last_name = models.CharField(max_length=DefaultModel.MAX_LENGTH, unique=False)
profile_photo = models.ImageField(default='uploads/profile/default_profile.jpg', upload_to=content_image_name)
cover_photo = models.ImageField(default='uploads/profile/default_cover.jpg', upload_to=content_image_name)
username = AutoSlugField(populate_from='first_name', unique=True, sep='.')
bio = models.CharField(max_length=255, blank=True, default="Nothing to see here !")
is_child = models.BooleanField(default=False)
is_parent = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
# storing timestamps for users.
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
CHOICES = (('M','Male'),('F','Female'),('O','Other'))
gender = models.CharField(max_length=10, choices=CHOICES)
def get_absolute_url(self):
return "/users/{}".format(self.username)
def __str__(self):
return "{} {}".format(self.first_name, self.last_name)
class Child(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
friends = models.ManyToManyField('self',
blank=True,
related_name='friends',
db_column='friends',)
def __str__(self):
return "{} {}".format(self.user.first_name, self.user.last_name)
class Parent(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
connections = models.ManyToManyField('self',
blank=True,
related_name='connections',
db_column='connections',)
def __str__(self):
return "{} {}".format(self.user.first_name, self.user.last_name)
Как вы видите, Child
может быть другом только с другим Child
, а Parent
может подключиться только с Parent
.
В основном у меня есть два приложения - Feeds для работы с постами и Accounts для работы с аккаунтами. Есть страница для отображения текущих пользователей (/childs/
для Child
и /parents/
для Parent
) и другая для друзей (/friends/
для Child
и /connections/
для Parent
).
На главной странице (/home
) приложения есть две боковые панели - одна для показа пользователей, которым request.user
может отправить запрос на дружбу, а другая для показа друзей request.user
. Поскольку для обоих типов пользователей существует один url (/home
), поэтому стратегия такова :
- Make a base ListView for displaying both current users and friends.
- Inherit it for the individual users and friends page.
- Inherit it for
home.html
for/home
.
@method_decorator(login_required, name='dispatch')
class UserList(ListView):
model = User
def get_context_data(self, *args, **kwargs):
context = super(UserList, self).get_context_data(**kwargs)
if self.request.user.is_child:
childs = Child.objects.exclude(user=self.request.user.child)
sent_requests = ChildFriendRequest.objects.filter(from_user=self.request.user.child)
recv_requests = ChildFriendRequest.objects.filter(to_user=self.request.user.child)
friends = self.request.user.child.friends.all()
recv_from = [i.from_user for i in recv_requests]
users = [i for i in childs if i not in friends and i not in recv_from]
sent_to = [ i.to_user for i in sent_requests]
context['users'] = users
context['sent'] = sent_to
context['friends'] = friends
context['recv_requests'] = recv_requests
elif self.request.user.is_parent:
parents = Parent.objects.exclude(user=self.request.user.parent)
sent_requests = ParentConnectionRequest.objects.filter(from_user=self.request.user.parent)
recv_requests = ParentConnectionRequest.objects.filter(to_user=self.request.user.parent)
connections = self.request.user.parent.connections.all()
recv_from = [i.from_user for i in recv_requests]
users = [i for i in parents if i not in connections and i not in recv_from]
sent_to = [ i.to_user for i in sent_requests]
context['users'] = users
context['sent'] = sent_to
context['connections'] = connections
context['recv_requests'] = recv_requests
return context
class ChildList(UserList):
template_name = "account/child/childs_list.html"
class FriendList(UserList):
template_name = "account/child/friend_list.html"
class ParentList(UserList):
template_name = "account/parent/parent_list.html"
class ConnectionList(UserList):
template_name = "account/parent/connection_list.html"
class Sidebar(UserList):
template_name = "feeds/home.html"
Теперь views
приложения Feeds
также используют home.html
для отображения фидов.
class PostListView(ListView):
model = Post
template_name = 'feeds/home.html'
context_object_name = 'posts'
ordering = ['-date_posted']
paginate_by = 10
def get_context_data(self, **kwargs):
context = super(PostListView, self).get_context_data(**kwargs)
if self.request.user.is_authenticated:
liked = [i for i in Post.objects.all() if Like.objects.filter(user = self.request.user, post=i)]
context['liked_post'] = liked
return context
Проблема в том, что при обращении к /friends
или /childs
я вижу пользователей, но в /home
пользователь не отображается, хотя я вижу сообщения.
Вот home.html
{% extends "feeds/layout.html" %}
{% load static %}
{% block friends_sidebar %}
<div class="widget stick-widget">
<h4 class="widget-title">People Nearby</h4>
<ul class="followers">
{% if users %}
{% for user_p in users %}
<li>
<figure>
<a href="{{ user_p.user.get_absolute_url }}" title=""><img src="{{ user_p.user.profile_photo.url }}" width="40" height="40" alt=""></a>
</figure>
<div class="friend-meta">
<h4><a href="{{ user_p.user.get_absolute_url }}" title="">{{ user_p.user }}</a></h4>
{% if not user_p in sent %}
<a href="/child/friend-request/send/{{ user_p.user.id }}/" title="" class="underline">Add Friend</a>
{% else %}
<a href="/child/friend-request/cancel/{{ user_p.user.id }}/" title="" class="underline">Cancel Request</a>
{% endif %}
</div>
</li>
{% endfor %}
{% else %}
<p>No one is here !</p>
{% endif %}
</ul>
</div>
{% endblock %}
Я могу только видеть :
No one is here !
Итак, вопрос в том, как я могу обойти это? Это потому, что два представления используют один и тот же шаблон?
Я использую Django 3.2.9 и Python 3.8.
Как упомянул @Razenstein, мне нужно было иметь контексты UserList в PostListView, поэтому я унаследовал UserList в PostListView, и это помогло. Вот что нужно было сделать :
class PostListView(UserListView):
model = Post
template_name = 'feeds/home.html'
context_object_name = 'posts'
ordering = ['-date_posted']
paginate_by = 10
def get_context_data(self, **kwargs):
context = super(PostListView, self).get_context_data(**kwargs)
if self.request.user.is_authenticated:
liked = [i for i in Post.objects.all() if Like.objects.filter(user = self.request.user, post=i)]
context['liked_post'] = liked
return context
Ключом здесь является наследование класса UserList
и использование super()
в get_context_data()
.