【问题标题】:Django - expected type pk, received str [Many to many]Django - 预期类型 pk,收到 str [多对多]
【发布时间】:2021-06-28 08:01:10
【问题描述】:

我有一个 webapp,我们可以在其中创建以 django 作为后端的社区,但是当我尝试发送 POST 来创建社区时,我得到:

community_configuration: ["类型不正确。预期的 pk 值,收到的 str。"]

我的帖子:

{
title: knkn kn .k jbjnmn,
logo: [object File],
is_active: true,
description: test,
welcome_message: Welcome message,
org_id: 114,
community_configuration: About us,Community news,FAQs,Supporters,Resources,
}

这是我的序列化程序:

class MicroConfigurationSerializer(serializers.ModelSerializer):

    class Meta:
        model = MicroConfiguration
        fields = [
            'name',
        ]

    def to_representation(self, instance):
        return instance.name


class CommunityConfigurationSerializer(serializers.ModelSerializer):
    micro_configurations = MicroConfigurationSerializer(many=True, read_only=True)
    
    class Meta:
        model = CommunityConfiguration
        fields = '__all__'


class CommunitySerializer(serializers.ModelSerializer):
    logo = serializers.SerializerMethodField()
    organisation = serializers.SerializerMethodField()
    community_configuration = CommunityConfigurationSerializer()

    class Meta:
        model = Community
        fields = (
            ...
            etcetc
            ...
        )

这是我的模型:

class MicroConfiguration(core_models.BaseModel):
    name = models.CharField(max_length=32, unique=True)
    permissions = models.ManyToManyField(Permission)

    def __str__(self):
        return self.name


class CommunityConfiguration(core_models.BaseModel):
    name = models.CharField(max_length=32)
    micro_configurations = models.ManyToManyField(MicroConfiguration)
    permission_group = models.ForeignKey(
        Group,
        on_delete=models.SET_NULL,
        null=True
    )

    def __str__(self):
        return self.name


class Community(core_models.BaseModel):
    accounts = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        through='associates.AccountCommunity',
        through_fields=('community', 'account')
    )
    goals = models.ManyToManyField(Goal, through='associates.CommunityGoal')
    type = models.ManyToManyField(CommunityType, through='CommunityAttribute')
    communities = models.ManyToManyField(
        'self',
        through='associates.CommunityCommunity',
        symmetrical=False,
    )
    crossposts = models.ManyToManyField(
        Action,
        through='activities.CommunityCrosspost',
        through_fields=('community', 'action'),
        related_name='communities',
    )

    title = models.CharField(max_length=64)
    logo = models.ImageField(null=True, blank=True)
    intro_media = models.ForeignKey(
        'associates.MediaStore',
        null=True,
        on_delete=models.SET_NULL
    )
    website_url = models.CharField(max_length=256, blank=True)
    is_invite_only = models.BooleanField(default=False)
    description = models.TextField(blank=True)
    intro_message = models.TextField(blank=True)
    welcome_message = models.TextField(blank=True)
    signup_autojoin = models.BooleanField(default=False)

    community_configuration = models.ForeignKey(
        CommunityConfiguration,
        default=1,
        null=True,
        on_delete=models.SET_NULL,
        help_text='Do not edit directly, create a new custom config instead, \
            as it is reference by difference community.',
    )

    objects = models.Manager()
    associates = AssociationManager()

    @property
    def url(self):
        return reverse(
            'communities:detail',
            kwargs={
                'id': self.id,
            }
        )

    class Meta:
        verbose_name = 'Community'
        verbose_name_plural = 'Communities'

    def __str__(self):
        return self.title

这是我的观点:

class CommunityCreateAPIView(CreateAPIView):
    serializer_class = CommunityCreateSerializer

    def create(self, request, **kwargs):
        organisation_id = request.data.get('org_id')
        micro_configurations_qd = request.data.copy()
        micro_configurations = micro_configurations_qd.pop('community_configuration', False)

        if micro_configurations:
            micro_configurations = micro_configurations[0].split(',')

        user = request.user
        data = {}

        permitted = AccountOrganisation.objects.filter(
            account=user,
            organisation_id=organisation_id,
            is_active=True,
            association__permissions__codename='add_community',
        ).exists()

        if not permitted and not request.user.is_superuser:
            data['message'] = 'Action not allowed'

            return Response(
                data=data,
                status=status.HTTP_400_BAD_REQUEST,
            )

        response = super().create(request, **kwargs)

        if response.status_code == 400:
            data['message'] = 'Failed to update community'

            return Response(
                data=data,
                status=status.HTTP_400_BAD_REQUEST,
            )

        community_id = response.data.get('id')
        OrganisationCommunity.objects.create(
            community_id=community_id,
            organisation_id=organisation_id,
        )
        association = Group.objects.get(name='Community Admin')
        AccountCommunity.objects.create(
            community_id=community_id,
            account=user,
            association=association,
        )

        if micro_configurations:
            com_config_qs = CommunityConfiguration.objects.filter(
                micro_configurations__name__in=micro_configurations
            ).annotate(
                num_micro_config=Count('micro_configurations__name')
            ).filter(
                num_micro_config=len(micro_configurations)
            )

        community_configuration = None

        if micro_configurations:
            for com_config in com_config_qs:
                micro_config_count = com_config.micro_configurations.count()

                if micro_config_count == len(micro_configurations):
                    community_configuration = com_config

                    break

        if community_configuration:
            Community.objects.filter(
                pk=community_id
            ).update(
                community_configuration=community_configuration
            )
        elif micro_configurations:
            micro_qs = MicroConfiguration.objects.filter(
                name__in=micro_configurations
            )
            community_config = CommunityConfiguration.objects.create(
                name='Custom'
            )
            community_config.micro_configurations.set(micro_qs)
            community_config.save()
            Community.objects.filter(
                pk=community_id
            ).update(
                community_configuration=community_config
            )

        return response

我已经被这个问题困扰了好几个小时了,有什么帮助吗?

【问题讨论】:

  • 你能添加你的视图代码吗?
  • @ÇağatayBarın 我已经编辑过了
  • 我认为错误很明显。你的 pk 是字符串,但它必须是 int。 pk = int(self.kwargs['pk'])
  • 不幸的是,即使在更改后我仍然会遇到相同的错误。不过还是谢谢!
  • 创建记录时应该不需要指定pk。如果您使用 django 自动创建的标准 id 字段,这一切都会为您完成。

标签: python django django-rest-framework


【解决方案1】:

您的序列化程序需要 community_configuration 实例的 pk(或 id)。

基本上你已经设置好了,所以你需要先创建一个community_configuration 条目,然后获取新创建的条目的 id 并在创建社区时使用该 id。

如果您希望在创建社区时创建community_configuration 实例,那么可以选择覆盖序列化程序中的create 方法并提取community_configuration 数据,然后创建一个新条目对于那个模型并使用它,像这样

class CommunitySerializer(serializers.ModelSerializer):
    # .. put your serializer code here
    def create(self, validated_data):
        community_configuration= validated_data.pop('community_configuration')
        config_instance, created = CommunityConfiguration.objects.get_or_create(<community_configuration>) # modify this however you need to create the CommunityConfiguration instance
        community_instance = community.objects.create(**validated_data, community_configuration=config_instance)
        return community_instance

您可能需要修改代码以满足您的需求。
我没有阅读您的所有模型,不确定您将如何根据输入值创建嵌套模型,但您明白了。

【讨论】:

  • 我已经修好了,谢谢!我没有使用您的代码,但我使用了您所说的并查看了我的 API,结果发现错误在那里,问题就像您所说的一样。谢谢!
  • @JirroReo 很高兴为您提供帮助
猜你喜欢
  • 2015-08-26
  • 2021-09-06
  • 2020-09-09
  • 2021-05-17
  • 2018-10-05
  • 2021-10-11
  • 1970-01-01
  • 2021-11-07
  • 1970-01-01
相关资源
最近更新 更多