Django - OneToOneField 不起作用 - RelatedObjectDoesNotExist:用户没有用户详细信息

Django - OneToOneField does not work - RelatedObjectDoesNotExist: User has no userdetail

我正在尝试用这个扩展用户模型:

class UserDetail(models.Model):
    user = models.OneToOneField(to=User, on_delete=models.CASCADE, verbose_name="Používateľ")

    def __str__(self):
        return f"{self.user.first_name} {self.user.last_name} ({self.user.username}) / Celková hodnota všetkých objednávok používateľa: {self.total_value_of_users_orders} €"

    @property
    def total_value_of_users_orders(self):
        all_orders = Order.objects.all().filter(user=self.user, status__in=["NW", "WP", "PD", "IP", "ST", "DN"])
        total_value = 0
        for order in all_orders:
            total_value += order.total_value
        return total_value

但是,当我尝试访问 total_value_of_users_orders 属性 时,它不起作用:

from django.contrib.auth import get_user_model
User = get_user_model()
all_users = User.objects.all()

for u in all_users:
    u.userdetail.total_value_of_users_orders

它显示了这个异常:

RelatedObjectDoesNotExist: User has no userdetail.

我做错了什么?我希望所有用户都拥有 total_value_of_users_orders 属性 returns 0(如果没有属于给定用户的订单)或确切的值(如果有属于给定用户的订单)用户)。

谢谢

您需要先检查是否存在:

if hasattr(u, 'userdetail'):
    print(u.userdetail.total_value_of_users_orders)

请注意,以下内容仍然会给您一个 RelatedObjectDoesNotExist 错误:

if u.userdetail:
    print(u.userdetail.total_value_of_users_orders)

在创建User的时候使用django signal来创建UserDetail这样每个用户都会有自己的UserDetail并且查询可以访问total_value_of_users_order

from django.db.models.signals import post_save

# ... your models

def create_user_detail(sender, created, instance, **kwargs):
    if created:
        UserDetail.objects.create(user=instance)

# ...
post_save.connect(create_user_detail, sender=User)

这意味着您的用户在数据库中没有 userdetail 相关的 one-to-one 对象。您可以在需要时创建它,也可以在创建用户时创建它。

有几种处理方式:

  1. 创建用户后立即创建 UserDetail 对象。这可以使用 django signals 轻松完成。 (您可能需要修改生成的迁移来为旧迁移创建 UserDetail。)
  2. 在您想要访问时创建 UserDetail 对象(如果不存在)。您可以自己实现或使用 django-annoying 的 AutoOneToOneField。
  3. 每次要访问时检查用户是否有 userdetail(使用 hasattr)。阅读 the documentation。 (有效,但我不推荐)

如果您可以扩展 User 模型,还有其他选项可能会工作得更好,但您似乎已经迁移了它,所以不会那么容易。