#python #django
#python #django
Вопрос:
Я новичок в django. В моем проекте я хочу создать домашнюю страницу, на которой просматривается часть публикации.Но если пользователь зарегистрирован или аутентифицирован, он может просматривать все публикации, доступные на веб-сайте. на данный момент я создал представление, которое отображает все записи на домашней странице, но я хочу ограничить их.
Я использую представление на основе классов.
posts/views.py
from django.views.generic import ListView, DetailView
from .models import Post
class PostListView(ListView):
model = Post
template_name = 'posts/home.html'
context_object_name = 'posts'
ordering = ['-date_posted']
class PostDetailView(DetailView):
model = Post
template_name = 'posts/post_detail.html'
posts/models.py
from django.db import models
from django.utils import timezone
from slugger import AutoSlugField
from django.contrib.auth.models import User
from django.urls import reverse
# Create your models here.
def upload_location(instance, filename):
return "%s/%s" %(instance.slug, filename)
class Category(models.Model):
title = models.CharField(max_length= 60)
slug = AutoSlugField(populate_from='title')
parent = models.ForeignKey('self',blank=True, null=True ,related_name='children',on_delete=models.CASCADE)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
def __unicode__(self):
return self.title
def __str__(self):
return self.title
class Post(models.Model):
title = models.CharField(max_length=120)
slug = AutoSlugField(populate_from='title')
image = models.ImageField(
upload_to=upload_location,
null=True,
blank=True,
)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("posts-detail", kwargs={"pk": self.pk})
Комментарии:
1. Пожалуйста, поделитесь своими соответствующими моделями и представлениями.
2. @WillemVanOnsem посмотрите, я добавил сообщения / просмотр и сообщения / модели
3. Итак, вы хотите показывать только
Post
s, для которых зарегистрировавшийся пользователь являетсяauthor
?4. ни один пользователь не может создавать сообщения. на самом деле я хочу заставить просматривать некоторые сообщения на домашней странице. но когда пользователь регистрируется, он может просматривать все сообщения
5. и в случае, если пользователь не вошел в систему, что должно произойти?
Ответ №1:
В ListView
наборе запросов по умолчанию используются все объекты. В вашем случае, с model
установленным значением Post
, набором запросов по умолчанию является Post.objects.all()
.
Вы можете переопределить get_queryset()
метод ListView
. Посетите этот веб-сайт, чтобы получить хорошее представление о Django CBVS.
def get_queryset(self):
qs = super().get_queryset()
if self.request.user.is_authenticated:
return qs
else:
return qs.filter(<add a filter for not logged in users>)
# of return qs[:10] # to limit to 10 posts
Ответ №2:
Перенаправление пользователя
Вы можете использовать LoginRequiredMixin
[Django-doc], чтобы запретить пользователям просматривать представление, если они не вошли в систему. В этом случае поведение по умолчанию заключается в перенаправлении на страницу входа.
Вы можете добавить mixin к своим представлениям, например:
# posts/views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView, DetailView
from .models import Post
class PostListView(LoginRequiredMixin, ListView):
model = Post
template_name = 'posts/home.html'
context_object_name = 'posts'
ordering = ['-date_posted']
class PostDetailView(LoginRequiredMixin, DetailView):
model = Post
template_name = 'posts/post_detail.html'
В документации описано, что вы можете присвоить redirect_to
атрибуту class значение чего-либо другого, если хотите перенаправить пользователя на другую страницу.
Показывать страницу без Post
страниц (или фильтровать их)
Вы также можете решить отображать страницу, но без каких-либо Post
объектов. Мы можем справиться с этим, исправив get_queryset
метод:
# posts/views.py
from django.views.generic import ListView, DetailView
from .models import Post
class PostListView(ListView):
model = Post
template_name = 'posts/home.html'
context_object_name = 'posts'
ordering = ['-date_posted']
def get_queryset(self):
if not self.request.user.is_authenticated:
return Post.objects.none()
else:
return super().get_queryset()
class PostDetailView(DetailView):
model = Post
template_name = 'posts/post_detail.html'
def get_queryset(self):
if not self.request.user.is_authenticated:
return Post.objects.none()
else:
return super().get_queryset()
Комментарии:
1. Он показывает форму входа на домашней странице, я этого не хочу. Я хочу, чтобы на домашней странице отображалось что-то еще. Я хочу, чтобы там было какое-то содержимое.
2. @adityakumar: тогда вам следует выбрать вариант 2 или перенаправить на другую интересующую страницу. Я забыл удалить
LoginRequired
во втором варианте.3. должен ли я использовать это, если не self.request.is_authenticated: return redirect(‘posts/home.html ‘)
4. @adityakumar: нет, вы просто возвращаете набор запросов
Post
объектов, которые вы хотели бы отобразить, в данном случае мы используем.none()
(поэтому никакихPost
объектов вообще), или вы можете исправитьget_template_names
и, таким образом, вернуть другой шаблон в этом случае.5. @adityakumar: ну, это действительно правильно, поскольку
DetailView
выполняет дополнительную фильтрацию: он фильтрует так, что извлекаетid
, но если вы сначала срезаете, то это больше не имеет смысла, поэтому я думаю, что для подробного просмотра использование среза не имеет смысла.