from_db_value() takes 4 positional arguments but 5 were given Django

Viewed 1314

i have simple django notification table with the following structure

+-------------------------------+--------------+------+-----+---------+----------------+
| Field                         | Type         | Null | Key | Default | Extra          |
+-------------------------------+--------------+------+-----+---------+----------------+
| id                            | int(11)      | NO   | PRI | NULL    | auto_increment |
| level                         | varchar(20)  | NO   |     | NULL    |                |
| unread                        | tinyint(1)   | NO   |     | NULL    |                |
| actor_object_id               | varchar(255) | NO   |     | NULL    |                |
| verb                          | varchar(255) | NO   |     | NULL    |                |
| description                   | longtext     | YES  |     | NULL    |                |
| target_object_id              | varchar(255) | YES  |     | NULL    |                |
| action_object_object_id       | varchar(255) | YES  |     | NULL    |                |
| timestamp                     | datetime(6)  | NO   |     | NULL    |                |
| public                        | tinyint(1)   | NO   |     | NULL    |                |
| action_object_content_type_id | int(11)      | YES  | MUL | NULL    |                |
| actor_content_type_id         | int(11)      | NO   | MUL | NULL    |                |
| recipient_id                  | int(11)      | NO   | MUL | NULL    |                |
| target_content_type_id        | int(11)      | YES  | MUL | NULL    |                |
| deleted                       | tinyint(1)   | NO   |     | NULL    |                |
| emailed                       | tinyint(1)   | NO   |     | NULL    |                |
| data                          | longtext     | YES  |     | NULL    |                |

And all what i want is to fetch the content so this is my view

@api_view(['GET'])
@login_required()
def getnotifications(request, page):

    try:
        if page == None:
            page = 1

        userID = request.user
        unreadnum = Notification.objects.filter(recipient=request.user,
                                                unread=True).count()
        notifs = Notification.objects.filter(recipient=userID, unread=True).distinct().order_by(
            '-timestamp')
        print("got ntifs")
        paginator = Paginator(notifs, 10)
        paginatednotifs = paginator.page(page)
        return Response(
            {"notifications": NotificationSerializer(paginatednotifs,many=True, context={"user": request.user}).data,
             "unread": unreadnum,"has_next":paginatednotifs.has_next()})


    except Exception as e:
        print("========")
        print(str(e))
        return Response(
            {"notifications": str(e)})

and thus view's serilizer is like this :

class NotificationSerializer(serializers.ModelSerializer):
    actor = serializers.SerializerMethodField()
    target = serializers.SerializerMethodField()

    class Meta:
        model = Notification
        fields = ("id","actor", "target","timestamp","verb")

    def get_actor(self,obj):
        user = Useraccount.objects.get(user__id=obj.actor_object_id)
        return UserAccountSerializer(user,many=False,context={"user":self.context["user"]}).data

    def get_target(self,obj):

        if obj.target_content_type.model == "action":

            action = ActstreamAction.objects.get(id=obj.target_object_id)
            return ActionNotificationSerializer(action,many=False).data
        return {"targetType":obj.target_content_type.model,"action":obj.action_object_content_type.model}

i tried to make many modifications in the serilizer and the view but always and always the same error

from_db_value() takes 4 positional arguments but 5 were given

i couldn't find this from_db_value() function i'm really having a hard time with this problem, and i know just the basics about Django

i'm using

  • django : 1.11.18
  • djangorestframework : 3.6.4
  • mysql : 5.7.25

A traceback for the error:

Traceback (most recent call last):
  File "<homedir>/project/webServer/app/myNotifications/views.py", line 66, in getnotifications
    {"notifications": NotificationSerializer(paginatednotifs,many=True, context={"user": request.user}).data,
  File "<homedir>/virtualenv/lib/python3.6/site-packages/rest_framework/serializers.py", line 739, in data
    ret = super(ListSerializer, self).data
  File "<homedir>/virtualenv/lib/python3.6/site-packages/rest_framework/serializers.py", line 263, in data
    self._data = self.to_representation(self.instance)
  File "<homedir>/virtualenv/lib/python3.6/site-packages/rest_framework/serializers.py", line 657, in to_representation
    self.child.to_representation(item) for item in iterable
  File "<homedir>/virtualenv/lib/python3.6/site-packages/rest_framework/serializers.py", line 657, in <listcomp>
    self.child.to_representation(item) for item in iterable
  File "/usr/lib/python3.6/_collections_abc.py", line 883, in __iter__
    v = self[i]
  File "<homedir>/virtualenv/lib/python3.6/site-packages/django/core/paginator.py", line 145, in __getitem__
    self.object_list = list(self.object_list)
  File "<homedir>/virtualenv/lib/python3.6/site-packages/django/db/models/query.py", line 250, in __iter__
    self._fetch_all()
  File "<homedir>/virtualenv/lib/python3.6/site-packages/django/db/models/query.py", line 1121, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "<homedir>/virtualenv/lib/python3.6/site-packages/django/db/models/query.py", line 62, in __iter__
    for row in compiler.results_iter(results):
  File "<homedir>/virtualenv/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 847, in results_iter
    row = self.apply_converters(row, converters)
  File "<homedir>/virtualenv/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 832, in apply_converters
    value = converter(value, expression, self.connection, self.query.context)
TypeError: from_db_value() takes 4 positional arguments but 5 were given
2 Answers

TL;DR:

Most likely, jsonfield package is not incompatible with Django==1.11.18


Details:

You are using Django in version 1.11.18, which requires 5 positional arguments for from_db_value method and do not support JSONFields.

You are also using django-notifications package, which internally uses jsonfield>=1.0.3 package. Since there is no max. version set, django-notifications uses the newest version of jsonfield package.

The newest versions of jsonfield (3.0.0 and higher) doesn't support Django below 2.2. One of the reasons is that it takes only 4 arguments instead of 5.

The highest version of jsonfield that supports Django 1.11 is jsonfield==2.1.1

Please check the version of installed jsonfield package (use grep only if you're on unix sytem):

pip freeze | grep jsonfield

If it's 3.0.0 or more, you may try to downgrade it to 2.1.1. Be aware that it may (or may not) cause other compatibility issues with other packages.

I got the same error:

  File "/home/django/lee3/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 833, in apply_converters
    value = converter(value, expression, self.connection, self.query.context)
TypeError: from_db_value() takes 4 positional arguments but 5 were given

The 'from_db_value' it was complaining about was in /picklefield/fields.py.

Changed line 184: def from_db_value(self, value, expression, connection): to: def from_db_value(self, value, expression, connection, context=None): Everything works fine now.

Related