how to use Relationship objects

Hi all -

I am interested in a function collecting the ‘child’ objects of a an object automatically. For example, from a Question, collect the Answers to it, and any ‘Comments’ on the Question but using the same code, collect the Questions that have on a particular Poll. Things connected by a OneToOne, ForeignKey or ManyToMany.

Using Model._meta.get_fields() I can get a field that is a “Many-To-One Relationship” from the Question to the Answer model. Naively, I would like to do (and have been trying) something like:

for obj in objs:
    relation_fields = [f for f in obj._meta.get_fields() if field.is_relation and field.concrete]
    child_objs[obj] = []
    for field in relation_fields:
         co =  getattr(obj, field.name).all()
         child_objects.append(co)

# alternative way - this works if a related_name is specified for the reverse relation, but 
# the same type raises an "ManyToOneRel error not callable" for a different field that lacks 
# 'related_name' but is of the same type
         field(manager='objects).all()

I am looking for a consistent interface for objects that refer to my main object, and so far coming up blank. There are so many accessors and its such a thoughtful ORM, but I am stuck on this one. If I can’t find anything better, I’ll slog through by handling a lot of special cases explicitly. Have the feeling that if I understood something better, I’d be on my way though.
`

Yes, Django provides an automatically allocated manager for access from the “reverse side” of a ForeignKey relationship.

See:

and

HI Ken - I have read those but I want to be able to:

  • take a random object from the database (any model),
  • get the ‘related_manager’ for its ManyToOneRel and ManyToMany non-concrete fields
  • run a function of or on the related_manager object that will return the queryset of related objects

But - good news, I worked out that what I want to do is:

for field in obj._meta.get_fields():
    if type(field) == models.ManyToOneRel:
        obj_children.add(getattr(obj, obj._meta.get_field(field.name).get_accessor_name()).all())
   elif type(field) == models.ManyToManyRel:
         obj_children.add(getattr(obj, obj._meta.get_field(field.name).get_attname()).all())
1 Like