gpt4 book ai didi

python - DRF-通过模型在 M2M 中创建新实例时出错

转载 作者:行者123 更新时间:2023-12-04 09:49:31 25 4
gpt4 key购买 nike

我有以下两个模型:

class User(models.Model):
user_id = models.CharField(
max_length=129,
unique=True,
)
user_article = models.ManyToManyField(
Article,
through="UserArticle",
)
occupation = models.CharField(max_length=100, default='null')

def __str__(self):
return self.user_id


class Article(models.Model):
uuid = models.UUIDField(editable=False, unique=True)
company = models.ForeignKey(
Company,
on_delete=models.PROTECT,
related_name='article_company_id',
)
articleType = models.ForeignKey(
ArticleType,
on_delete=models.PROTECT,
related_name='type',
)
date_inserted = models.DateField()
def __str__(self):
return self.uuid

以多对多关系建模,使用这个直通模型:
class UserArticle(models.Model):    
user = models.ForeignKey(User, to_field='user_id',
on_delete=models.PROTECT,)
article = models.ForeignKey(Article, to_field='uuid',
on_delete=models.PROTECT,)
posted_as = ArrayField(
models.CharField(max_length=100, blank=True),)
post_date = models.DateField()

class Meta:
db_table = "core_user_articles"

这是我的看法:
class BatchUserArticleList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = UserArticle.objects.all()
serializer_class = BatchUserArticleSerializer

def create(self, request, *args, **kwargs):
serializer = BatchUserArticleSerializer(data=request.data)
if not serializer.is_valid():
return response.Response({'Message': 'POST failed',
'Errors': serializer.errors},
status.HTTP_400_BAD_REQUEST)
self.perform_create(serializer) # equal to serializer.save()
return response.Response(serializer.data, status.HTTP_201_CREATED)

def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)

我面临的问题是当我想在 M2M 表中发布以下格式的数据时:
{
"posted_as": ["news"],
"post_date": "2020-05-26",
"user": "jhtpo9jkj4WVQc0000GXk0zkkhv7u",
"article": [
"11111111",
"22222222"
]
}

上面包含了许多文章的列表,所以我使用了 custom field在我的 serializer为了提取每个 article , 新建 UserArticle对象并插入它,使用 bulk_create ,进入我的 M2M 表。我认为当传入的数据不完全映射到数据库模型时,这是要走的路,但我可能错了。因此,如果您发现这种方法有问题,请发表评论。

这是序列化程序:
class BatchUserArticleSerializer(serializers.ModelSerializer):
article= ArticleField(source='*') #custom field

class Meta:
model = UserArticle
fields = ('posted_as', 'post_date', 'user', 'article')

def validate(self, data):
post_date = data['post_date']
if post_date != date.today():
raise serializers.ValidationError(
'post_date: post_date is not valid',
)
return data

def create(self, validated_data):
post_as = list(map(lambda item: item, validated_data['posted_as']))
post_date = validated_data['post_date']
user = validated_data['user']
list_of_articles = validated_data['article']
user_object = User.objects.get(user_id=user)
articles_objects = list(map(lambda res: Article.objects.get(uuid=res), list_of_articles))
user_articles_to_insert = list(map(
lambda article: UserArticle(
posted_as=posted_as,
post_date=post_date,
article=article,
user=user_object),
articles_objects))

try:
created_user_articles = UserArticles.objects.bulk_create(user_articles_to_insert)
for res in created_user_articles:
res.save()
return created_user_articles
except Exception as error:
raise Exception('Something went wrong: {0}'.format(error))


class ArticleField(serializers.Field):
def to_representation(self, value):
resource_repr = [value.article]
return resource_repr

def to_internal_value(self, data):
internal_repr = {
'article': data
}
return internal_repr

这似乎工作正常,因为我可以看到数据被正确插入 UserArticle table :
id | posted_as | post_date | user | article
1 | news | 2020-05-26 | jhtpo9jkj4WVQc0000GXk0zkkhv7u | 11111111
2 | news | 2020-05-26 | jhtpo9jkj4WVQc0000GXk0zkkhv7u | 22222222

当代码到达这一行时问题就来了:
response.Response(serializer.data, status.HTTP_201_CREATED)

更具体地说,我得到的错误是:
AttributeError: Got AttributeError when attempting to get a value for field `posted_as` on serializer `BatchUserArticleSerializer`.

The serializer field might be named incorrectly and not match any attribute or key on the `list` instance. Original exception text was: 'list' object has no attribute 'posted_as'.

原始异常错误在 instance = getattr(instance, attr) 处引发。 def get_attribute(instance, attrs) 的行 fields.py 中的函数DRF 来源。

我在这里想念什么?

最佳答案

首先,没有理由调用save每个批量创建的实例的方法。

第二个是异常(exception)原因。您调用create View 集方法。它调用序列化程序 create必须只返回一个实例(创建的对象)的方法。但是您的序列化程序返回列表 created_user_articles .列表真的没有字段posted_as .

因此,有两种方法可以修复它。

  • 第一个是覆盖 create方法来看,改变数据表示的方式。例如。对响应数据使用另一个序列化程序:
    def create(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    created_user_articles = self.perform_create(serializer)

    # use another way to get representation
    response_data = AnotherUserArticleSerializer(created_user_articles, many=True).data
    return Response(response_data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
    # add return to get created objects
    return serializer.save()
  • 第二个是在 create 中只返回一个实例您的序列化程序的方法。
  • 关于python - DRF-通过模型在 M2M 中创建新实例时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62029328/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com