【问题标题】:Django get the Model name using ORM's related field nameDjango 使用 ORM 的相关字段名称获取模型名称
【发布时间】:2017-03-30 04:12:12
【问题描述】:

我有一个像 order__product__category__description 这样的字符串,这是我的 Django 模型结构的相关表达式

现在我有一个模型叫Shipment

field = 'order__product__category__description'

这里description是表/模型Category的列名。问题来了,只要有这个模型Shipment和这个字段字符串order__product__category__description,我如何找到这些模型OrderProductCategory

我的用例是我需要将Category 的所有字段名称存储在一个列表中。关于如何连接点的任何想法?只留下了两个细节Shipment 和那个字段字符串。

首先想到的是按__ 拆分,然后得出一个类似['order','product','category'] 的列表,然后根据字段名称迭代模型_meta。任何其他优雅的方式将不胜感激。

【问题讨论】:

    标签: django django-models


    【解决方案1】:

    如果要从模型类中获取相关模型(而不是从模型实例中获取相关实例),可以使用_meta.get_field()结合field.related_model获取相关模型类:

    from django.core.exceptions import FieldDoesNotExist
    
    model = Shipment
    lookup = 'order__product__category__description'
    
    for name in lookup.split('__'):
        try:
            field = model._meta.get_field(name)
        except FieldDoesNotExist:
            # name is probably a lookup or transform such as __contains
            break
        if hasattr(field, 'related_model'):
            # field is a relation
            model = field.related_model
        else:
            # field is not a relation, any name that follows is
            # probably a lookup or transform
            break
    

    然后用model 做你想要的。

    【讨论】:

    • 消化这个问题并理解我真正在寻找什么需要耐心。很好的答案。赞~
    【解决方案2】:

    我没听懂。无论如何希望这是你想要的。

    field = 'order__product__category__description' 
    

    Shipment 实例中获取product

    product_var = ".".join(field.split("__")[:2]) 
    

    然后

    from operator import attrgetter
    attrgetter(product_var)(shipment_instance)
    

    您还可以通过tuple 获取所有相关信息

    attrgetter(".".join(field.split("__")[:1]), ".".join(field.split("__")[:2]), ".".join(field.split("__")[:3]), ".".join(field.split("__")[:4]))(shipment_instance)
    

    希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      假设您已将字符串拆分为一个列表,正如您对这些所说的:

      models = ['order', 'product', 'category']
      

      首先获取每个模型引用的app标签(一个字符串):

      from django.contrib.contenttypes.models import ContentType
      
      app_labels = []
      
      for model in models:
          app_labels.append(ContentType.objects.filter(model=model).values('app_label').first().get('app_label'))
      

      现在您拥有model 名称和app 名称。所以:

      from django.apps import apps
      
      model_classes = []
      
      for app, model in zip(app_labels, models):
          model_classes.append(apps.get_model(app, model))
      

      最后,用你已经知道的_meta 属性获取每个模型字段:

      for model in model_classes:
          print(model._meta.get_fields())
      

      【讨论】:

        猜你喜欢
        • 2021-04-18
        • 2016-03-26
        • 2012-11-05
        • 1970-01-01
        • 2021-01-24
        • 1970-01-01
        • 1970-01-01
        • 2011-03-10
        • 2011-07-04
        相关资源
        最近更新 更多