umutbozkurt / django-rest-framework-mongoengine

Mongoengine support for Django Rest Framework
MIT License
616 stars 167 forks source link

Serializer for ListField(ReferenceField) fails when setting unique=True #261

Open sebitoelcheater opened 5 years ago

sebitoelcheater commented 5 years ago

I'm getting error when creating an Invoice from an InvoiceSerializer with a field that is a List of ReferenceFields. This code:

class Invoice(Document):
    requests = ListField(ReferenceField(Request), unique=True)

class InvoiceSerializer(DocumentSerializer):
    class Meta:
        model = Invoice
        fields = ('requests',)

Invoice.objects.create(requests=[request1])

will raise this error

Failure
Traceback (most recent call last):
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/mongoengine/base/fields.py", line 465, in to_mongo
    return ObjectId(six.text_type(value))
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/bson/objectid.py", line 110, in __init__
    self.__validate(oid)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/bson/objectid.py", line 206, in __validate
    _raise_invalid_id(oid)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/bson/objectid.py", line 52, in _raise_invalid_id
    " or a 24-character hex string" % oid)
bson.errors.InvalidId: "[DBRef('request', ObjectId('5bbd0f933e0a630c1a5f2ab6')), DBRef('request', ObjectId('5bbd0f923e0a630c1a5f2ab2'))]" is not a valid ObjectId, it must be a 12-byte input or a 24-character hex string

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/sebito/Developer/Proyectos/cargoo/cargoo/api/tests/api/test_invoice_api.py", line 544, in test_user_can_create_custom_invoices_from_non_invoiced_requests
    format='json'
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework/test.py", line 299, in post
    path, data=data, format=format, content_type=content_type, **extra)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework/test.py", line 212, in post
    return self.generic('POST', path, data, content_type, **extra)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework/test.py", line 237, in generic
    method, path, data, content_type, secure, **extra)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/django/test/client.py", line 404, in generic
    return self.request(**r)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework/test.py", line 288, in request
    return super(APIClient, self).request(**kwargs)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework/test.py", line 240, in request
    request = super(APIRequestFactory, self).request(**kwargs)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/django/test/client.py", line 485, in request
    raise exc_value
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/django/core/handlers/exception.py", line 35, in inner
    response = get_response(request)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/django/core/handlers/base.py", line 128, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework/viewsets.py", line 95, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework/views.py", line 494, in dispatch
    response = self.handle_exception(exc)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework/views.py", line 454, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework/views.py", line 491, in dispatch
    response = handler(request, *args, **kwargs)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework/mixins.py", line 20, in create
    serializer.is_valid(raise_exception=True)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework/serializers.py", line 236, in is_valid
    self._validated_data = self.run_validation(self.initial_data)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework/serializers.py", line 435, in run_validation
    value = self.to_internal_value(data)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework_mongoengine/serializers.py", line 201, in to_internal_value
    ret = super(DocumentSerializer, self).to_internal_value(data)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework/serializers.py", line 465, in to_internal_value
    validated_value = field.run_validation(primitive_value)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework/fields.py", line 524, in run_validation
    self.run_validators(value)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework/fields.py", line 538, in run_validators
    validator(value)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/rest_framework_mongoengine/validators.py", line 27, in __call__
    if queryset.first():
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/mongoengine/queryset/base.py", line 299, in first
    result = queryset[0]
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/mongoengine/queryset/base.py", line 197, in __getitem__
    queryset._cursor[key],
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/mongoengine/queryset/base.py", line 1547, in _cursor
    self._cursor_obj = self._collection.find(self._query,
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/mongoengine/queryset/base.py", line 1590, in _query
    self._mongo_query = self._query_obj.to_query(self._document)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/mongoengine/queryset/visitor.py", line 89, in to_query
    query = query.accept(QueryCompilerVisitor(document))
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/mongoengine/queryset/visitor.py", line 155, in accept
    return visitor.visit_query(self)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/mongoengine/queryset/visitor.py", line 78, in visit_query
    return transform.query(self.document, **query.query)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/mongoengine/queryset/transform.py", line 98, in query
    value = field.prepare_query_value(op, value)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/mongoengine/fields.py", line 804, in prepare_query_value
    return self.field.prepare_query_value(op, value)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/mongoengine/fields.py", line 1097, in prepare_query_value
    return self.to_mongo(value)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/mongoengine/fields.py", line 1075, in to_mongo
    id_ = id_field.to_mongo(id_)
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/mongoengine/base/fields.py", line 468, in to_mongo
    self.error(six.text_type(e))
  File "/Users/sebito/.virtualenvs/cargoo/lib/python3.6/site-packages/mongoengine/base/fields.py", line 166, in error
    raise ValidationError(message, errors=errors, field_name=field_name)
mongoengine.errors.ValidationError: "[DBRef('request', ObjectId('5bbd0f933e0a630c1a5f2ab6')), DBRef('request', ObjectId('5bbd0f923e0a630c1a5f2ab2'))]" is not a valid ObjectId, it must be a 12-byte input or a 24-character hex string

However, this code works if unique=True is removed.

BurkovBA commented 5 years ago

Thanks for reporting this bug.

It's an interesting problem, and I see multiple records of it in Mongoengine repos, see this github issue and this stackoverflow question.

If you could submit a unit-test with this problem, it would be ideal. Any help is more than welcome.

Sorry, I'm very pressed with multiple deadlines and can't dedicate much time to this project unfortunately. So, if you really want to get something done by me, please keep poking me, otherwise I'll forget about this issue in favour of more urgent matters.