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
связанного объекта один-к-одному. Вы можете создать его, когда он вам понадобится или при создании пользователя.
Есть несколько способов справиться с этим:
- Создание объекта UserDetail сразу после создания пользователя. Это можно легко сделать, используя django signals. (Возможно, вам придется модифицировать сгенерированную миграцию для создания UserDetail для старых пользователей.)
- Создание объекта UserDetail (если он не существует), когда вы хотите получить к нему доступ. Вы можете реализовать это самостоятельно или использовать django-annoying's AutoOneToOneField.
- Проверять, есть ли у пользователя
userdetail
или нет (используяhasattr
) каждый раз, когда вы хотите получить к нему доступ. Прочитайте документацию . (Это работает, но я все равно не рекомендую) .
Есть другие варианты, которые могут работать гораздо лучше, если вы сможете расширить модель User, но, похоже, вы уже перенесли ее, поэтому это будет не так просто.