django - Django中的ManyToMany字段序列化器
问题描述
我已经成功序列化了我的Blog模型,但是其中有两个ManyToMany关系,一个是Category,一个是SubCategory,这些都可以是一个或多个。该GET
方法按预期工作,问题仍然存在POST
。
型号:`
class Category(models.Model):
category_name = models.CharField(max_length=100)
sub_category = models.ManyToManyField(SubCategory, blank=True, )
added_on = models.DateTimeField(auto_now=True)
icon = models.CharField(default="pi-angle-double-right", max_length=30,
help_text="Icons can be picked from https://www.primefaces.org/primevue/showcase-v2/#/icons")
def __str__(self) -> str:
return self.category_name
@property
def total_blogs(self):
return Blog.objects.filter(category=self).count()
class Blog(models.Model):
"""
Blog table
"""
colors = [("r", "danger"), ("s", "success"),
("i", "info"), ]
title = models.CharField(max_length=250, help_text="Unique, catchy topic of the article", unique=True, null=True, blank=True)
body = CKEditor5Field(
'Add a body', help_text="Full body of the article, supports markup", config_name='default', null=True,
blank=True)
introductory_file = models.ImageField(
upload_to="blog_intros", null=True, blank=True, help_text="Cover image to introduce the rest of the blog",
validators=[validate_image_file_extension, validate_img_extension])
author = models.ForeignKey(Author, on_delete=models.CASCADE)
blog_color = models.CharField(
choices=colors, null=True, blank=True, max_length=10)
posted_on = models.DateTimeField(auto_now_add=True)
upvotes = models.ManyToManyField(
User, blank=True, related_name="upvoters")
downvotes = models.ManyToManyField(
User, blank=True, related_name="downvoters")
slug = models.SlugField(unique=True, blank=True, null=True)
category = models.ManyToManyField(Category, verbose_name="category")
sub_category = models.ManyToManyField(
SubCategory, blank=True, verbose_name="subCategory")
schedule_to = models.DateField(
null=True, help_text="If you are want to schedule the blog to a future date.", blank=True)
contributors = models.ManyToManyField(
Author, blank=True, related_name="coauthors")
def __str__(self):
return self.title
class SubCategory(models.Model):
sub_category_name = models.CharField(max_length=100)
added_on = models.DateTimeField(auto_now=True)
icon = models.CharField(default="pi-angle-double-right", max_length=30,
help_text="Icons can be picked from https://www.primefaces.org/primevue/showcase-v2/#/icons")
def __str__(self):
return self.sub_category_name
`
那么我的Blogserializer如下
`
class CategorySerializer(serializers.RelatedField):
def to_representation(self, value):
return {"category_name": value.category_name, "icon": value.icon}
def get_queryset(self):
queryset = Category.objects.all()
return queryset
def to_internal_value(self, data):
print(data)
category_name = data.get('category_name', None)
try:
category = Category.objects.get(category_name=category_name)
except Category.DoesNotExist:
raise serializers.ValidationError('Category does not exist')
return Category(category_name=category_name)
class Meta:
model = Category
class SubCategorySerializer(serializers.RelatedField):
def to_representation(self, value):
return {"sub_category_name": value.sub_category_name, "icon": value.icon}
def get_queryset(self):
queryset = SubCategory.objects.all()
return queryset
def to_internal_value(self, data):
sub_category_name = data.get('sub_category_name', None)
try:
sub_category = SubCategory.objects.get(sub_category_name=sub_category_name)
except SubCategory.DoesNotExist:
raise serializers.ValidationError('Sub category does not exist')
return SubCategory(sub_category_name=sub_category_name)
class Meta:
model = SubCategory
class BlogSerializer(serializers.ModelSerializer):
"""
Blog serializers
"""
category = CategorySerializer(many=True)
sub_category = SubCategorySerializer(many=True)
total_upvotes = serializers.ReadOnlyField()
total_downvotes = serializers.ReadOnlyField()
total_comments = serializers.ReadOnlyField()
poster_image = serializers.SerializerMethodField()
full_name = serializers.SerializerMethodField()
blog_color = DisplayNameWritableField()
class Meta:
model = Blog # the model we working on
fields = '__all__'
`
当我发出一个 get 请求时,我得到了一个好的和预期的响应,但是 createview 抛出了一个错误。
ListCreateAPIView `
class BlogListCreateView(generics.ListCreateAPIView):
"""
Get all articles or create one
"""
permission_classes = [IsAuthenticatedOrReadOnly, IsAuthor]
model = Blog
serializer_class = BlogSerializer
queryset = Blog.objects.all()
filter_backends = [filters.SearchFilter, DjangoFilterBackend]
search_fields = ["title", "author__user__username",
"category__category_name", "sub_category__sub_category_name"]
filterset_fields = ["title", "author__user__username",
"category__category_name", "sub_category__sub_category_name"]
def get_queryset(self):
now = datetime.datetime.now()
return Blog.objects.filter(Q(schedule_to__lte=now) | Q(schedule_to=None))
def perform_create(self, serializer):
if self.request.user.profile.is_author:
author_now = Author.objects.get(user=self.request.user)
serializer.save(author=author_now)
else:
return JsonResponse({"error": "You need to be an author to create an article"})
`
我的邮递员返回的错误
AttributeError at /api/blog/articles 'str' object has no attribute 'get'
很可能是在我的 Category Serializer 中生成的,to_internal_value()
在您看到正在打印数据的位置下!
我如何绕过它,以便创建一个博客,其中没有一个或多个类别,也没有一个或多个子类别。
也欢迎更好的方法。
解决方案
推荐阅读
- html - 页框已损坏
- c++ - 用二维字符数组的内容填充字符串的 C++ 向量:大小太大时失败
- c# - 如何重构当前使用字典的 C# 代码以减少冗余并提高类型安全性?
- python - 如何从python中的文本文件中获取函数参数?
- angular - Angular 服务将字符串从 App 组件共享到其他组件
- date - 使用 ARRAYFORMULA 插入新行时谷歌表格日期重新格式化
- python - 有什么方法可以在 Django 中为我的 sqlite3 数据库设置密码?
- asp.net-core - 如何从 asp.net core 3 Identity 中删除 UserName 字段
- html - 如何从网站获取 HTML 代码并将其转换为 VB 字符串?
- javascript - 可以在没有 ajaxSetup 的情况下预定义 ajax 参数吗?