简体   繁体   中英

Using Django-taggit and django-taggit-serializer with issue

I am trying to add tags in my model by taggit and taggit serializer. I making my API in rest framework. I followed the instruction( https://github.com/glemmaPaul/django-taggit-serializer ) but it is still an issues:

"tags": [ "Invalid json list. A tag list submitted in string form must be valid json."]

/setting.py

INSTALLED_APPS = [
  [...]
'rest_framework',
'taggit',
'taggit_serializer',
]

/models.py

tags = TaggableManager(blank = True) 

/serializer.py

class JobSerializer(TaggitSerializer,serializers.HyperlinkedModelSerializer):

# tag serializer
tags = TagListSerializerField()

There is noting changed in the view.py.

thanks @ykh for helping me to solve this problem, but it comes to new situation with error:

when you want to initial the value:

hao,free

the outcome will be like that:

 "tags": [
    "hao",
    "free"
],

But when I intend to put updates into this value: it showed the Json file in rest framework automatically:

在此处输入图像描述

and if you put data to your api, the result will be:

在此处输入图像描述

The issue is that each time when I try to modify the instance which including the 'tag' in rest framework, brackets and line breaks were automatic attached added in 'tag' field, like the picture result shows


Update: It seems that I have solved this issue, the solution is overriding the create function in serializer:

using django-taggit-serializer. and

    def create(self, validated_data):
    tags = validated_data.pop('tags')
    instance = super(JobSerializer, self).create(validated_data)
    instance.tags.set(*tags)
    return instance

try:

import six

class NewTagListSerializerField(TagListSerializerField):
    def to_internal_value(self, value):
        if isinstance(value, six.string_types):
            value = value.split(',')

        if not isinstance(value, list):
            self.fail('not_a_list', input_type=type(value).__name__)

        for s in value:
            if not isinstance(s, six.string_types):
                self.fail('not_a_str')

            self.child.run_validation(s)
        return value

class JobSerializer(TaggitSerializer,serializers.HyperlinkedModelSerializer):

    tags = NewTagListSerializerField()

post tags with ' tags1,tags2 '

The original source code is :

def to_internal_value(self, value):
    if isinstance(value, six.string_types):
        if not value:
            value = "[]"
        try:
            value = json.loads(value)
        except ValueError:
            self.fail('invalid_json')

    if not isinstance(value, list):
        self.fail('not_a_list', input_type=type(value).__name__)

    for s in value:
        if not isinstance(s, six.string_types):
            self.fail('not_a_str')

        self.child.run_validation(s)

    return value

the error is caused by json.loads(value) is not success and i don't konw which data type is excepted.

Correction to the answer above, because solution by Ykh works incorrect, when i want to update my tags in JSON format(i got \\r \\m \\ symbols)

import json

class NewTagListSerializerField(TagListSerializerField):
    def to_internal_value(self, value):
        if isinstance(value, six.string_types):
            if not value:
                value = "[]"
            try:
                if(type(value) == str):
                    if(value.__contains__('"') == True):
                        value = json.loads(value)
                    else:
                        value = value.split(',')

            except ValueError:
                self.fail('invalid_json')

        if not isinstance(value, list):
            self.fail('not_a_list', input_type=type(value).__name__)

        for s in value:
            if not isinstance(s, six.string_types):
                self.fail('not_a_str')

            self.child.run_validation(s)

        return value

I've just had this issue when writing unit tests. It's because the python dictionary that I used to store the POST data becomes internally converted into a QueryDict. This typically happens when Django considers the POST as content of type application/x-www-form-urlencoded , eg something sent via an HTML form.

I think TagListSerializerField is expecting json, so when its to_internal_value is called, incorrect data is being received and it fails with the "Invalid json list..." error.

In short, this is what I had to do.

data = {"tags": ["tag1", "tag2"]}
response = self.client.post('/api/endpoint/', json.dumps(data), content_type='application/json')

In other words, the data needs to be converted to json, and the content type has to be set. In my example, self.client is a APIClient from from rest_framework.test .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM