Django saving to ManyToMany fields

2019-08-29 04:30发布

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()

2条回答
倾城 Initia
2楼-- · 2019-08-29 05:08

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 a retarded 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()
查看更多
ら.Afraid
3楼-- · 2019-08-29 05:21

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/

查看更多
登录 后发表回答