django-taggit icon indicating copy to clipboard operation
django-taggit copied to clipboard

tag_model uninitialized in migrations

Open wrichert opened this issue 8 years ago • 9 comments

I'm trying to migrate django-tagging to django-taggit. After having run a migration to add it side-by-side such that it looks like this:

 class Flow(models.Model):
      tags = TagField()
     new_tags = TaggableManager()

I was trying to copy over the tags:

def transfer_tags(apps, schema_editor):
    Flow = apps.get_model("flow", "Flow")
    for f in Flow.objects.all():
        if f.tags:
            f.new_tags.add(*f.tags.split(" "))
            f.save()


class Migration(migrations.Migration):

    dependencies = [
        ('flow', '0003_flow_new_tags'),                                                                                                                                                                                                      
    ]

    operations = [
            migrations.RunPython(transfer_tags),
    ]

But this ran into an AttributeError when running 'migrate':

> ~/env/local/lib/python2.7/site-packages/taggit/managers.py(192)_to_tag_model_instances()
    190         for t in tags:
    191             import ipdb;ipdb.set_trace()
--> 192             if isinstance(t, self.through.tag_model()):
    193                 tag_objs.add(t)
    194             elif isinstance(t, six.string_types):

ipdb> self.through
<class 'TaggedItem'>

And when I continue, I am getting this error:

AttributeError: type object 'TaggedItem' has no attribute 'tag_model'

wrichert avatar Dec 29 '16 17:12 wrichert

I'm facing the same issue

jorenham avatar Aug 17 '17 13:08 jorenham

This happens because django creates a state for the migrations. In doing this it does not make models methods accessible - in this case tag_model. I'm not sure on a straightforward solution. Any suggestions?

wrdeman avatar Jan 12 '18 11:01 wrdeman

I'm also facing the same issue, when attempting a data migration, but for the "tags_for" attribute.

alexseitsinger avatar Apr 10 '18 08:04 alexseitsinger

At migration you need do something like this.

mgr = CustomTaggableManager(through=CustomTaggedItem, model=apps.get_model('my_app', 'MyModelInThisApp'), instance=instance_of_MyModelInThisApp, prefetch_cache_name='tags')

mgr.add('custom_name')

DmytroLitvinov avatar May 24 '18 11:05 DmytroLitvinov

I'm having the same issue.

frattallone avatar May 14 '19 14:05 frattallone

Would be great to find a solution for this and document it somewhere.

steverecio avatar Dec 23 '19 18:12 steverecio

I added this snipped to my data migration and it seemed to work well. Might be nice to generalize it and add a helper utility somewhere.

tags = ['tag1', 'tag2']
Tag = apps.get_model('taggit', 'Tag')
TaggedItem = apps.get_model('taggit', 'TaggedItem')
ContentType = apps.get_model('contenttypes', 'ContentType')
ct = ContentType.objects.get(app_label="myapp", model="mymodel")
for tg in tags:
    t, created = Tag.objects.get_or_create(name=tg)
    tagged_items, created = TaggedItem.objects.get_or_create(
            content_type_id=ct.id,
            object_id=my_model_instance.id,
            tag=t
    )

steverecio avatar Dec 23 '19 18:12 steverecio

yeah in a data migration you'll have to do stuff by hand (copying to through tables etc). If anyone could write up a small guide for steps going from django-tagging to django-taggit we can put it in the docs

rtpg avatar Apr 14 '21 06:04 rtpg

I added this snipped to my data migration and it seemed to work well. Might be nice to generalize it and add a helper utility somewhere.

tags = ['tag1', 'tag2']
Tag = apps.get_model('taggit', 'Tag')
TaggedItem = apps.get_model('taggit', 'TaggedItem')
ContentType = apps.get_model('contenttypes', 'ContentType')
ct = ContentType.objects.get(app_label="myapp", model="mymodel")
for tg in tags:
    t, created = Tag.objects.get_or_create(name=tg)
    tagged_items, created = TaggedItem.objects.get_or_create(
            content_type_id=ct.id,
            object_id=my_model_instance.id,
            tag=t
    )

@steverecio What do you do with the tagged_items after this though? I'm trying to get this to work with a data migration as well, and trying to save the TaggedItem back to mymodel is not working, and still giving me the same error.

bmoe872 avatar Jun 07 '21 23:06 bmoe872