所以我试图通过django-rest-framework (DRF)
创建一个可浏览的API,但是我遇到了一些嵌套序列化器的问题。到目前为止,我可以将Sport
和Category
字段/ foreignkeys包含到我的Article
中,但是当我通过API尝试POST
时,我收到错误消息如下:
在致电
TypeError
时获得Article.objects.create()
。这可能是因为序列化程序类上的可写字段不是Article.objects.create()
的有效参数。您可能需要将该字段设置为只读,或覆盖ArticleSerializer.create()方法以正确处理此字段。 原始异常文本是:int()参数必须是字符串,类似字节的对象或数字,而不是' ArticleSport'。
以下是我的文件:
models.py
[...]
class ArticleSport(TimeStampedModel):
title = models.CharField(max_length=20, blank=False)
slug = AutoSlugField(populate_from='title', unique=True, always_update=True)
parent = models.ForeignKey('self', blank=True, null=True, related_name='children') # TODO: Add on_delete?
uuid = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
def __str__(self):
return '{0}'.format(self.title)
#class Meta: # TODO: Migrate live
#unique_together = ('title', 'parent')
class ArticleCategory(TimeStampedModel):
title = models.CharField(max_length=20, blank=False)
slug = AutoSlugField(populate_from='title', unique=True, always_update=True)
parent = models.ForeignKey('self', blank=True, null=True, related_name='children') # TODO: Add on_delete?
uuid = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
def __str__(self):
return '{0}'.format(self.title)
class Meta:
verbose_name_plural = 'article categories'
#unique_together = ('title', 'parent') # TODO: Migrate live
class Article(TimeStampedModel):
DEFAULT_FEATURED_IMAGE = settings.STATIC_URL + 'images/defaults/default-featured-image.png'
title = models.CharField(max_length=160, blank=False)
slug = AutoSlugField(populate_from='title', unique=True, always_update=True)
sport = models.ForeignKey(ArticleSport, on_delete=models.CASCADE, related_name='articleAsArticleSport')
category = models.ForeignKey(ArticleCategory, on_delete=models.CASCADE, related_name='articleAsArticleCategory')
featured_image = models.ImageField(upload_to=PathAndUniqueFilename('featured-images/'), blank=True)
featured_image_caption = models.CharField(max_length=100, blank=True)
views = models.IntegerField(default=0)
uuid = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
def get_absolute_url(self):
return reverse('main:article_specific', args=[self.slug]) # TODO: Remove if standalone pages are removed
def get_featured_image(self):
if self.featured_image:
return self.featured_image.url
else:
return self.DEFAULT_FEATURED_IMAGE
def get_comment_count(self):
return ArticleComment.objects.filter(article=self).count()
def __str__(self):
return '{0}'.format(self.title)
[...]
urls.py
[...]
class ArticleSportSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ArticleSport
fields = ('id', 'title', 'parent', 'created', 'modified')
class ArticleCategorySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ArticleCategory
fields = ('id', 'title', 'parent', 'created', 'modified')
class ArticleSerializer(serializers.HyperlinkedModelSerializer):
sport = ArticleSportSerializer(read_only=True)
sport_id = serializers.PrimaryKeyRelatedField(queryset=ArticleSport.objects.all(), write_only=True)
category = ArticleCategorySerializer(read_only=True)
category_id = serializers.PrimaryKeyRelatedField(queryset=ArticleCategory.objects.all(), write_only=True)
modified = serializers.HiddenField(default=timezone.now()) #TODO: Figure out how to implement this
class Meta:
model = Article
fields = ('id', 'title', 'sport', 'sport_id', 'category', 'category_id', 'featured_image', 'featured_image_caption', 'views', 'created', 'modified')
[...]
示例POST到API:
{
"title": "This is a test Title",
"sport_id": 1,
"category_id": 1,
"featured_image": null,
"featured_image_caption": "",
"views": null,
"modified": null
}
答案 0 :(得分:1)
您需要覆盖序列化程序的create
方法以适应您的POST
请求。这可能不是您正在寻找的,但您还没有包含您的样品申请,因此我们没有太大的帮助。
如果我有足够的声誉,这将是一个评论。
答案 1 :(得分:1)
所以我能够通过使用Carter_Smith
的一些建议回答这个问题 - 我不是百分之百确定为什么会这样做,但是我将这个create()
方法添加到我的{ {1}},它起作用了:
ArticleSerializer
我的猜测是def create(self, validated_data):
# Override default `.create()` method in order to properly add `sport` and `category` into the model
sport = validated_data.pop('sport_id')
category = validated_data.pop('category_id')
article = Article.objects.create(sport=sport, category=category, **validated_data)
return article
尝试根据名称解析PrimaryKeyRelatedField()
和sport_id
作为kwarg字段,而它们应该只是category_id
和sport
},所以覆盖category
允许你修复它,同时仍然允许.create()
和read_only
的{{1}}字段。希望这可以帮助其他有同样问题的人。