【问题标题】:django testing passing request.user to foreignKey field, "Event.creator" must be a "User" instancedjango 测试将 request.user 传递给 foreignKey 字段,“Event.creator”必须是“User”实例
【发布时间】:2017-12-17 18:12:20
【问题描述】:

我正在尝试为创建事件模型对象的视图编写测试。事件模型包含一个 foreignKey 字段,该字段将 auth user 引用为模型对象的创建者。在测试中,我尝试登录用户,我认为该用户会将 request.user 设置为登录用户。正在测试的视图在创建事件时引用 request.user,当通过 ajax 正常触发但我运行时工作正常测试我不断收到以下错误。我也尝试在测试函数中创建用户,而不是引用在“class.setupTestData()”创建的用户,同样的错误。

错误

ValueError: Cannot assign "<SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x108ae9cc0>>": "Event.creator" must be a "User" instance.

型号

    class Event(models.Model):
        name = models.CharField(max_length=200)
        event_type = models.CharField(max_length=200, null=True)
        creator = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
        attendees = models.ManyToManyField(User, related_name='attendees')
        start_date = models.DateField(null=True)
        start_time = models.TimeField(null=True)
        end_date = models.DateField(null=True)
        end_time = models.TimeField(null=True)
        location = models.CharField(max_length=200, null=True)
        date_created = models.DateTimeField(auto_now_add=True)
        description = models.TextField()

        def __str__(self):
            return self.name

查看

    def createEvent(request):
        # dec vars
        event_title = str(request.POST['event-title']).title()
        event_type = str(request.POST['event-type'])
        event_location = str(request.POST['event-location'])
        event_description = str(request.POST['event-description'])
        event_start_date = str(request.POST['event-start-date'])
        event_start_time = str(request.POST['event-start-time'])
        event_end_date = str(request.POST['event-end-date'])
        event_end_time = str(request.POST['event-end-time'])
        creator = request.user

        # create event
        Event.objects.create(
            name=event_title,
            event_type=event_type,
            creator=creator,
            location=event_location,
            description=event_description,
            start_date=event_start_date,
            start_time=event_start_time,
            end_date=event_end_date,
            end_time=event_end_time
        )

        # #create response
        response = {
            'status': 'success',
        }

        # send reponse JSON
        return JsonResponse(response)

测试

def test_create_event(self):
    today = timezone.now()
    user = User.objects.get(pk=1)

    # login user
    self.c.login(username=user.username, password=user.password)

    # Check event create
    response = self.c.post('/event/create/', {
        'event-title': 'test create event',
        'event-type': 'combat',
        'event-location': 'ltt 9455',
        'event-description': lorem.paragraph,
        'event-start-date': today.date(),
        'event-end-date': today.date(),
        'event-end-time': today.time(),
        'event-start-time': today.time()
    })

    self.assertTrue()

【问题讨论】:

  • 我想我使用 Django 的 RequestFactory 找到了解决方案,如果可行,我会回复。

标签: django python-3.x django-testing


【解决方案1】:

user.passwordhashed密码,所以你在调用client.login()时不能使用它

拨打login时可以使用实际密码

user = User.objects.get(pk=1)
self.client.login(username=user.username, password='actual_password')

或者您可以使用client.force_login() 代替,这不需要密码。

user = User.objects.get(pk=1)
self.client.force_login(user)

请注意,您的失败测试表明您的视图存在问题。如果匿名用户使用该视图,ValueError 将导致 500 服务器错误。最简单的解决方法是使用 login_required 装饰器。

from django.contrib.auth.decorators import login_required

@login_required
def createEvent(request):
    ...

【讨论】:

  • 非常感谢,强制登录成功了。在模板中,我确实使用了{% if user.is_authenticated %} 标签来隐藏按钮,以防止未登录的用户创建事件。我是否仍应在需要登录用户的视图上将 @login_required 装饰器与模板标签结合使用,或者是否过大。
  • 我会签入​​视图而不依赖模板。在模板中隐藏按钮是好的,但它不会阻止用户手动提交请求。
  • 再次感谢我继续添加装饰器的建议,我将同时使用装饰器和模板标签。
猜你喜欢
  • 2020-12-01
  • 2020-07-22
  • 2021-05-16
  • 2015-04-30
  • 2012-03-09
  • 2015-01-05
  • 1970-01-01
  • 2019-03-21
相关资源
最近更新 更多