Django - Создать связанный объект при первом вызове - PullRequest
0 голосов
/ 03 октября 2019

У меня есть несколько моделей:

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)

Теперь мне нужно создать экземпляр корзины пользователя при первом вызове.

   if request.user.cart is None:
        request.user.cart = Cart.objects.create()
        request.user.save()

Этот метод мне не подходит, потому что он приводит кдублирование кода (каждый раз, когда мне нужно импортировать модель корзины и проверить корзину пользователя, нет ли ее или нет).

Лучший способ, который я могу найти, - это AutoOneToOneField в django-раздражает , нок сожалению, это полностью нарушило текущее поле автозаполнения в PyCharm.

Как правильно это сделать?

PS Мне действительно не нужно создавать объект корзины пользователя в момент создания пользователя. PPS Извините за мой плохой английский.

ОБНОВЛЕНИЕ: Большое спасибо! Я пришел к первому фрагменту кода самостоятельно, но это скрипт редакции noob:

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

... конец, на мой взгляд, у меня ошибка типа "объект Корзина не имеет свойства" продукты "",Но следующий код прекрасно работает

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

... за исключением предупреждения о "неразрешенной ссылке на атрибут":

if request.user.cart.add(type, pk):
    messages.success(request, 'Added to cart')

, но в любом случае это предупреждение должно быть ошибкой PyCharm (не дополняйте автоматически@ методы, украшенные собственностью). Вы великолепны, спасибо большое!

Ответы [ 2 ]

2 голосов
/ 03 октября 2019

Есть несколько разных способов, которые я могу придумать:

  • Промежуточное программное обеспечение, которое проверяет каждый запрос - чисто, но вызывает дополнительные обращения к базе данных, даже если этот запрос не нуженкорзина для пользователя
  • Отдельная функция get_cart(request) -> Cart, которая выполняет проверку
  • Аксессор на вашем пользовательском пользователе:
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_id: 
             self._cart = ...
             self.save(update_fields=('_cart',))
        return self._cart

Также вы можетехочу рассмотреть

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

.

0 голосов
/ 03 октября 2019

Вы можете установить класс корзины на одноэлементный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...