Home > Mobile >  Django: how to update a ManyToManyField in a custom Django management task?
Django: how to update a ManyToManyField in a custom Django management task?

Time:02-03

In Django I have a model where one of the fields (tags) is a ManyToManyField:

class MyModel(models.Model):

   id = models.CharField(max_length=30, primary_key=True)
   title = models.CharField(max_length=300, default='')
   author = models.CharField(max_length=300)
   copy = models.TextField(blank=True, default='')
   tags = models.ManyToManyField(Tag)

I have a custom management task below where I'm getting all of the instances of the MyModel table on a server and using that to replace the instances of the MyModel table on my local server. (I'm running this custom management task from my local)

Here's what I'm trying so far.

However I'm getting this error: CommandError: Direct assignment to the forward side of a many-to-many set is prohibited. Use tags.set() instead.

How can I update the tags field that's a ManyToMany field?

from bytes.models import MyModel

class Command(BaseCommand):

    def handle(self, *args, **options):

        try:
            // get queryset of MyModel instances from server
            queryset = MyModel.objects.using('theserver').all()

            // loop through that queryset and create a list of dictionaries
            mymodel_list = [
                {
                    'id': mymodel['id'],
                    'title': mymodel['title'],
                    'author': mymodel['author'],
                    'copy': mymodel['copy'],
                    'tags': mymodel['tags']
                } 
                for mymodel in queryset
            ]

            //delete all objects in the local MyModel table
            MyModel.objects.all().delete() 

            //replace with MyModel instances from server
            new_mymodel = [
                MyModel(
                    id=mymodel['id'],
                    title=mymodel['title'],
                    author=mymodel['author'],
                    copy=mymodel['copy'],
                    tags=mymodel['tags'] <--- causing error
                )
                for mymodel in mymodel_list
            ]

            MyModel.objects.bulk_create(new_mymodel)

CodePudding user response:

ManyToMany fields are working differently from any other field. You cannot simply copy it's values, especially from strings. You can try add objects in a loop just after after creating MyModel:

    //replace with MyModel instances from server
    new_mymodels = []
    for mymodel in mymodel_list:
        new_mymodel = MyModel(
                id=mymodel['id'],
                title=mymodel['title'],
                author=mymodel['author'],
                copy=mymodel['copy']
            )

        for tag in mymodel['tags']:
            new_mymodel.tags.add(tag)

        new_mymodels.append(new_mymodel)

    MyModel.objects.bulk_create(new_mymodel)

It is possible, that you will have to firstfully find the Tag object before .add() method. It depends on values in mymodel['tags'].

  •  Tags:  
  • Related