1

在我的 Django 项目中,我有一个产品模型,如下所示:

class Manufacturer(models.Model):
    name = models.CharField(max_length=100)

class Product(models.Model):
    manufacturer = models.ForeignKey('Manufacturer')
    # .favorite_set: ManyToOne relation coming from the
    # 'Favorite' class (shown a couple of lines below)

我网站的用户可以将某些产品标记为收藏。为了提供这个功能,我有一个看起来像这样的 Django 模型:

class Favorite(models.Model):
    user = models.ForeignKey(User)
    product = models.ForeignKey('Product')

    class Meta:
        unique_together = ('user', 'product',)

在该模型中, ForeignKey 在名为 的模型.product中创建反向关系。这一切都很好而且有用:当我收到用户的 HTTP 请求以检索产品时,我可以通过执行以下操作轻松确定它是否被特定用户收藏:Productfavorite_set

product = Product.objects.get(id='whatever_id')
is_favorited = bool(product.favorite_set.filter(user=self.user).count() == 1)
# or probably:
#   is_favorited = product.favorite_set.filter(user=self.user).exists()
# 

现在,我有另一个模型是高度非规范化的(即 SQL 非规范化),我想将其用于快速文本搜索。

此模型“假装”为产品,但将通过“常规”产品的 FK 关系找到的数据包含到模型本身中。像这样的东西:

class ProductSearch(models.Model):
    product = models.OneToOneField('Product', 
                                   on_delete=models.CASCADE,
                                   related_name='searcher')
    product_name = models.CharField(max_length=100)
    manufacturer_name = models.CharField(max_length=100)

此类有自己的id字段(因为它是 Django 模型),并且如您在上面看到的,它将OneToOne与产品有关系(其中一个ProductSearch条目链接到一个且只有一个Product

由于这个模型,如果我想搜索制造商是“福特”的产品(例如),我不需要将Product表与Manufacturer' 表连接起来。我可以直接进行查找ProductSearch并节省几毫秒。

由于ProductSearch旨在与 a 兼容Product,因此我还尝试将favorite_set在我的班级中“自然”发生的建模Product到此ProductSearch模型中。

这就是困难出现的地方:我不知道该怎么做:-)

理想情况下,我会有类似的东西:

class ProductSearch(models.Model):
    product = models.OneToOneField('Product', 
                                   on_delete=models.CASCADE,
                                   related_name='searcher')
    manufacturer_name = models.CharField(max_length=100)
    #
    # Couldn't find anything to do the following:
    product_favorite_set = models.ManyToOneField('Favorite',
                                                 through_fields=('product',))

但我无法做到这一点。

我试图“滥用”ManyToManyField这样的:

class ProductSearch(BaseModel):
    product = models.OneToOneField('Product', 
                                   on_delete=models.CASCADE,
                                   related_name='searcher')
    product_name = models.CharField(max_length=100)
    manufacturer_name = models.CharField(max_length=100)
    product_favorite_set = models.ManyToManyField('Favorite', related_name='+',
                                              through='Favorite',
                                              through_fields=['product']
                                              )

但这会在系统检查中产生错误:

api.Favorite: (fields.E336) The model is used as an intermediate model
              by 'api.ProductSearch.product_favorite_set', but it
              does not have a foreign key to 'ProductSearch' or 'Favorite'.
api.ProductSearch.product_favorite_set: (fields.E339) 'Favorite.product'
              is not a foreign key to 'ProductSearch'.

我想我可以制作product_favorite_set一个 Python @property,然后在其中进行自定义查询,例如:

class ProductSearch(BaseModel):
     # ....
     @property
     def product_favorite_set(self):
           return Favorite.objects.filter(product=self.product)

但我想知道我是否可以使用“纯” Django 工具来做到这一点(仅出于好奇)

任何帮助将不胜感激。先感谢您。

4

0 回答 0