Как я могу ограничить просмотр post для не прошедшего проверку подлинности пользователя в представлении на основе классов django

#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 , но если вы сначала срезаете, то это больше не имеет смысла, поэтому я думаю, что для подробного просмотра использование среза не имеет смысла.