使用Django-taggit与django-rest-framework,我无法保存我的标签 [英] Using Django-taggit with django-rest-framework, i'm not able to save my tags
问题描述
我想知道为什么当我提交表单时,我的标签没有保存在我的数据库中。相当新的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屋!