如何让Django Queryset根据另一个模型字段过滤一个模型条目

时间:2018-06-09 11:01:14

标签: django django-models django-views django-queryset django-template-filters

我正在尝试根据用户购买的内容(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'))

我希望我已经清楚地解释了自己。提前谢谢。

此外,如果您认为有任何方法可以改进我的代码或使购买方法更有效,欢迎提出建议:)

0 个答案:

没有答案