Get all related Django model objects

后端 未结 9 1241
攒了一身酷
攒了一身酷 2020-11-27 09:46

How can I get a list of all the model objects that have a ForeignKey pointing to an object? (Something like the delete confirmation page in the Django admin before DELETE C

相关标签:
9条回答
  • 2020-11-27 10:30
    for link in links:
        objects = getattr(a, link).all()
    

    Works for related sets, but not for ForeignKeys. Since RelatedManagers are created dynamically, looking at the class name is easier than doing an isinstance()

    objOrMgr = getattr(a, link)
     if objOrMgr.__class__.__name__ ==  'RelatedManager':
          objects = objOrMgr.all()
     else:
          objects = [ objOrMgr ]
     for object in objects:
          # Do Stuff
    
    0 讨论(0)
  • 2020-11-27 10:31

    @digitalPBK was close... here is probably what you are looking for using Django's built-in stuff that is used in Django admin for displaying related objects during deletion

    from django.contrib.admin.utils import NestedObjects
    collector = NestedObjects(using="default") #database name
    collector.collect([objective]) #list of objects. single one won't do
    print(collector.data)
    

    this allows you to create what the Django admin displays - the related objects to be deleted.

    0 讨论(0)
  • 2020-11-27 10:37

    links = [rel.get_accessor_name() for rel in a._meta.get_all_related_objects()]

    You can then use something like this to get all related objects:

    for link in links:
        objects = getattr(a, link.name).all()
        for object in objects:
            # do something with related object instance
    

    From Django 1.10 offical docs:

    MyModel._meta.get_all_related_objects() becomes:

    [
        f for f in MyModel._meta.get_fields()
        if (f.one_to_many or f.one_to_one)
        and f.auto_created and not f.concrete
    ]
    

    So by taking the approved example we would use:

    links = [
                f for f in MyModel._meta.get_fields()
                if (f.one_to_many or f.one_to_one)
                and f.auto_created and not f.concrete
            ]
    
    for link in links:
        objects = getattr(a, link.name).all()
        for object in objects:
            # do something with related object instance
    
    0 讨论(0)
  • 2020-11-27 10:38

    Here is another way to get a list of fields (names only) in related models.

    def get_related_model_fields(model):
        fields=[]
        related_models = model._meta.get_all_related_objects()
        for r in related_models:
            fields.extend(r.opts.get_all_field_names())
        return fields
    
    0 讨论(0)
  • 2020-11-27 10:39

    Django <= 1.7

    This gives you the property names for all related objects:

    links = [rel.get_accessor_name() for rel in a._meta.get_all_related_objects()]
    

    You can then use something like this to get all related objects:

    for link in links:
        objects = getattr(a, link).all()
        for object in objects:
            # do something with related object instance
    

    I spent a while trying to figure this out so I could implement a kind of "Observer Pattern" on one of my models. Hope it's helpful.

    Django 1.8+

    Use _meta.get_fields(): https://docs.djangoproject.com/en/1.10/ref/models/meta/#django.db.models.options.Options.get_fields (see reverse in the _get_fields() source also)

    0 讨论(0)
  • 2020-11-27 10:42

    The following is what django uses to get all related objects

    from django.db.models.deletion import Collector
    collector = Collector(using="default")
    collector.collect([a])
    
    print collector.data
    
    0 讨论(0)
提交回复
热议问题