首页 > 解决方案 > DRF:无法通过管理界面发布或创建新对象

问题描述

当我尝试通过管理界面创建新对象时出现以下错误:

类型错误:% 的不支持的操作数类型:“配置不当”和“元组”

我有以下型号:

class CustomUser(AbstractUser):
    def __str__(self):
        return self.email

    class Meta:
        ordering = ('id',)
        verbose_name = 'user'

class Address(models.Model):
    """Address contains information about location. Address can be own by any
    kind of model."""
    content_type = models.ForeignKey(
        ContentType, on_delete=models.CASCADE, null=True
    )
    object_id = models.PositiveIntegerField(null=True)
    owner = GenericForeignKey("content_type", "object_id")

    CATEGORIES = Choices('billing', 'shipping')
    category = models.CharField(choices=CATEGORIES, max_length=16)
    address_1 = models.CharField("address line 1", max_length=128)
    address_2 = models.CharField("address line 2", max_length=128, blank=True)
    city = models.CharField(max_length=64)
    state_province = models.CharField('state/province', max_length=128)
    country = CountryField(blank_label='(select country)')
    zip_code = models.CharField(max_length=10)

    def __str__(self):
        return (
            f'{self.address_1}, {self.city}, {self.state_province}, '
            f'{self.country.name}, {self.zip_code}'
        )

    class Meta:
        ordering = ('id',)

class Company(Group):
    """An abstract base class that inherits Group."""
    addresses = GenericRelation(Address)
    owner = models.ForeignKey(User,
                              on_delete=models.CASCADE,
                              related_name='%(class)ss',
                              related_query_name='%(class)s')
    logo = CloudinaryField('image',
                           default='your_logo_here',
                           null=True,
                           blank=True)
    description = models.TextField('description', max_length=3000, blank=True)
    facebook_url = models.URLField('facebook url', blank=True)
    twitter_url = models.URLField('twitter url', blank=True)
    instagram_url = models.URLField('instagram url', blank=True)
    pinterest_url = models.URLField('pinterest url', blank=True)
    portfolio_url = models.URLField('portfolio url',  blank=True)
    phone_number = PhoneNumberField('phone number', blank=True)

    class Meta:
        abstract = True
        ordering = ('id',)


class Brand(Company):
    """A Brand can have multiple members."""

这些是我的序列化程序:

class CustomUserSerializer(HyperlinkedModelSerializer):
    brands = HyperlinkedRelatedField(
        many=True,
        read_only=True,
        view_name='brand-detail'
    )

    class Meta:
        model = CustomUser
        fields = (
            'url',
            'username',
            'email',
            'brands',
        )

class AddressSerializer(HyperlinkedModelSerializer):
    owner = GenericRelatedField({
        Brand: HyperlinkedRelatedField(
            queryset=Brand.objects.all(),
            view_name='brand-detail',
        )
    })

    class Meta:
        model = Address
        fields = (
            'url',
            'category',
            'address_1',
            'address_2',
            'city',
            'state_province',
            'country',
            'zip_code',
            'owner',
        )


class BrandSerializer(HyperlinkedModelSerializer):
    addresses = HyperlinkedRelatedField(many=True,
                                        read_only=True,
                                        view_name='address-detail')

    class Meta:
        model = Brand
        fields = (
            'url',
            'owner',
            'logo',
            'description',
            'facebook_url',
            'twitter_url',
            'instagram_url',
            'pinterest_url',
            'portfolio_url',
            'phone_number',
            'addresses',
        )

这就是我配置网址的方式:

router = DefaultRouter()
router.register('users', CustomUserViewSet)
router.register('addresses', AddressViewSet)
router.register('brands', BrandViewSet)

urlpatterns = [
    path('', include(router.urls)),
    path('auth/', include('rest_framework.urls', namespace='rest_framework')),
]

我可以访问http://localhost:8000/api/addresses/,我有以下表格:

在此处输入图像描述

问题是当我尝试 POST 创建一个新对象时。我收到了我描述的那个错误,这似乎是因为我没有正确传递所有者(实际上我不知道如何在这里传递一个对象,我应该使用 JSON 还是如何传递)。

在此处输入图像描述

问题:

  1. 我怎样才能解决这个错误,因为我也在尝试测试 POST 方法,并且当我意识到这不起作用时?

  2. 有没有办法GenericForeignKey在该表单中包含 a 的字段?

这是我的回溯:

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/generic_relations/serializers.py" in to_internal_value
  39.             serializer = self.get_deserializer_for_data(data)

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/generic_relations/serializers.py" in get_deserializer_for_data
  75.                 'Could not determine a valid serializer for value %r.' % value)

During handling of the above exception (Could not determine a valid serializer for value ''.), another exception occurred:

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/rest_framework/serializers.py" in to_internal_value
  488.                 validated_value = field.run_validation(primitive_value)

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/rest_framework/fields.py" in run_validation
  536.         value = self.to_internal_value(data)

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/generic_relations/serializers.py" in to_internal_value
  41.             raise ValidationError(e)

During handling of the above exception (["Could not determine a valid serializer for value ''."]), another exception occurred:

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/rest_framework/fields.py" in get_error_detail
  240.         error_dict = exc_info.error_dict

During handling of the above exception ('ValidationError' object has no attribute 'error_dict'), another exception occurred:

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
  126.                 response = self.process_exception_by_middleware(e, request)

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
  124.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/django/views/decorators/csrf.py" in wrapped_view
  54.         return view_func(*args, **kwargs)

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/rest_framework/viewsets.py" in view
  116.             return self.dispatch(request, *args, **kwargs)

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/rest_framework/views.py" in dispatch
  495.             response = self.handle_exception(exc)

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/rest_framework/views.py" in handle_exception
  455.             self.raise_uncaught_exception(exc)

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/rest_framework/views.py" in dispatch
  492.             response = handler(request, *args, **kwargs)

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/rest_framework/mixins.py" in create
  20.         serializer.is_valid(raise_exception=True)

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/rest_framework/serializers.py" in is_valid
  236.                 self._validated_data = self.run_validation(self.initial_data)

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/rest_framework/serializers.py" in run_validation
  434.         value = self.to_internal_value(data)

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/rest_framework/serializers.py" in to_internal_value
  494.                 errors[field.field_name] = get_error_detail(exc)

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/rest_framework/fields.py" in get_error_detail
  245.             for error in exc_info.error_list]

File "/Users/user/.local/share/virtualenvs/na-ERB0uoVd/lib/python3.7/site-packages/rest_framework/fields.py" in <listcomp>
  245.             for error in exc_info.error_list]

Exception Type: TypeError at /api/addresses/
Exception Value: unsupported operand type(s) for %: 'ImproperlyConfigured' and 'tuple'

标签: pythondjangodjango-rest-framework

解决方案


如果添加 read_only=True 如下所示:

owner = GenericRelatedField({
    Brand: HyperlinkedRelatedField(
        queryset=Brand.objects.all(),
        view_name='brand-detail',
    )
}, read_only=True)

错误将消失。但是,您需要在同一个序列化程序中编写自己的 create() 方法,并序列化所有者,以说明您希望如何保存所有者。


推荐阅读