Как разрешить Объект типа 'AttributeError' не сериализуемый JSON? - PullRequest
0 голосов
/ 04 апреля 2019

Я пытаюсь понять 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 post, и представление проверит, если пользователь создал ключи, затемполучите последний ключ, затем проверьте, что ключу было 3 дня, прежде чем создавать новый, и сериализатор заполнил бы недостающие данные из запроса на отправку.

Фактическим результатом было получение AttributeError.Кроме того, возможно ли перенести большую часть моей логики представления в сериализатор?Может кто-нибудь дать мне подсказку?Я искал что-то похожее в Документах DRF для сериализаторов и представлений и не могу найти много.

Если мне не хватает какой-либо информации, дайте мне знать, спасибо ...

РЕДАКТИРОВАТЬ:Добавлен модельный класс EDIT: я изменил на str (e), и моя ошибка теперь:

type object 'Invite_Key' has no attribute 'object'

EDIT: добавлен Error-Traceback

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'

EDIT: я отлаживаю изастрял на том, как структурировать это выражение 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 ['made_at'] быть отформатированным.Какой правильный способ сделать это?Я использую Postgres для отметок времени.

1 Ответ

1 голос
/ 04 апреля 2019
.......
except Exception as e:
return Response(
    data={
        "message": "The Invite Key could not be created.",
        <b>"error": e</b>    },
    status=status.HTTP_400_BAD_REQUEST)

В приведенном выше фрагменте переменная e объект любого допустимого класса исключений Pycthon и, очевидно, не сериализуемый.


Решение

представляет объект в строковом формате

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

UPDATE-1

Это должно быть objects вместо object (символ s отсутствует)

check_key = Invite_Key.<b>objects</b>.filter(user_submitter_id=user.id)[0]
...