使用Django-taggit与django-rest-framework,我无法保存我的标签 [英] Using Django-taggit with django-rest-framework, i'm not able to save my tags

查看:282
本文介绍了使用Django-taggit与django-rest-framework,我无法保存我的标签的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道为什么当我提交表单时,我的标签没有保存在我的数据库中。相当新的django-rest框架和Django-taggit,我想我做错了事情:)

I'm trying to figure it out why when i submit my form, my tags are not saved in my db. Pretty new with the django-rest-framework and Django-taggit too, i think i'm doing something wrong :)

首先,在我的API与其余的 - 框架,我正在使用通用视图(CreateView和UpdateView)来注册/验证我的事件。这是工作正常,但我决定进一步尝试建立一个API,因为我现在使用Angularjs。

First, before making my API with the rest-framework, i was using a generic view (CreateView and UpdateView) to register/validate my event. It was working fine but i decided to go further and try to build an API since i'm using Angularjs now.

现在我的模型事件被创建,但没有我的标签和我有一些错误。我放了一些代码,我会描述我的错误。

Now my model event is created but without my tag and i have some errors. I put some code and i'll describe my errors after.

events / models.py

class Event(models.Model):
[...]

    title = models.CharField(max_length=245, blank=False)
    description = models.TextField(max_length=750, null=True, blank=True)
    start = models.DateTimeField()
    end = models.DateTimeField()
    created_at = models.DateTimeField(editable=False)
    updated_at = models.DateTimeField(editable=False)
    slug = AutoSlugField(populate_from='title', unique=True, editable=False)
    expert = models.BooleanField(choices=MODE_EXPERT, default=0)
    home = models.BooleanField(choices=HOME, default=0)
    nb_participant = models.PositiveSmallIntegerField(default=1)
    price = models.PositiveSmallIntegerField(default=0)
    cancelled = models.BooleanField(default=0)

    user = models.ForeignKey(User, editable=False, related_name='author')
    address = models.ForeignKey('Address', editable=False, related_name='events')
    participants = models.ManyToManyField(User, related_name='participants', blank=True, editable=False,
                                      through='Participants')
    theme_category = models.ForeignKey('EventThemeCategory', unique=True, editable=False)

    tags = TaggableManager(blank=True)

    class Meta:
        db_table = 'event'

    def save(self, *args, **kwargs):
        if not self.pk:
            self.created_at = timezone.now()
        self.updated_at = timezone.now()
        super(Event, self).save(*args, **kwargs)
    [...]

我正在使用serializers.HyperlinkedModelSerializer。

i'm using the serializers.HyperlinkedModelSerializer.

api / serializer.py

from taggit.models import Tag

class TagListSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Tag
        fields = ('url', 'id', 'name')


class EventSerializer(serializers.HyperlinkedModelSerializer):
    address = AddressSerializer()
    user = UserSerializer(required=False)
    tags = TagListSerializer(blank=True)

    class Meta:
        model = Event
        fields = ('url', 'id', 'title', 'description', 'start', 'end', 'created_at', 'updated_at', 'slug', 'expert','home', 'nb_participant', 'price', 'address', 'user', 'theme_category', 'tags')
        depth = 1

api / views / tags_views.py

from rest_framework import generics
from api.serializers import TagListSerializer
from taggit.models import Tag


class TagsListAPIView(generics.ListCreateAPIView):
    queryset = Tag.objects.all()
    model = Tag
    serializer_class = TagListSerializer


class TagsDetailAPIView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Tag.objects.all()
    model = Tag
    serializer_class = TagListSerializer

api / views / events_views.py

api/views/events_views.py

class EventListAPIView(generics.ListCreateAPIView):
    queryset = Event.objects.all()
    model = Event
    serializer_class = EventSerializer
    paginate_by = 100

    def pre_save(self, obj):
        """
        Set the object's owner, based on the incoming request.
        """
        obj.user = self.request.user
        return super(EventListAPIView, self).pre_save(obj)

api / urls.py

    url(r'^events/(?P<slug>[0-9a-zA-Z_-]+)/$', EventDetailAPIView.as_view(), name='event-detail'),

首先,当我打电话给 / api / events / name-of-my-event 发送给我很好的资源与我的标签,它的GET方法是正常工作。

So first when i call /api/events/name-of-my-event the API send me the good resource with my tags on it. The GET method is working fine.

我以为休息框架遵循查询集,所以如果我可以得到资源与所有我的标签为什么当我使用POST我的标签没有注册?

I was thinking that rest-framework follow the query set. So if i can get the resource with with all my tags why when i use POST my tags are not register ?

其实我有两个POST方法的问题:

Actually i have two problems with the POST method:


  • 第一个,如果我发送一个我已经创建的标签,他给我发送一个错误,说标签必须是唯一的,我明白,我不想创建一个新的,我只是希望它与我的对象链接当我使用通用视图(它是由魔术完成的),并且所有都正常工作时,没有这个问题)

  • 其次,当我尝试创建一个新的标签时,我的新事件是保存,但没有我的标签。
    您可以看到我的标签的angularjs收到的响应...他给我发送标签的名称,但没有id,url(超链接)。当我检查我的数据库时,标签尚未创建。

我想我必须在我的tags_views中定制一个get_queryset(self),但我不确定。
我会继续调查。如果有人已经有了这个建议,我会非常API。谢谢。

I think i have to make a custom get_queryset(self) in my tags_views but i'm not sure. I'll will continue to investigate. If someone have already to that and have some advise, i'll be very API. Thanks.

推荐答案

遇到同样的问题。但是我只是想通过TaggableManager直接保存标签列表(没有TagListSerializer和TagsListAPIView)。我的解决方案是:

meet the same question. But I just want to save the tag list directly by TaggableManager (without TagListSerializer and TagsListAPIView). My solution is:

class MyModel(models.Model):
    ...
    tags = TaggableManager(blank=True)

    def get_tags_display(self):
        return self.tags.values_list('name', flat=True)

class MyModelSerializer(serializers.HyperlinkedModelSerializer):
    ...
    tags = serializers.Field(source='get_tags_display') # more about: http://www.django-rest-framework.org/api-guide/fields#generic-fields
    ...

class MyModelViewSet(viewsets.ModelViewSet):
    ...
    def post_save(self, *args, **kwargs):
        if 'tags' in self.request.DATA:
            self.object.tags.set(*self.request.DATA['tags']) # type(self.object.tags) == <taggit.managers._TaggableManager>
        return super(MyModelViewSet, self).post_save(*args, **kwargs)

标签数据的帖子数据将是['tagA','tagB',...],TaggableManager将处理它。 Thx。

The post data of tags data will be ['tagA', 'tagB',...], the TaggableManager will handle it. Thx.

对于DRF> 3.1,您只需要在ModelSerializer类中重写创建和更新:

For DRF>3.1, you just need to override create and update in your ModelSerializer class:

class StringListField(serializers.ListField): # get from http://www.django-rest-framework.org/api-guide/fields/#listfield
    child = serializers.CharField()

    def to_representation(self, data):
        return ' '.join(data.values_list('name', flat=True)) # you change the representation style here.


class MyModelSerializer(serializers.ModelSerializer):
    tags = StringListField()

    class Meta:
        model = models.MyModel

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

    def update(self, instance, validated_data):
        # looks same as create method

这篇关于使用Django-taggit与django-rest-framework,我无法保存我的标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆