【问题标题】:Django: Check for related objects and whether it contains dataDjango:检查相关对象及其是否包含数据
【发布时间】:2014-06-01 07:04:33
【问题描述】:

例如,我在汽车管理系统(网页)中有两个模型:

    class Brand(models.Model):
        brand_name= models.CharField(max_length=100, null=False)

    class Cars(models.Model):
        car_model= models.CharField(max_length=100, null=False)
        car_production_year= models.CharField(max_length=100, null=False)
        car_brand= models.ForeignKey(Brand, null=True, blank=True, default = None)

现在,我想从汽车系统中删除品牌数据。如何检查此品牌是否已在其他模型中使用,或者该外键是否包含任何数据(因为我已允许 Cars 模型中的 car_brand 为 null True)。

PS: 使用此功能:

self.model._meta.get_all_related_objects():

我在 Brand 模型类中使用了任何相关对象。但是,我不知道该相关对象是否包含任何数据。

【问题讨论】:

    标签: python django


    【解决方案1】:

    使用exists()。它专为这种情况而设计:

    for brand in Brand.objects.all():
        if not brand.cars_set.all().exists():
            # delete
    

    此外,它几乎总是比任何其他类型的检查都快,因为它被设计为在数据库级别工作。您可以在docs 中阅读exists() 行为的详细信息

    【讨论】:

    • 非常感谢。虽然我在寻找动态的东西,比如我想覆盖删除操作( def delete(self): )并捕获将要删除的模型有任何活动的相关对象。如果是,则引发异常,否则删除。
    • 您可以使用与我在答案中发布的相同逻辑来执行此操作。但不要覆盖delete(),而是在您的品牌模型上使用pre_deletepost_delete 信号,因为使用QuerySet 批量删除对象时,不一定会调用对象的delete() 方法。
    • query_set.all().exists()query_set.exists() 一样吗?
    • 是的,它们是一样的,我只是用all()来表明你可以在queryset和exists()之间放些别的东西,例如filter()
    • 我们如何获取模型上的所有关系字段来检查它们是否存在?
    【解决方案2】:

    来自this question,对于我的代码,这更快:

    for b in Brand.objects.filter(cars__isnull=True):
        # delete
    

    如果你有 ids(我的情况),我用这个(比 cars_set 快 60%):

    for brand_id in brand_id_set:
        if Brand.objects.filter(id=brand_id).filter(cars__isnull=True):
            # delete
    

    我正在使用 Django 1.11

    【讨论】:

      【解决方案3】:

      我想说最简单的方法是这样的:

      # brand is an instance of Brand
      
      if not brand.cars_set.all():
          # delete
      else:
          # do something else
      

      Django docs 非常详细地介绍了外键。

      【讨论】:

      • 在模板中使用all() 更有意义。当不存在相关对象时您不想输出任何内容。 {% with model.rmodel_set as rmodels %}{% if rmodels %}<table>{% for rmodel in rmodels %}<tr><td>...{% endfor %}</table>{% endif %}{% endwith %}.
      【解决方案4】:
      cars_with_brands = Car.objects.filter(car_brand__isnull = False)
      if cars_with_brands.count() == 0:
          # you can delete Brand Model
      else:
         cars_with_brands.delete()
         # you can delete Brand Model
      

      【讨论】:

        猜你喜欢
        • 2020-06-07
        • 2022-11-09
        • 2019-08-24
        • 2021-03-09
        • 2013-05-15
        • 1970-01-01
        • 2020-08-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多