Как заставить Django Queryset фильтровать записи одной модели в зависимости от полей другой модели - PullRequest
0 голосов
/ 09 июня 2018

Я пытаюсь отфильтровать записи от одной модели (продукта) в зависимости от того, что купил пользователь (EntryProduct).

Я искал другие сообщения, но ни одна из них не могла решить мою проблему.

Я использую Django 2.0.

Прежде всего, я собираюсьобъясните, как работает этот магазин: один товар состоит из определенной группы контента.Пользователь должен покупать содержимое этого продукта, а не сам продукт (как большинство магазинов), поэтому для этого процесс покупки, который я сделал, был следующим: В EntryProduct я добавил логическое значение для каждого содержимогочто продукты имеют, так что каждый раз, когда пользователь покупает контент у продукта, есть функция, которая создает новую запись, устанавливающую для соответствующего логического значения значение true.Таким образом, у меня есть 1 запись для каждого контента, купленного пользователем и продуктом.

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

  • Сначала получите фильтрацию «Записи» зарегистрированным пользователем.
  • Затем сгруппируйте по продуктам (чтобы я мог получить весь контент, купленный этим пользователем).
  • И создайте набор запросов, передавая только купленное содержимое продуктов в Шаблон, чтобы я мог их распечатать.

Это именно то, что я думал, но я неНе знаю, как создать этот Queryset, а затем распечатать содержимое в шаблон ...

Другой способ, который я подумал, - передать набор запросов продуктов, другой элемент записей и отфильтровать их в собственном шаблоне.Пример: (только если исключить for s)

{% if entry.user=user and entry.abstract %}
    {{prod.abstract}}
{% endif %}

Но я не думаю, что это лучший способ сделать это ... Я совершенно новичок в Django ине совсем уверен, что является лучшей практикой для этого случая.

(связано) Модели :

class Product(models.Model):
    owner = models.ForeignKey(CustomUser, on_delete=models.PROTECT)
    name = models.CharField(_('Product Name'), max_length=150)
    category = models.ManyToManyField(Category)
    tag = models.ManyToManyField(Tag)
    it_exist = models.BooleanField(_('is an existing idea?'), default=False)
    # content
    content_tweet = models.CharField(_('Content Tweet'), max_length=150, blank=True)
    content_abstract = models.CharField(_('Content Abstract'), max_length=3000, blank=True)
    canvas_01 = models.FileField(upload_to='documents/canvas_01/', blank=True)
    executive_resume = models.FileField(upload_to='documents/executive_resume', blank=True)
    graphic_01 = models.FileField(upload_to='documents/graphic_01', blank=True)
    business_plan = models.FileField(upload_to='documents/business_plan', blank=True)
    investor_deck = models.FileField(upload_to='documents/investor_deck', blank=True)
    graphic_02 = models.FileField(upload_to='documents/graphic_02', blank=True)
    # prices
    price_tweet = models.IntegerField(_('Tweet Price in Tokens'), default=0)
    price_abstract = models.IntegerField(_('Abstract Price in Tokens'), default=50)
    price_canvas_01 = models.IntegerField(_('Canvas 01 Price in Tokens'), default=500)
    price_executive_resume = models.IntegerField(_('Executive Resume Price in Tokens'), default=1000)
    price_graphic_01 = models.IntegerField(_('Graphic 01 Price in Tokens'), default=1000)
    price_business_plan = models.IntegerField(_('Business Plan Price in Tokens'), default=10000)
    price_investor_deck = models.IntegerField(_('Investor Deck Price in Tokens'), default=7500)
    price_graphic_02 = models.IntegerField(_('Graphic 02 Price in Tokens'), default=5000)
    # extra
    is_deleted = models.BooleanField(
        _('deleted'),
        default=False,
        help_text=_(
            'Designates whether this product should be treated as deleted. '
            'Unselect this instead of deleting products.'
        ),
    )
    deleted_at = models.DateTimeField(blank=True, null=True)
    history = HistoricalRecords()

    class Meta:
        unique_together = ('name', 'owner')

    def get_categories(self):
        return ",".join([str(p) for p in self.category.all()])

    def get_tags(self):
        return ",".join([str(p) for p in self.tag.all()])

    def __str__(self):
        return self.name

    # Here's where to take a look
    def soft_delete(self):
        self.is_deleted = True
        self.deleted_at = timezone.now()
        self.save()

class EntryProduct(models.Model):
    user = models.ForeignKey(CustomUser, on_delete=models.PROTECT)
    product = models.ForeignKey(Product, on_delete=models.PROTECT)
    name = models.CharField(_('Content Tweet'), max_length=150, blank=True)
    price = models.IntegerField(_('Price in Tokens'), default=0)
    tweet = models.BooleanField(_('tweet is buyed'), default=False)
    abstract = models.BooleanField(_('abstract is buyed'), default=False)
    canvas_01 = models.BooleanField(_('canvas 01 is buyed'), default=False)
    executive_resume = models.BooleanField(_('executive resume is buyed'), default=False)
    graphic_01 = models.BooleanField(_('graphic 01 is buyed'), default=False)
    business_plan = models.BooleanField(_('business plan is buyed'), default=False)
    investor_deck = models.BooleanField(_('investor deck is buyed'), default=False)
    graphic_02 = models.BooleanField(_('graphic 02 is buyed'), default=False)
    buy_date = models.DateTimeField(_('buy date'), default=timezone.now)
    history = HistoricalRecords()

(связано) Просмотр :

# view for the buyer-product-list page
class BuyerProductListView(generic.ListView):
    # name of the object to be used in the store/buyer_product_list.html
    model = Product
    context_object_name = 'product_list'
    template_name = 'store/buyer_product_list.html'
    paginate_by = 3

    # TODO get the right queries.
    # HERE IS WHERE I THINK I HAVE TO DO THE WORK
    # THIS QUERYSET IS WRONG FOR THIS PURPOUSE.
    def get_queryset(self):
        queryset = super(BuyerProductListView, self).get_queryset()
        queryset = queryset.filter(is_deleted=False, owner=self.request.user).order_by('-id')
        return queryset

    # Make the view only available for the users with current fields
    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_buyer:
            raise PermissionDenied()
        return super().dispatch(request, *args, **kwargs)

Дополнительный вопрос : Как вы думаете, было бы неплохо добавить следующие meta к EntryProduct, чтобы избежать повторяющихся записей?

class Meta:
    unique_together = (('user', 'product', 'tweet'),
                        ('user', 'product', 'abstract'),
                        ('user', 'product', 'canvas_01'),
                        ('user', 'product', 'executive_resume'),
                        ('user', 'product', 'graphic_01'),
                        ('user', 'product', 'business_plan'),
                        ('user', 'product', 'investor_deck'),
                        ('user', 'product', 'graphic_02'))

Надеюсь, я все объяснил ясно.Заранее спасибо.

Также, если вы считаете, что есть какой-либо способ улучшить мой код или сделать метод покупки более эффективным, пожалуйста, предложения приветствуются:)

...