You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django测试:如何编写用例区分登录/未登录用户的问题可见性

Great question! Let's break down how to implement these test cases step by step. I'll extend your existing QuestionsAndChoices test class with all the required scenarios, using Django's built-in TestCase utilities.

First, we'll set up reusable test data (users and questions) in the setUp method, which runs before every test. Then we'll write individual tests for each of your requirements.

Full Test Code

from django.test import TestCase
from django.contrib.auth.models import User
from django.urls import reverse
from .models import Question  # Import your Question model here

class QuestionsAndChoices(TestCase):
    def setUp(self):
        # Create test users: admin, regular logged-in user
        self.admin_user = User.objects.create_superuser(
            username='admin_user',
            email='admin@example.com',
            password='admin_pass123'
        )
        self.regular_user = User.objects.create_user(
            username='regular_user',
            email='user@example.com',
            password='user_pass123'
        )
        
        # Create test questions
        # 1. Unpublished question (only admin should see this)
        self.unpublished_question = Question.objects.create(
            question_text="This is an unpublished question",
            is_published=False
        )
        # 2. Published question with no choices (only logged-in users see this)
        self.no_choices_question = Question.objects.create(
            question_text="Question with no options",
            is_published=True
        )
        # 3. Published question with choices (everyone should see this, as a control)
        self.published_with_choices = Question.objects.create(
            question_text="Normal published question with choices",
            is_published=True
        )
        # If you have a Choice model, add a choice to the above question:
        # Choice.objects.create(
        #     question=self.published_with_choices,
        #     choice_text="Sample Option 1"
        # )

    def test_admin_can_view_unpublished_questions(self):
        """Admin users should be able to see unpublished questions in the list"""
        # Log in as admin
        self.client.login(username='admin_user', password='admin_pass123')
        # Fetch the question list page (replace 'question_list' with your actual URL name)
        response = self.client.get(reverse('question_list'))
        
        # Verify all questions are visible to admin
        self.assertContains(response, self.unpublished_question.question_text)
        self.assertContains(response, self.no_choices_question.question_text)
        self.assertContains(response, self.published_with_choices.question_text)

    def test_anonymous_user_cannot_view_unpublished_questions(self):
        """Anonymous visitors should NOT see unpublished questions"""
        # No login needed - client is anonymous by default
        response = self.client.get(reverse('question_list'))
        
        # Unpublished question should be hidden
        self.assertNotContains(response, self.unpublished_question.question_text)
        # Published with choices should be visible (control check)
        self.assertContains(response, self.published_with_choices.question_text)

    def test_logged_in_user_can_view_question_without_choices(self):
        """Any logged-in user (admin or regular) should see questions without choices"""
        # Test regular user first
        self.client.login(username='regular_user', password='user_pass123')
        response = self.client.get(reverse('question_list'))
        self.assertContains(response, self.no_choices_question.question_text)
        
        # Test admin user (optional but thorough)
        self.client.logout()
        self.client.login(username='admin_user', password='admin_pass123')
        response = self.client.get(reverse('question_list'))
        self.assertContains(response, self.no_choices_question.question_text)

    def test_anonymous_user_cannot_view_question_without_choices(self):
        """Anonymous users should NOT see questions without any choices"""
        response = self.client.get(reverse('question_list'))
        self.assertNotContains(response, self.no_choices_question.question_text)
        # Published with choices should still be visible
        self.assertContains(response, self.published_with_choices.question_text)

Key Explanations:

  • setUp Method: Creates reusable test users and questions so we don't repeat code in each test. This makes tests faster and cleaner.
  • Authentication: We use self.client.login() to simulate logged-in users, and the client is anonymous by default for tests that don't call login.
  • URL Reversing: Using reverse('question_list') instead of hardcoding URLs ensures your tests stay valid even if you change URL patterns later. Replace question_list with the actual name of your question list view from urls.py.
  • Assertions:
    • assertContains: Checks that a piece of text exists in the response (good for verifying visible content).
    • assertNotContains: Checks that text is NOT present (good for verifying restricted content is hidden).

Notes for Your View Logic:

To make these tests pass, your view should implement the following logic:

  1. If the user is an admin: Show all questions (published/unpublished, with/without choices).
  2. If the user is logged in (but not admin): Show all published questions (including those without choices).
  3. If the user is anonymous: Only show published questions that have at least one choice.

For example, in a class-based view, you might override get_queryset() to handle these cases:

from django.views.generic import ListView
from .models import Question

class QuestionListView(ListView):
    model = Question
    template_name = 'questions/question_list.html'

    def get_queryset(self):
        queryset = super().get_queryset()
        if self.request.user.is_superuser:
            return queryset
        # Filter to published questions for logged-in users
        queryset = queryset.filter(is_published=True)
        if not self.request.user.is_authenticated:
            # Anonymous users only see questions with choices
            queryset = queryset.filter(choices__isnull=False).distinct()
        return queryset

内容的提问来源于stack exchange,提问作者khashashin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:16:12