即使使用if语句,仍会出现RelatedObjectDoesNotExist错误

3
我有以下代码:if self.request.user.is_authenticated() and self.request.user.userlocation,我不明白的是为什么会出现“用户没有userlocation”错误。我有一个if语句,如果条件不满足,它不应该只是继续执行并显示上下文吗?
class Homepage(TemplateView):
    template_name = 'home.html'

    def get_context_data(self, **kwargs):
        context = super(Homepage, self).get_context_data(**kwargs)
        context['event_list'] = Event.objects.all()
        if self.request.user.is_authenticated() and self.request.user.userlocation:
            print("The code reached here ")
        return context

以下是models.py文件:
class UserLocation(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    lat = models.FloatField(blank=True, null=True)
    lon = models.FloatField(blank=True, null=True)
    point = models.PointField(srid=4326, default='SRID=4326;POINT(0.0 0.0)')
    objects = models.GeoManager()

enter image description here


这是从UserLocationOneToOneField吗? - Willem Van Onsem
@WillemVanOnsem,你能检查一下我在上面问题中实现的代码吗?我做错了什么吗?我还是得到了同样的错误。 - Samir Tendulkar
你是否已经importObjectDoesNotExist错误? - Willem Van Onsem
@WillemVanOnsem 是的,我正在使用pycharm专业版,并且使用 from django.core.exceptions import ObjectDoesNotExist ,它会显示这些类型的错误。 - Samir Tendulkar
@WillemVanOnsem,你的代码很好,它运行得非常棒。令人惊讶的是,你甚至没有看我的模型就能够理解它。 - Samir Tendulkar
显示剩余2条评论
3个回答

7

使用Python的 hasattr()方法,在您的if语句中添加一个额外的条件,检查是否存在userlocation属性。

尝试以下代码:

class Homepage(TemplateView):
    template_name = 'home.html'

    def get_context_data(self, **kwargs):
        context = super(Homepage, self).get_context_data(**kwargs)
        context['event_list'] = Event.objects.all()
        if self.request.user.is_authenticated() and \
                <b>hasattr(self.request.user, 'userlocation')</b> and \
                self.request.user.userlocation:
            print("The code reached here ")
        return context



参考
Django 检查相关对象是否存在错误:RelatedObjectDoesNotExist


这个也行,谢谢你的 hasattr()。我实际上编写了你的解决方案,两个解决方案都很棒。我也给你的答案点了赞。感谢详细的参考资料。 - Samir Tendulkar
@Willem Van Onsem 总是喜欢写描述性答案而我有点懒;) - JPG
使用 try...catch 块处理异常是比条件表达式更符合 Python 风格的方式。 - JPG

5
我猜你构建了一个类似于以下模型的模型:
class UserLocation(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # ...

与普遍观念不同,一个一对一字段并不意味着被引用的模型(这里是User)总是有一个UserLocation对象。实际上,OneToOneField实际上是一个具有unique=True约束的ForeignKey字段(以及一些额外的逻辑,使得反向关系不是userlocation_set,而是userlocation)。因此,它意味着两个UserLocation永远不能引用相同的User对象。
因此,对于某些用户,可能没有user.userlocation,并且在调用属性时,不幸的是它返回的不是None,而是引发错误(已经有票据要求它返回None,但可能不会在(不久的)将来实现,因为需要保持向后兼容性)。
因此,您应该使用try-catch-except进行检查:
from django.core.exceptions import ObjectDoesNotExist

class Homepage(TemplateView):
    template_name = 'home.html'

    def get_context_data(self, **kwargs):
        context = super(Homepage, self).get_context_data(**kwargs)
        context['event_list'] = Event.objects.all()
        if self.request.user.is_authenticated()
            try:
                my_location = self.request.user.userlocation
            except ObjectDoesNotExist:
                # ... hande case where the location does <b>not</b> exists
            else:
                print("The location is {}".format(my_location))
        return context

except user.userlocation.DoesNotExist: 可以再具体一些 :) - JPG
1
@JPG:这是“ObjectDoesNotExists”,它是所有模型的“DoesNotExists”的“母类”。请参阅:https://docs.djangoproject.com/en/2.1/ref/exceptions/#objectdoesnotexist - Willem Van Onsem
2
通过编写user.userlocation.DoesNotExist:是无法解决问题的,因为现在它将为except子句部分中的user.userlocation引发异常 :) - Willem Van Onsem
1
最后一条评论太棒了 :+1 - JPG

-1

User 类中没有 userlocation 变量。 使用从 User 继承的自定义用户类。


2
在这种情况下,它会引发一个AttributeError。这个关系是OneToOneField反向的结果。 - Willem Van Onsem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接