如何解析“ AttributeError”类型的对象不可JSON序列化?

时间:2019-04-04 06:28:58

标签: django python-3.x django-rest-framework

我试图了解Django DRF,并尝试根据我的知识做一些复杂的事情。在我的应用程序中,我有邀请键,但是我只想允许用户在3天后(如果这是他们的第一个键)创建邀请键。如何创建序列化程序并以更好的方式查看它?

我正在使用Django 2.1.5和DRF 3.9.1

我已经尝试并在网络上阅读了其他问题,但是无法很好地实现自己想要的目标。我所想到的只是薄的视图,厚的串行器。

导致我的视​​图部分无法正常工作
Object of type 'AttributeError' is not JSON serializable

这个错误是我的观点,我知道很多。

我的模特:

class Invite_Key(models.Model):
    STATUS_CHOICES = (
        ('valid', 'valid'),
        ('not_valid', 'not_valid'),
        ('banned', 'banned'),
    )

    # Foreign keys
    user_submitter = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name='user_submitter'
    )

    user_receiver = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name='user_receiver'
    )

    uuid = models.UUIDField(default=generate_ulid_as_uuid, editable=False, unique=True, null=False)
    open_uuid = models.UUIDField(default=uuid1, editable=False, unique=True, null=False)
    reason = models.TextField(validators=[bad_words, bad_words_inline, test_test])

    # Now are choices
    status = models.CharField(max_length=14, choices=STATUS_CHOICES, default="valid")

    # Now below are boolean
    is_taken = models.BooleanField(default=False)
    is_locked = models.BooleanField(default=False)

    claim_date = models.DateField(editable=True, null=True, blank=True)
    expire_date = models.DateField(editable=True, null=True, blank=True)

    # Now these are the time stamps
    created_at = models.DateTimeField(auto_now_add=True, editable=False)
    updated_at = models.DateTimeField(auto_now=True, editable=False)

    def __str__(self):
        return str(self.uuid)

    # An instance of our object temp used for later
    def __init__(self, *args, **kwargs):
        super(Invite_Key, self).__init__(*args, **kwargs)
        self.temp = ''

    # We can set attributes onSave of our data to the table
    def save(self, *args, **kwargs):
        if not self.id:
            # for expire date
            self.expire_date = datetime.now() + timedelta(days=7)

        super(Invite_Key, self).save(*args, **kwargs)

我的序列化器:

class InviteKeyCreateAllSerializer(serializers.ModelSerializer):
    current_user = serializers.SerializerMethodField('_user')
    is_take = serializers.SerializerMethodField()
    class Meta:
        model = Invite_Key
        exclude = [
            'user_submitter',
            'user_receiver',
            'uuid',
            'status',
            'is_taken',
            'is_locked',
            'claim_date',
            'expire_date',
        ]

    # Use this method for the custom field
    def _user(self, obj):
        request = getattr(self.context, 'request', None)
        if request:
            return request.user

    def get_is_taken(self, obj):
        return False

    def get_status(self, obj):
        return 'valid'

    # end of custom fields

    def create(self, validated_data):
        key = Invite_Key(
            user_submitter=validated_data['request.user'],
        )
        key.set_user_submitter(validated_data['user_submitter'])
        key.save()
        return key

我的观点

class InviteKeyAllCreateView(generics.CreateAPIView):
    """
    POST invitekey/
    """
    serializer_class = InviteKeyCreateAllSerializer
    permission_classes = (IsAuthenticated,)

    def post(self, request, *args, **kwargs):
        user = self.request.user
        try:
            # get user count of keys
            cur_key_count = Invite_Key.objects.filter(user_submitter_id=user.id).order_by('-created_at').count()
            if cur_key_count > 0:
                # now we get the latest one
                check_key = Invite_Key.object.filter(user_submitter_id=user.id)[0]
                now = datetime.now()
                if now-timedelta(days=3) <= datetime.datetime.strptime(check_key['created_at'], "%Y-%m-%dT%H:%M:%S.%fZ"):
                    serialized_data = InviteKeyCreateAllSerializer(data=request.data)
                    serialized_data.is_valid(raise_exception=True)
                    serialized_data.save()
                else:
                    return Response(
                        data={
                            "message": "Sorry, you have recently created an Invite Key, try again some other time."
                        },
                        status=status.HTTP_400_BAD_REQUEST
                    )
        except Exception as e:
            return Response(
                data={
                    "message": "The Invite Key could not be created.",
                    "error": e
                },
                status=status.HTTP_400_BAD_REQUEST
            )

我希望通过创建一个http发布请求来创建一个邀请密钥,该视图将检查用户是否已创建密钥,然后获取最新密钥,然后在创建新密钥之前检查密钥是否存在3天,然后序列化程序将填充发布请求中缺少的数据。

实际结果是我得到AttributeError。另外,是否可以将我的大多数视图逻辑移至串行器?有人可以给我提示吗?我在“序列化器和视图的DRF文档”中寻找类似的内容,但找不到太多。

如果我缺少一些信息,请告诉我,谢谢...

编辑:添加了模型类 编辑: 我更改为str(e),现在的错误是:

type object 'Invite_Key' has no attribute 'object'

编辑:添加了错误跟踪功能

Django Version: 2.1.5
Python Version: 3.6.8
Installed Applications:
['django.contrib.admin.apps.SimpleAdminConfig',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'rest_framework',
 'corsheaders',
 'djmoney',
 'api',
 'main',
 'rssparser',
 'invite_system',
 'user_system']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'corsheaders.middleware.CorsMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  126.                 response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  124.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/usr/local/lib/python3.6/site-packages/django/views/decorators/csrf.py" in wrapped_view
  54.         return view_func(*args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py" in dispatch
  495.             response = self.handle_exception(exc)

File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py" in handle_exception
  455.             self.raise_uncaught_exception(exc)

File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py" in dispatch
  492.             response = handler(request, *args, **kwargs)

File "/opt/service/api/src/invite_system/views.py" in post
  229.             check_key = Invite_Key.object.filter(user_submitter_id=user.id).order_by('-created_at')[0]

Exception Type: AttributeError at /api/v1/invitekey
Exception Value: type object 'Invite_Key' has no attribute 'object'

编辑: 我正在调试中,并停留在下面的if语句的结构上。

错误:

'Invite_Key' object is not subscriptable

错误点:

            now = datetime.now()
            if now-timedelta(days=3) <= datetime.strptime(check_key['created_at'], "%Y-%m-%dT%H:%M:%S.%fZ"):
                serialized_data = InviteKeyCreateAllSerializer(data=request.data)

if语句无法评估要格式化的check_key ['created_at']。什么是正确的方法?我正在使用Postgres作为时间戳。

1 个答案:

答案 0 :(得分:1)

.......
except Exception as e:
return Response(
    data={
        "message": "The Invite Key could not be created.",
        "error": e    },
    status=status.HTTP_400_BAD_REQUEST)

在上面的代码段中,变量 e 是任何有效Pycthon Exception类的 对象 ,显然不是可序列化。


解决方案

以字符串格式表示对象

.......
except Exception as e:
return Response(
    data={
        "message": "The Invite Key could not be created.",
        "error": str(e)
    },
    status=status.HTTP_400_BAD_REQUEST)

UPDATE-1

应为 objects ,而不是object(缺少字符 s )< / p>

check_key = Invite_Key.objects.filter(user_submitter_id=user.id)[0]