how do i solve the following Django serializer error: TypeError: int() argument must be a string, a bytes-like object or a number, not 'Article'

Issue

Im quite new to django but i cant find the solution in the docs

My question:

I have a model with 2 OneToOne relations:


class Slotting(ICSBaseMixin):
    # database fields
    article = models.OneToOneField(
        "ics_stock.Article",
        on_delete=models.CASCADE,
        related_name="slotting",
        null=False
    )
    article_location = models.OneToOneField(
        "ics_stock.ArticleLocation",
        on_delete=models.CASCADE,
        null=False,
        related_name="slotting"
    )

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

    class Meta:
        db_table = "ICS_Stock_Slotting"
        verbose_name = "Slotting"
        verbose_name_plural = "Slottings" # noqa

I want to create and save a new instance through a serializer.

serializer:


class SlottingCreateUpdateSerializer(serializers.ModelSerializer):
    def update(self, instance, validated_data):
        article = validated_data.pop("article")
        instance.article_id = article

        article_location = validated_data.pop("article_location")
        instance.article_location_id = article_location

        instance.save()
        return instance

    def create(self, validated_data):
        article_id = validated_data.pop("article")
        article = get_object_or_404(
            Article,
            record_id=article_id
        )

        article_location_id = validated_data.pop("article_location")
        article_location = get_object_or_404(
            ArticleLocation,
            record_id=article_location_id
        )

        slotting = Slotting()
        slotting.article_location = article_location,
        slotting.article = article
        slotting.save()

        return slotting

Now when trying to serialize and save i get the following error:

raceback (most recent call last):
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\db\models\fields\__init__.py", line 1988, in get_prep_value
    return int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'Article'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\views\generic\base.py", line 84, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\rest_framework\views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
    raise exc
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\rest_framework\views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "C:\000 Projects\Applications\ICS_Django_core\ics_stock\api\views\slotting.py", line 44, in post
    instance = validated_data.save()
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\rest_framework\serializers.py", line 212, in save
    self.instance = self.create(validated_data)
  File "C:\000 Projects\Applications\ICS_Django_core\ics_stock\api\serializers\slotting.py", line 40, in create
    article = get_object_or_404(
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\shortcuts.py", line 85, in get_object_or_404
    return queryset.get(*args, **kwargs)
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\db\models\query.py", line 482, in get
    clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs)
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\db\models\query.py", line 1071, in filter
    return self._filter_or_exclude(False, args, kwargs)
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\db\models\query.py", line 1089, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, args, kwargs)
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\db\models\query.py", line 1096, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\db\models\sql\query.py", line 1502, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\db\models\sql\query.py", line 1532, in _add_q
    child_clause, needed_inner = self.build_filter(
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\db\models\sql\query.py", line 1448, in build_filter
    condition = self.build_lookup(lookups, col, value)
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\db\models\sql\query.py", line 1273, in build_lookup
    lookup = lookup_class(lhs, rhs)
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\db\models\lookups.py", line 27, in __init__
    self.rhs = self.get_prep_lookup()
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\db\models\lookups.py", line 85, in get_prep_lookup
    return self.lhs.output_field.get_prep_value(self.rhs)
  File "C:\000 Projects\Applications\ICS_Django_core\venv\lib\site-packages\django\db\models\fields\__init__.py", line 1990, in get_prep_value
    raise e.__class__(
TypeError: Field 'record_id' expected a number but got <Article: test article>.

Now im googling and looking for a whole day but i still dont know what im doing wrong.

What do i need to refactor to be able to fix the bug.

Solution

I created a serializer class to inherrit from that uses a dict input from the Meta class.

class RelatedModelSerializer(serializers.ModelSerializer):
    """
    serializes all relationship based models

    added field for Meta class

        -   relationships: dict[str:Model]

    Create and update method adds all fields from relationships with the primary key with from model described in relationships dict and saves and raises HTTP404 when object not found

    - Arjen Keller
    """

    class Meta:
        relationships = {}
        model = None

    def create(self, validated_data):
        for key in frozenset(validated_data):
            if self.Meta.relationships and key in self.Meta.relationships:
                validated_data[f"{key}_id"] = get_object_or_404(
                    self.Meta.relationships[key],
                    record_id=validated_data.pop(key).id
                ).id

        return self.Meta.model.objects.create(**validated_data)

    def update(self, instance, validated_data):
        for key in frozenset(validated_data):
            setattr(
                instance, f"{key}_id",
                validated_data.pop(key)
            ) if self.Meta.relationships and key in self.Meta.relationships and get_object_or_404(
                self.Meta.relationships[key],
                record_id=validated_data[key].id
            ).id else setattr(
                instance,
                f"{key}",
                validated_data.pop(key)
            )
        instance.save(**validated_data)
        return instance

i hope it helps somebody.

Answered By – ArjenKellerICS

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published