DRF将额外变量传递给序列化程序

时间:2017-12-11 08:36:04

标签: python django django-rest-framework

我创建了一个创建CompletedTest对象的序列化程序。当我创建create方法时,我需要传递2个新变量:one - " test"包含测试ID,另一个" user_list"包含用户列表' ids,例如:[1,2,3,4]。我设法通过"测试"包含测试ID,但我无法通过" user_list"。

models.py

class CompletedTest(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    test = models.ForeignKey(Test)
    created = models.DateTimeField()
    completed_with = models.ManyToManyField('self', blank=True)

serializers.py

class CompletedTestSerializer(serializers.Serializer):
    test = serializers.CharField(source='test.id')
    user_list = serializers.ListField(child=serializers.IntegerField())

    def create(self, validated_data):
        test = validated_data['test']
        users = CustomUser.objects.filter(id__in=validated_data['user_list'])
        for user in users:
            try:
                CompletedTest.objects.get(test_id=test, user_id=user)
            except CompletedTest.DoesNotExist:
                completed_test = CompletedTest.objects.all()
                completed_test.create(user=user, test=test, created=timezone.now())
                completed_test.get(user=user).completed_with = completed_test.exclude(user=user)

    def update(self, instance, validated_data):
        pass

views.py

class CompletedTestView(ListAPIView):

    queryset = CompletedTest.objects.order_by('id')
    serializer_class = CompletedTestSerializer
    permission_classes = (IsAuthenticatedOrReadOnly, )

    def post(self, request):
        comp = CompletedTestSerializer(data=request.data)
        comp.is_valid(raise_exception=True)
        comp.save()
        return Response({'success': True})

在我的测试中,这就是我传递的内容:

{
    "test": 1,
    "user_list": [1,2,3]
}

使用当前的user_list变量,我收到此错误:

Traceback:  

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/django/views/decorators/csrf.py" in wrapped_view
  58.         return view_func(*args, **kwargs)

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/rest_framework/views.py" in dispatch
  489.             response = self.handle_exception(exc)

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/rest_framework/views.py" in handle_exception
  449.             self.raise_uncaught_exception(exc)

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/rest_framework/views.py" in dispatch
  486.             response = handler(request, *args, **kwargs)

File "/home/alex/Documents/Proiecte/Django/escaper/application/location/views.py" in post
  328.         comp.save()

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/rest_framework/serializers.py" in save
  215.             self.instance = self.create(validated_data)

File "/home/alex/Documents/Proiecte/Django/escaper/application/location/serializers.py" in create
  90.                 CompletedTest.objects.get(test_id=test, user_id=user)

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/django/db/models/manager.py" in manager_method
  85.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/django/db/models/query.py" in get
  371.         clone = self.filter(*args, **kwargs)

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/django/db/models/query.py" in filter
  784.         return self._filter_or_exclude(False, *args, **kwargs)

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/django/db/models/query.py" in _filter_or_exclude
  802.             clone.query.add_q(Q(*args, **kwargs))

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/django/db/models/sql/query.py" in add_q
  1250.         clause, _ = self._add_q(q_object, self.used_aliases)

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/django/db/models/sql/query.py" in _add_q
  1276.                     allow_joins=allow_joins, split_subq=split_subq,

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/django/db/models/sql/query.py" in build_filter
  1206.             condition = lookup_class(lhs, value)

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/django/db/models/lookups.py" in __init__
  24.         self.rhs = self.get_prep_lookup()

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/django/db/models/fields/related_lookups.py" in get_prep_lookup
  112.                 self.rhs = target_field.get_prep_value(self.rhs)

File "/home/alex/Documents/Proiecte/Django/escaper/venv/lib/python3.5/site-packages/django/db/models/fields/__init__.py" in get_prep_value
  966.         return int(value)

Exception Type: TypeError at /tests/completed/
Exception Value: int() argument must be a string, a bytes-like object or a number, not 'dict'

2 个答案:

答案 0 :(得分:0)

用户是queryset,因此用户中的用户是User实例。

try:
    CompletedTest.objects.get(test_id=test, user=user)
except CompletedTest.DoesNotExist:
    ....

或者您可以这样写:

    for user in validated_data['user_list']:
        try:
            CompletedTest.objects.get(test_id=test, user_id=user)
        except CompletedTest.DoesNotExist:

顺便说一下,ModelSerializer最简单。

class CompletedTestSerializer(ModelSerializer):

    class Meta:
        model = CompletedTest
        fields = '__all__'
邮递员应该是: enter image description here 不是: enter image description here

创建的

可以更改为created = models.DateTimeField(auto_now_add=True),然后默认情况下可以将Django设置为现在。

completed_room.get(user_id=user).completed_with = completed_room.exclude(user_id=user)

意味着添加CompletedRooms的completed_with设置为CompletedRooms,在创建后不属于此用途?如果是,signal是实现此目的的好方法:

完成/ signals.py

from datetime import datetime
from django.dispatch import receiver
from django.db.models.signals import post_save

from .models import CompletedTest


@receiver(post_save, sender=CompletedTest)
def set_completed_with(sender, instance=None, created=False, **kwargs):
    if created:
        not_belongs = CompletedTest.objects.exclude(user=instance.user)
        instance.completed_with.add(*not_belongs)
        instance.save()

完成/ app.py:

from django.apps import AppConfig


class CompletedConfig(AppConfig):
    name = 'Completed'
    verbose_name = 'Completed'

    def ready(self):
        import completed.signals

答案 1 :(得分:0)

你可以做这样的事情

class CompletedTestSerializer(serializers.Serializer):
   test = serializers.CharField(source='test.id')
   user_list = serializers.PrimaryKeyRelatedField(read_only=True, many=True)

现在您可以在序列化程序函数中获取user_list