Django rest framework `` `TypeError: аргумент объекта типа после ** должен быть отображением, а не int``` - PullRequest
0 голосов
/ 05 октября 2019

У меня есть модель SMSMessages, которая будет содержать все отправленные смс. Я пытаюсь получить доступ через класс django-rest-framework ListCreateAPIView, но продолжаю выдавать ошибку, когда пытаюсь выполнить OPTIONзапрос на API через Insomnia, TypeError at /smsmessages/ type object argument after ** must be a mapping, not int.

Я искал на SO и обнаружил похожие ошибки, но они были вызваны b / c аргументом filter(), который к этому не относится. Я использую django 2.2.5, python 3.6.8, django-rest-framework 3.10.3 и mysqlclient 1.4.4.

это модель SMSMessages

from django.db import models
from django.contrib.auth.models import AbstractUser
from rest_framework.authtoken.models import Token

class SMSMessages(models.Model):
    sms_number_to = models.CharField(max_length=14)
    sms_content = models.CharField(max_length=160)
    sending_user = models.ForeignKey("SMSUser", on_delete=models.PROTECT, related_name="user_that_sent", limit_choices_to=1)
    sent_date = models.DateTimeField(auto_now=True)
    delivery_status = models.BooleanField(default=False)

    class Meta:
        verbose_name_plural = "SMSMessages"

    def __str__(self):
        return self.sending_user

и это файл urls.py:

from django.urls import path
from rest_framework.authtoken import views
from rest_framework.routers import DefaultRouter

from notification.apiviews import SMSendView, SMSMessagesView

app_name = "notification"

router = DefaultRouter()

urlpatterns = [
    path("smsmessages/", SMSMessagesView.as_view(), name="sms_messages"),
]

, поэтому я могу получить к нему доступ, отправив запрос OPTION на http://localhost:8000/smsmessages/. Этот класс SMSMessagesview, который используется для представления API:

from rest_framework import generics, status, viewsets, permissions
from rest_framework.response import Response
from rest_framework.views import APIView
from django.shortcuts import get_object_or_404, get_list_or_404
from django.contrib.auth import authenticate

from commons.models import SMSMessages
from commons.serializers import SMSMessagesSerializer


class SMSMessagesView(generics.ListCreateAPIView):

    """
    This class is responsible for generating, and returning, the view for all created objects of the SMSMessages model.
    It sub-classes the ListCreateAPIView class from the generics module.
    """
    queryset = SMSMessages.objects.all()
    if not queryset:
        Response(data={"{0} not found".format(queryset)}, status=404, content_type="application/json")

    serializer_class = SMSMessagesSerializer

, и это ошибка:

TypeError at /notification/smsmessages/
type object argument after ** must be a mapping, not int

Request Method: OPTIONS
Request URL: http://localhost:8055/notification/smsmessages/
Django Version: 2.2.5
Python Executable: /home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/bin/python
Python Version: 3.6.8
Python Path: ['/home/gadd/vscodeworkspace/sms.et/api.sms.et', '/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python36.zip', '/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6', '/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/lib-dynload', '/usr/lib/python3.6', '/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages']
Server time: Sat, 5 Oct 2019 16:19:59 +0000
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'rest_framework',
 'rest_framework_swagger',
 'rest_framework.authtoken',
 'commons',
 'notification']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']


Traceback:

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/django/views/decorators/csrf.py" in wrapped_view
  54.         return view_func(*args, **kwargs)

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/django/views/generic/base.py" in view
  71.             return self.dispatch(request, *args, **kwargs)

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/rest_framework/views.py" in dispatch
  505.             response = self.handle_exception(exc)

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/rest_framework/views.py" in handle_exception
  465.             self.raise_uncaught_exception(exc)

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/rest_framework/views.py" in raise_uncaught_exception
  476.         raise exc

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/rest_framework/views.py" in dispatch
  502.             response = handler(request, *args, **kwargs)

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/rest_framework/views.py" in options
  516.         data = self.metadata_class().determine_metadata(request, self)

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/rest_framework/metadata.py" in determine_metadata
  68.             actions = self.determine_actions(request, view)

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/rest_framework/metadata.py" in determine_actions
  94.                 actions[method] = self.get_serializer_info(serializer)

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/rest_framework/metadata.py" in get_serializer_info
  111.             for field_name, field in serializer.fields.items()

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/django/utils/functional.py" in __get__
  80.         res = instance.__dict__[self.name] = self.func(instance)

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/rest_framework/serializers.py" in fields
  360.         for key, value in self.get_fields().items():

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/rest_framework/serializers.py" in get_fields
  1047.                 source, info, model, depth

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/rest_framework/serializers.py" in build_field
  1182.                 return self.build_relational_field(field_name, relation_info)

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/rest_framework/serializers.py" in build_relational_field
  1257.         field_kwargs = get_relation_kwargs(field_name, relation_info)

File "/home/gadd/vscodeworkspace/sms.et/api.sms.et/api_env/lib/python3.6/site-packages/rest_framework/utils/field_mapping.py" in get_relation_kwargs
  255.             limit_choices_to = models.Q(**limit_choices_to)

Exception Type: TypeError at /notification/smsmessages/
Exception Value: type object argument after ** must be a mapping, not int

Это используемый класс сериализатора:

from rest_framework import serializers
from rest_framework.authtoken.models import Token

from commons.models import SMSUser, SMSPrice, Type, SMSMessages

class SMSMessagesSerializer(serializers.ModelSerializer):
    """
    A class for serializing the SMSMessages model's data. It sub-classes the
    ModelSerializer class from serializer's module.
    """

    class Meta:
        model = SMSMessages
        fields = '__all__'

Эта же ошибка возникает, когда я пытаюсь добавить объект SMSMessages в БД через интерфейс администратора. Кто-нибудь может помочь?

Ответы [ 2 ]

1 голос
/ 05 октября 2019

Это просто потому, что вы используете limit_choices_to с неверным форматом данных, который определен Django.

Либо словарь, объект Q, либо вызываемый объект, возвращающий словарь или объект Qможно использовать.

Так что это вызвало ошибку:

sending_user = models.ForeignKey("SMSUser", on_delete=models.PROTECT, related_name="user_that_sent", limit_choices_to=1 # HERE)

Так что вам может потребоваться ясно, что вы хотите сделать здесь, чтобы настроить правильный фильтр так, чтобы Django Adminбудет фильтровать данные, когда вы выбираете sending_user для вашей модели. Например, если вы хотите разрешить выбирать is_superuser только для sending_user на странице администратора, тогда вы можете пойти с этим:

limit_choices_to={
    'is_superuser': True,
}
1 голос
/ 05 октября 2019

Из документации для ForeignKey.limit_choices_to он ...

устанавливает ограничение на доступные варианты выбора для этого поля, когда это поле отображается с использованием ModelForm илиadmin (по умолчанию все объекты в наборе запросов доступны для выбора). Можно использовать словарь, объект Q или вызываемый объект, возвращающий словарь или объект Q.

... но в модели вы задаете целое число limit_choices_to=1, которое не является ни одним из этихвещи.

Возможно, вы намеревались использовать что-то вроде limit_choices_to={'id': 1}, чтобы ограничить выбор для пользователей SMS с этим идентификатором?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...