0

In views.py I have:

my_computer = Computer.objects.get(pk=some_value)

The computer object has a field called projects that's a ManyRelatedManager.

Calling

my_projects = my_computer.projects.all()

will set the value of my_projects to a list of three project objects.

What I'm trying to achive is to set the value of my_computer.projects to the above list of projects instead of the ManyRelatedManager.

I have tried:

my_computer.projects = my_projects

but that doesn't work, although it doesn't raise an error either. The value of my_computer.projects is still the ManyRelatedManager.

Ionut Hulub
  • 6,180
  • 5
  • 26
  • 55
  • This is not clear. You already get the attribute from `my_computer.projects`, why do you want to set it back to that attribute? – Daniel Roseman Jul 28 '14 at 13:07
  • I can get it's value but I can't change it. – Ionut Hulub Jul 28 '14 at 13:11
  • @DanielRoseman to `my_computer.projects.all()` – Ionut Hulub Jul 28 '14 at 13:52
  • Now I am very confused. You want to set `my_computer.projects` to the value of `my_computer.projects.all()`? You mean you just want to remove the necessity to add the `.all()`? Why? – Daniel Roseman Jul 28 '14 at 14:01
  • @DanielRoseman Yes, that's what I want. I want to do that because afterwards I want to edit the projects list in order to add some extra attributes to the projects before passing them to the template. – Ionut Hulub Jul 28 '14 at 14:03

2 Answers2

1

You can't do that. Your best bet is to simply use another attribute name.

my_computer.related_projects = list(my_computer.projects.all())
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
1

Manager objects implement __set__ - they behave as descriptors.

This means you cannot change the object by assigning it (as long as its attribute of another object - __set__ is only called in the context of __setattr__ on the parent object - parent regarding composition relationships, and not inheritance relationships).

You can assign any list-like (actually: iterable) value to a manager if such iterable value yields models of the expected type. However this means:

  1. When you query my_computer.projects, you will get again a manager object, with the objects you assigned.
  2. When you save the object my_computer, only the specified objects will belong to the relationship - previous object in the relationship will not be related anymore to the current object.

There are three scenarios you could have which led you to this issue:

  1. You need to hold a volatile list - this data is not stored, in any way, but used temporarily. You have to create a normal attribute in the class:

    class Computer(models.Model):
        #normal database fields here
    
        def __init__(self, *args, **kwargs):
            super(Computer, self).__init__(*args, **kwargs)
            #ENSURE this attribute name does not collide with any field
            #I'm assuming the Many manager name is projects.
            self.my_projects = []
    
  2. You need another representation of the exact same relationship - in this way, you want a comfortable way to access the object, instead of calling a strange .all(), e.g. to do a [k.foo for k in mycomputer.my_projects]. You have to create a property like this:

    class Computer(models.Model):
        #Normal database fields here
        #I'm assuming the Many manager name is projects.
    
        @property
        def my_projects(self):
            #remember: my_projects is another name.
            #it CANNOT collide, so I have another
            #name - cannot use projects as name.
            return list(self.projects.all())
    
        @my_projects.setter
        def my_projects(self, value):
            #this only abstracts the name, to match
            #the getter.
            self.projects = value
    
  3. You need another relationship (so it's not volatile data): Create ANOTHER relationship in your model, pointing to the same mode, using the same through if applicable, but using a different related_name= (you must explicitly set related_name for at least one of the multiple relationships to the same model, from the same model)

Luis Masuelli
  • 12,079
  • 10
  • 49
  • 87