I am trying to extend the User model with this:
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
However, when I try to access the total_value_of_users_orders
property, it does not work:
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
it shows this exception:
RelatedObjectDoesNotExist: User has no userdetail.
What am I doing wrong? I expect all users to have the total_value_of_users_orders
property which either returns 0 (if there are no Orders belonging to the given user) or the exact value (if there are Orders belonging to the given user).
Thank you
CodePudding user response:
You need to check for existence first:
if hasattr(u, 'userdetail'):
print(u.userdetail.total_value_of_users_orders)
Note that the following will still give you an RelatedObjectDoesNotExist
error:
if u.userdetail:
print(u.userdetail.total_value_of_users_orders)
CodePudding user response:
Use django signal to create UserDetail at the time of User creation so that each user will have its own UserDetail and query can access 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)
CodePudding user response:
It means your user does not have a userdetail
related one-to-one object in the database. You can create it when you need it or when you create a user.
There are several ways to handle it:
- Creating UserDetail object immediately after creating user. This can be easily done using django signals. (You may need to modify generated migration to create UserDetail for old ones.)
- Creating UserDetail object (if doesn't exist) when you want to access it. You can implement it yourself or use django-annoying's AutoOneToOneField.
- Checking if user has a
userdetail
or not (usinghasattr
) every time you want to access it. Read the documentation. (It works, but I don't recommend it anyway)
There are other options that may work much better if you can extend the User model, but it seems you already migrated it, so it won't be that easy.