jazzband / django-taggit

Simple tagging for django
https://django-taggit.readthedocs.io
BSD 3-Clause "New" or "Revised" License
3.31k stars 624 forks source link

TypeError: Object of type _TaggableManager is not JSON serializable #839

Open mirodil1 opened 1 year ago

mirodil1 commented 1 year ago

I am using django-taggit, django-parler, django-parler-rest and django-rest-framework on my project and getting following errors when trying to get or add object.

models.py

class Post(TimeStampedModel):
    translations = TranslatedFields(
      name = models.CharField(
          max_length=255,
          db_index=True,
      ),
      slug = models.SlugField(
          max_length=255,
          db_index=True,
          unique=True,
      )
      tags = TaggableManager(),
    )

serializer.py

class PostSerializer(TaggitSerializer, TranslatableModelSerializer):
    tags = TagListSerializerField()
    translations = TranslatedFieldsField(shared_model=Posts)

    class Meta:
        model = Posts
        fields = [
            "id",
            "name",
            "translations",
            "tags",
        ]
rtpg commented 1 year ago

@mirodil1 do you have a full stack trace for these errors? this is not enough information for us to figure things out.

mirodil1 commented 1 year ago

@rtpg no atm, I guess the problem was with django-parler, it creates translations table and there is also field for django-taggit, in serializer it should be defined as tags=TagListSerializerField() , and for tags field in translations also should be TagListSerializerField() somehow.

rosamundm commented 1 year ago

Hi, I came across this issue as I got the same error when using tags with factory-boy (otherwise everything is working great, thanks!). Would be great if you could take another look at it.

I added the following to my existing factory class, as suggested in your docs:

@post_generation
def tags(self, create, extracted, **kwargs):
    if not create:
        return
    if extracted:
        self.tags.add(*extracted)

Then when I ran my tests, I got the following stack trace, in case that helps you figure out the problem:

self = <json.encoder.JSONEncoder object at 0x107460820>
o = <taggit.managers._TaggableManager object at 0x109af23a0>

    def default(self, o):
        """Implement this method in a subclass such that it returns
        a serializable object for ``o``, or calls the base implementation
        (to raise a ``TypeError``).

        For example, to support arbitrary iterators, you could
        implement default like this::

            def default(self, o):
                try:
                    iterable = iter(o)
                except TypeError:
                    pass
                else:
                    return list(iterable)
                # Let the base class default method raise the TypeError
                return JSONEncoder.default(self, o)

        """
>       raise TypeError(f'Object of type {o.__class__.__name__} '
                        f'is not JSON serializable')
E       TypeError: Object of type _TaggableManager is not JSON serializable

/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/encoder.py:179: TypeError
sarozpradhan64 commented 1 month ago

the solution for this issue in django-taggit is to import the built in TagListSerializerField from the django-taggit itself.

from taggit.serializers import TagListSerializerField, TaggitSerializer

class BlogSerializer(TaggitSerializer, serializers.ModelSerializer):
    tags = TagListSerializerField(required=False)