Reputation: 191
I have some models:
class User(AbstractUser):
cart = models.OneToOneField('cart.Cart', on_delete=models.SET_NULL, null=True, blank=True)
class Cart(models.Model):
products = models.ManyToManyField('product.Product')
date_updated = models.DateTimeField(auto_now=True, editable=False)
Now I need to create user cart instance at first call.
if request.user.cart is None:
request.user.cart = Cart.objects.create()
request.user.save()
This method is not good for me, because it leads to code duplication (every time I need to import Cart model and check the user's cart is it None or not).
The best way that I can find is AutoOneToOneField in django-annoying, but unfortunately it absolutely broke current field autocomplete in PyCharm.
What is the right way to do that?
P.S. I really don't need to create user cart object at user creation moment. P.P.S. Sorry for my bad English.
UPDATE: Thank you very much! I came to the first code fragment on my own, but it is noob edition script:
class User(AbstractUser):
_cart = models.OneToOneField('cart.Cart', on_delete=models.SET_NULL, null=True, blank=True, db_column='cart')
@property
def cart(self):
return self._cart # just for test
...end in my view i've got error like "object Cart has no property 'products'". But next code works great
class User(AbstractUser):
_cart = models.OneToOneField('cart.Cart', on_delete=models.SET_NULL, null=True, blank=True, db_column='cart')
@property
def cart(self):
if not self._cart:
self._cart = Cart.objects.create()
self.save(update_fields=('_cart',))
return self._cart
...except "unresolved attribute reference" warning in view:
if request.user.cart.add(type, pk):
messages.success(request, 'Added to cart')
but anyway, that warning should be PyCharm bug (do not autocomplete any @property-decorated methods). You are great, thank's a lot!
Upvotes: 0
Views: 1002
Reputation: 169051
There's a couple different ways I can think of off the cuff:
get_cart(request) -> Cart
that does the checkclass User(AbstractUser):
_cart = models.OneToOneField('cart.Cart', on_delete=models.SET_NULL, null=True, blank=True, db_column='cart')
@property
def cart(self):
if not self._cart_id:
self._cart = ...
self.save(update_fields=('_cart',))
return self._cart
Also, you might want to consider
class Cart(models.Model):
user = models.OneToOneField(User)
products = models.ManyToManyField('product.Product')
date_updated = models.DateTimeField(auto_now=True, editable=False)
# and
class User(AbstractUser):
@cached_property
def cart(self):
cart, created = Cart.objects.get_or_create(user=self)
return cart
instead.
Upvotes: 3