Django - OneToOneField не работает - RelatedObjectDoesNotExist: У пользователя нет данных о пользователе

Я пытаюсь расширить модель User следующим образом:

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, которое либо возвращает 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)

Используйте 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связанного объекта один-к-одному. Вы можете создать его, когда он вам понадобится или при создании пользователя.

Есть несколько способов справиться с этим:

  1. Создание объекта UserDetail сразу после создания пользователя. Это можно легко сделать, используя django signals. (Возможно, вам придется модифицировать сгенерированную миграцию для создания UserDetail для старых пользователей.)
  2. Создание объекта UserDetail (если он не существует), когда вы хотите получить к нему доступ. Вы можете реализовать это самостоятельно или использовать django-annoying's AutoOneToOneField.
  3. Проверять, есть ли у пользователя userdetail или нет (используя hasattr) каждый раз, когда вы хотите получить к нему доступ. Прочитайте документацию . (Это работает, но я все равно не рекомендую)
  4. .

Есть другие варианты, которые могут работать гораздо лучше, если вы сможете расширить модель User, но, похоже, вы уже перенесли ее, поэтому это будет не так просто.

Вернуться на верх