Question

I have a simple model class with 2 ManyToManyField fields like this:

models.py

class Folder(models.Model):
    user = models.ManyToManyField(User)
    asset = models.ManyToManyField(Asset)

In my view, I know the user ID and the asset ID. Say the user ID is 1 and the asset ID is 30, how do I inject this row? I guess I don't understand how to instantiate Folder so I can save/update the row.

views.py

def addAssetToMyFolder(request, id=None):
    ''' view is simplified for brevity
    '''
    f = Folder(
        user = 1,
        asset = 30,
    )
    f.save()
Was it helpful?

Solution

To associate a user or asset instance with a folder you need to first save the folder.

To store a many to many relationship the database creates a third table which stores the ids of the objects.

So if you want to relate a user to a folder as a many to many relationship, both of them should have their own ids before they can be related as many to many.

Say you have two users with ids 10 and 19 respectively. You have one folder with id 4 and user 10 and user 19 are related to this folder. At the db level this how these relations will be stored

   folder_id       user_id
       4            10
       4            19

so for each many to many relation there is one row in the relations table for the two models.

Same will be valid for asset.

So the code should be changed to:

def addAssetToMyFolder(request, id=None):
    ''' view is simplified for brevity
    '''
    f = Folder()
    f.save()
    user = User.objects.get(id=1)  # not needed if adding by id
    f.user.add(user)  # or f.user.add(user_id)
    asset = Asset.objects.get(id=30)  # not needed if adding by id
    f.asset.add(asset)  # or f.asset.add(asset_id)

check out : https://docs.djangoproject.com/en/1.6/topics/db/examples/many_to_many/

OTHER TIPS

Because I reallllly hate redundancy, here's a another solution using a dynamic modelform. The benefits are it's neater, you don't need to fetch the User and Asset objects, you use the related pk and you only save once.

The drawback is that it's overkill for the common everyday need. So you should probably mark @zaphod100.10 answer as correct, but know that this method also exists:

Meta = type('Meta', (), {'model': Folder, 'fields': ['user', 'asset']} )
FolderForm = type('FolderForm', (forms.ModelForm, ), {'Meta': Meta})

data = {'user': ['1'], 'asset': ['30']} #the values need to be a list of strings, representing pks of related objects
f = FolderForm(data)
new_obj = f.save()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top