From af1e081a468bb594fb9268716934fb45778e49ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Fri, 9 Apr 2021 15:17:38 +0200
Subject: [PATCH] misc: remove django-jsonfield dependency (#52912)

---
 .../migrations/0010_auto_20190328_1111.py       |  4 ++--
 .../migrations/0015_auto_20201202_1424.py       |  6 +++---
 combo/apps/dataviz/models.py                    |  2 +-
 combo/apps/lingo/migrations/0001_initial.py     |  6 ++----
 combo/apps/lingo/migrations/0002_transaction.py |  4 ++--
 .../migrations/0021_transactionoperation.py     |  4 ++--
 .../lingo/migrations/0029_auto_20170528_1334.py |  4 ++--
 .../lingo/migrations/0034_auto_20190426_1159.py |  6 ++----
 .../0037_regie_transaction_options.py           |  4 ++--
 combo/apps/lingo/models.py                      | 12 ++++++------
 combo/apps/pwa/migrations/0001_initial.py       |  4 ++--
 .../pwa/migrations/0006_auto_20190628_1042.py   |  4 ++--
 combo/apps/pwa/models.py                        |  6 +++---
 .../migrations/0002_auto_20180720_1511.py       |  4 ++--
 combo/apps/search/models.py                     |  2 +-
 combo/apps/wcs/forms.py                         |  9 +++------
 .../migrations/0008_wcsformcell_cached_json.py  |  4 ++--
 .../0012_wcsformsofcategorycell_manual_order.py |  4 ++--
 .../0015_wcscurrentformscell_categories.py      |  4 ++--
 .../0018_wcscurrentdraftscell_categories.py     |  4 ++--
 combo/apps/wcs/migrations/0021_card.py          |  4 ++--
 .../migrations/0025_submission_categories.py    |  4 ++--
 combo/apps/wcs/models.py                        | 17 ++++++++++-------
 combo/data/migrations/0013_parameterscell.py    |  4 ++--
 combo/data/migrations/0024_configjsoncell.py    |  4 ++--
 .../data/migrations/0033_auto_20180401_1300.py  |  4 ++--
 .../data/migrations/0035_page_related_cells.py  |  4 ++--
 combo/data/models.py                            |  8 ++++----
 combo/utils/forms.py                            |  3 +++
 requirements.txt                                |  1 -
 setup.py                                        |  1 -
 tests/test_wcs.py                               |  3 ++-
 32 files changed, 76 insertions(+), 78 deletions(-)

diff --git a/combo/apps/dataviz/migrations/0010_auto_20190328_1111.py b/combo/apps/dataviz/migrations/0010_auto_20190328_1111.py
index 808cdbed..37440ef9 100644
--- a/combo/apps/dataviz/migrations/0010_auto_20190328_1111.py
+++ b/combo/apps/dataviz/migrations/0010_auto_20190328_1111.py
@@ -3,7 +3,7 @@
 from __future__ import unicode_literals
 
 import django.db.models.deletion
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
 
@@ -39,7 +39,7 @@ class Migration(migrations.Migration):
                 ('last_update_timestamp', models.DateTimeField(auto_now=True)),
                 ('data_reference', models.CharField(max_length=150, verbose_name='Data')),
                 ('title', models.CharField(blank=True, max_length=150, verbose_name='Title')),
-                ('cached_json', jsonfield.fields.JSONField(blank=True, default=dict)),
+                ('cached_json', JSONField(blank=True, default=dict)),
                 (
                     'chart_type',
                     models.CharField(
diff --git a/combo/apps/dataviz/migrations/0015_auto_20201202_1424.py b/combo/apps/dataviz/migrations/0015_auto_20201202_1424.py
index f578abda..cb9c0dd5 100644
--- a/combo/apps/dataviz/migrations/0015_auto_20201202_1424.py
+++ b/combo/apps/dataviz/migrations/0015_auto_20201202_1424.py
@@ -2,7 +2,7 @@
 # Generated by Django 1.11.29 on 2020-12-02 13:24
 from __future__ import unicode_literals
 
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations
 
 
@@ -16,11 +16,11 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='chartngcell',
             name='filter_params',
-            field=jsonfield.fields.JSONField(default=dict),
+            field=JSONField(default=dict),
         ),
         migrations.AddField(
             model_name='statistic',
             name='filters',
-            field=jsonfield.fields.JSONField(default=list),
+            field=JSONField(default=list),
         ),
     ]
diff --git a/combo/apps/dataviz/models.py b/combo/apps/dataviz/models.py
index d6f7322d..65ef1174 100644
--- a/combo/apps/dataviz/models.py
+++ b/combo/apps/dataviz/models.py
@@ -22,6 +22,7 @@ from datetime import date
 import pygal
 import pygal.util
 from django.conf import settings
+from django.contrib.postgres.fields import JSONField
 from django.db import models, transaction
 from django.urls import reverse
 from django.utils import timezone
@@ -29,7 +30,6 @@ from django.utils.encoding import force_text
 from django.utils.translation import gettext
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ungettext
-from jsonfield import JSONField
 from requests.exceptions import HTTPError, RequestException
 
 from combo.data.library import register_cell_class
diff --git a/combo/apps/lingo/migrations/0001_initial.py b/combo/apps/lingo/migrations/0001_initial.py
index 3daaf8b1..01f77ab9 100644
--- a/combo/apps/lingo/migrations/0001_initial.py
+++ b/combo/apps/lingo/migrations/0001_initial.py
@@ -1,8 +1,8 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-import jsonfield.fields
 from django.conf import settings
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
 
@@ -84,9 +84,7 @@ class Migration(migrations.Migration):
                 ),
                 (
                     'service_options',
-                    jsonfield.fields.JSONField(
-                        default=dict, verbose_name='Payment Service Options', blank=True
-                    ),
+                    JSONField(default=dict, verbose_name='Payment Service Options', blank=True),
                 ),
             ],
             options={
diff --git a/combo/apps/lingo/migrations/0002_transaction.py b/combo/apps/lingo/migrations/0002_transaction.py
index b770560c..25f74677 100644
--- a/combo/apps/lingo/migrations/0002_transaction.py
+++ b/combo/apps/lingo/migrations/0002_transaction.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
 
@@ -21,7 +21,7 @@ class Migration(migrations.Migration):
                 ),
                 ('start_date', models.DateTimeField(auto_now_add=True)),
                 ('end_date', models.DateTimeField(null=True)),
-                ('bank_data', jsonfield.fields.JSONField(default=dict, blank=True)),
+                ('bank_data', JSONField(default=dict, blank=True)),
                 ('order_id', models.CharField(max_length=200)),
                 ('items', models.ManyToManyField(to='lingo.BasketItem', blank=True)),
             ],
diff --git a/combo/apps/lingo/migrations/0021_transactionoperation.py b/combo/apps/lingo/migrations/0021_transactionoperation.py
index 0773fb21..d4447368 100644
--- a/combo/apps/lingo/migrations/0021_transactionoperation.py
+++ b/combo/apps/lingo/migrations/0021_transactionoperation.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
 
@@ -28,7 +28,7 @@ class Migration(migrations.Migration):
                 ),
                 ('amount', models.DecimalField(max_digits=8, decimal_places=2)),
                 ('creation_date', models.DateTimeField(auto_now_add=True)),
-                ('bank_result', jsonfield.fields.JSONField(default=dict, blank=True)),
+                ('bank_result', JSONField(default=dict, blank=True)),
                 ('transaction', models.ForeignKey(to='lingo.Transaction', on_delete=models.CASCADE)),
             ],
         ),
diff --git a/combo/apps/lingo/migrations/0029_auto_20170528_1334.py b/combo/apps/lingo/migrations/0029_auto_20170528_1334.py
index 68accc08..5b15cadf 100644
--- a/combo/apps/lingo/migrations/0029_auto_20170528_1334.py
+++ b/combo/apps/lingo/migrations/0029_auto_20170528_1334.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
 
@@ -24,7 +24,7 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='basketitem',
             name='request_data',
-            field=jsonfield.fields.JSONField(default=dict, blank=True),
+            field=JSONField(default=dict, blank=True),
         ),
         migrations.AddField(
             model_name='regie',
diff --git a/combo/apps/lingo/migrations/0034_auto_20190426_1159.py b/combo/apps/lingo/migrations/0034_auto_20190426_1159.py
index 356ac60f..ca69d5b2 100644
--- a/combo/apps/lingo/migrations/0034_auto_20190426_1159.py
+++ b/combo/apps/lingo/migrations/0034_auto_20190426_1159.py
@@ -3,7 +3,7 @@
 from __future__ import unicode_literals
 
 import django.db.models.deletion
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
 
@@ -50,9 +50,7 @@ class Migration(migrations.Migration):
                 ),
                 (
                     'service_options',
-                    jsonfield.fields.JSONField(
-                        blank=True, default=dict, verbose_name='Payment Service Options'
-                    ),
+                    JSONField(blank=True, default=dict, verbose_name='Payment Service Options'),
                 ),
             ],
         ),
diff --git a/combo/apps/lingo/migrations/0037_regie_transaction_options.py b/combo/apps/lingo/migrations/0037_regie_transaction_options.py
index c84db461..e5eb3522 100644
--- a/combo/apps/lingo/migrations/0037_regie_transaction_options.py
+++ b/combo/apps/lingo/migrations/0037_regie_transaction_options.py
@@ -2,7 +2,7 @@
 # Generated by Django 1.11.18 on 2019-05-14 12:02
 from __future__ import unicode_literals
 
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
 from combo.apps.lingo.models import SERVICES
@@ -18,7 +18,7 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='regie',
             name='transaction_options',
-            field=jsonfield.fields.JSONField(blank=True, default=dict, verbose_name='Transaction Options'),
+            field=JSONField(blank=True, default=dict, verbose_name='Transaction Options'),
         ),
         migrations.AlterField(
             model_name='paymentbackend',
diff --git a/combo/apps/lingo/models.py b/combo/apps/lingo/models.py
index ee065b5f..d173cc13 100644
--- a/combo/apps/lingo/models.py
+++ b/combo/apps/lingo/models.py
@@ -27,6 +27,7 @@ from dateutil import parser
 from django import template
 from django.conf import settings
 from django.contrib.auth.models import User
+from django.contrib.postgres.fields import JSONField
 from django.core import serializers
 from django.core.exceptions import ObjectDoesNotExist, PermissionDenied, ValidationError
 from django.core.mail import EmailMultiAlternatives
@@ -42,7 +43,6 @@ from django.utils.http import urlencode
 from django.utils.six.moves.urllib import parse as urlparse
 from django.utils.timezone import make_aware, utc
 from django.utils.translation import ugettext_lazy as _
-from jsonfield import JSONField
 from requests import RequestException
 
 from combo.apps.notifications.models import Notification
@@ -118,7 +118,7 @@ class PaymentBackend(models.Model):
         unique=True, verbose_name=_('Identifier'), help_text=_('The identifier is used in webservice calls.')
     )
     service = models.CharField(verbose_name=_('Payment Service'), max_length=64, choices=SERVICES)
-    service_options = JSONField(blank=True, verbose_name=_('Payment Service Options'))
+    service_options = JSONField(blank=True, default=dict, verbose_name=_('Payment Service Options'))
 
     objects = PaymentBackendManager()
 
@@ -190,7 +190,7 @@ class Regie(models.Model):
     payment_backend = models.ForeignKey(
         PaymentBackend, on_delete=models.CASCADE, verbose_name=_('Payment backend')
     )
-    transaction_options = JSONField(blank=True, verbose_name=_('Transaction Options'))
+    transaction_options = JSONField(blank=True, default=dict, verbose_name=_('Transaction Options'))
     can_pay_only_one_basket_item = models.BooleanField(
         default=True, verbose_name=_('Basket items must be paid individually')
     )
@@ -486,7 +486,7 @@ class BasketItem(models.Model):
     source_url = models.URLField(_('Source URL'), blank=True)
     details = models.TextField(verbose_name=_('Details'), blank=True)
     amount = models.DecimalField(verbose_name=_('Amount'), decimal_places=2, max_digits=8)
-    request_data = JSONField(blank=True)
+    request_data = JSONField(blank=True, default=dict)
     extra_fee = models.BooleanField(default=False)
     user_cancellable = models.BooleanField(default=True)
     creation_date = models.DateTimeField(auto_now_add=True)
@@ -611,7 +611,7 @@ class Transaction(models.Model):
     to_be_paid_remote_items = models.CharField(max_length=512, null=True)
     start_date = models.DateTimeField(auto_now_add=True)
     end_date = models.DateTimeField(null=True)
-    bank_data = JSONField(blank=True)
+    bank_data = JSONField(blank=True, default=dict)
     order_id = models.CharField(max_length=200)
     bank_transaction_id = models.CharField(max_length=200, null=True)
     bank_transaction_date = models.DateTimeField(blank=True, null=True)
@@ -703,7 +703,7 @@ class TransactionOperation(models.Model):
     kind = models.CharField(max_length=65, choices=OPERATIONS)
     amount = models.DecimalField(decimal_places=2, max_digits=8)
     creation_date = models.DateTimeField(auto_now_add=True)
-    bank_result = JSONField(blank=True)
+    bank_result = JSONField(blank=True, default=dict)
 
 
 @register_cell_class
diff --git a/combo/apps/pwa/migrations/0001_initial.py b/combo/apps/pwa/migrations/0001_initial.py
index 4e9c24a9..328f9af4 100644
--- a/combo/apps/pwa/migrations/0001_initial.py
+++ b/combo/apps/pwa/migrations/0001_initial.py
@@ -3,8 +3,8 @@
 from __future__ import unicode_literals
 
 import django.db.models.deletion
-import jsonfield.fields
 from django.conf import settings
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
 
@@ -24,7 +24,7 @@ class Migration(migrations.Migration):
                     'id',
                     models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
                 ),
-                ('subscription_info', jsonfield.fields.JSONField(default=dict)),
+                ('subscription_info', JSONField(default=dict)),
                 ('creation_timestamp', models.DateTimeField(auto_now_add=True)),
                 (
                     'user',
diff --git a/combo/apps/pwa/migrations/0006_auto_20190628_1042.py b/combo/apps/pwa/migrations/0006_auto_20190628_1042.py
index 6f08763a..d3aecb28 100644
--- a/combo/apps/pwa/migrations/0006_auto_20190628_1042.py
+++ b/combo/apps/pwa/migrations/0006_auto_20190628_1042.py
@@ -2,7 +2,7 @@
 # Generated by Django 1.11.12 on 2019-06-28 08:42
 from __future__ import unicode_literals
 
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
 
@@ -23,6 +23,6 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='pwasettings',
             name='push_notifications_infos',
-            field=jsonfield.fields.JSONField(blank=True, default=dict),
+            field=JSONField(blank=True, default=dict),
         ),
     ]
diff --git a/combo/apps/pwa/models.py b/combo/apps/pwa/models.py
index 94bf1809..fd945ec2 100644
--- a/combo/apps/pwa/models.py
+++ b/combo/apps/pwa/models.py
@@ -20,6 +20,7 @@ import base64
 import json
 
 from django.conf import settings
+from django.contrib.postgres.fields import JSONField
 from django.core import serializers
 from django.core.files.base import ContentFile
 from django.core.files.storage import default_storage
@@ -28,7 +29,6 @@ from django.utils import six
 from django.utils.encoding import force_bytes, force_text
 from django.utils.six import BytesIO
 from django.utils.translation import ugettext_lazy as _
-from jsonfield import JSONField
 from py_vapid import Vapid
 
 from combo import utils
@@ -56,7 +56,7 @@ class PwaSettings(models.Model):
     push_notifications = models.BooleanField(
         verbose_name=_('Enable subscription to push notifications'), default=False
     )
-    push_notifications_infos = JSONField(blank=True)
+    push_notifications_infos = JSONField(blank=True, default=dict)
     last_update_timestamp = models.DateTimeField(auto_now=True)
 
     def save(self, **kwargs):
@@ -193,5 +193,5 @@ class PwaNavigationEntry(models.Model):
 
 class PushSubscription(models.Model):
     user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
-    subscription_info = JSONField()
+    subscription_info = JSONField(default=dict)
     creation_timestamp = models.DateTimeField(auto_now_add=True)
diff --git a/combo/apps/search/migrations/0002_auto_20180720_1511.py b/combo/apps/search/migrations/0002_auto_20180720_1511.py
index 73bc1669..c9be4d99 100644
--- a/combo/apps/search/migrations/0002_auto_20180720_1511.py
+++ b/combo/apps/search/migrations/0002_auto_20180720_1511.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations
 
 
@@ -15,6 +15,6 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='searchcell',
             name='_search_services',
-            field=jsonfield.fields.JSONField(default=dict, verbose_name='Search Services', blank=True),
+            field=JSONField(default=dict, verbose_name='Search Services', blank=True),
         ),
     ]
diff --git a/combo/apps/search/models.py b/combo/apps/search/models.py
index 0f8bc347..3e689639 100644
--- a/combo/apps/search/models.py
+++ b/combo/apps/search/models.py
@@ -18,6 +18,7 @@ from django import template
 from django.contrib.auth.models import Group
 from django.contrib.contenttypes import fields
 from django.contrib.contenttypes.models import ContentType
+from django.contrib.postgres.fields import JSONField
 from django.core.exceptions import PermissionDenied
 from django.db import models
 from django.http import HttpResponse
@@ -26,7 +27,6 @@ from django.template import RequestContext, Template
 from django.utils.functional import cached_property
 from django.utils.http import quote
 from django.utils.translation import ugettext_lazy as _
-from jsonfield import JSONField
 
 from combo.data.library import register_cell_class
 from combo.data.models import CellBase, Page
diff --git a/combo/apps/wcs/forms.py b/combo/apps/wcs/forms.py
index f4acaa5e..3d6b677b 100644
--- a/combo/apps/wcs/forms.py
+++ b/combo/apps/wcs/forms.py
@@ -14,6 +14,8 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+import json
+
 from django import forms
 from django.utils.datastructures import MultiValueDict
 from django.utils.translation import ugettext_lazy as _
@@ -96,14 +98,9 @@ class WcsFormsOfCategoryCellForm(forms.ModelForm):
 
 class CategoriesSelectMultiple(forms.SelectMultiple):
     def format_value(self, value):
-        # this converts data dictionary to list, for django >=1.11
+        value = json.loads(value)
         return super(CategoriesSelectMultiple, self).format_value(value.get('data') or [])
 
-    def render_options(self, choices, value):
-        # this converts data dictionary to list, for django <1.11
-        value = value.get('data') or []
-        return super(CategoriesSelectMultiple, self).render_options(choices, value)
-
     def value_from_datadict(self, data, files, name):
         if isinstance(data, MultiValueDict):
             return {'data': data.getlist(name)}
diff --git a/combo/apps/wcs/migrations/0008_wcsformcell_cached_json.py b/combo/apps/wcs/migrations/0008_wcsformcell_cached_json.py
index 6e7353dd..dc97fcf7 100644
--- a/combo/apps/wcs/migrations/0008_wcsformcell_cached_json.py
+++ b/combo/apps/wcs/migrations/0008_wcsformcell_cached_json.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
 
@@ -15,7 +15,7 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='wcsformcell',
             name='cached_json',
-            field=jsonfield.fields.JSONField(default=dict, blank=True),
+            field=JSONField(default=dict, blank=True),
             preserve_default=True,
         ),
     ]
diff --git a/combo/apps/wcs/migrations/0012_wcsformsofcategorycell_manual_order.py b/combo/apps/wcs/migrations/0012_wcsformsofcategorycell_manual_order.py
index f8ef98e6..6c539535 100644
--- a/combo/apps/wcs/migrations/0012_wcsformsofcategorycell_manual_order.py
+++ b/combo/apps/wcs/migrations/0012_wcsformsofcategorycell_manual_order.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
 
@@ -15,7 +15,7 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='wcsformsofcategorycell',
             name='manual_order',
-            field=jsonfield.fields.JSONField(
+            field=JSONField(
                 default=dict,
                 help_text='Use drag and drop to reorder forms',
                 verbose_name='Manual Order',
diff --git a/combo/apps/wcs/migrations/0015_wcscurrentformscell_categories.py b/combo/apps/wcs/migrations/0015_wcscurrentformscell_categories.py
index 081c1e68..818631e8 100644
--- a/combo/apps/wcs/migrations/0015_wcscurrentformscell_categories.py
+++ b/combo/apps/wcs/migrations/0015_wcscurrentformscell_categories.py
@@ -2,7 +2,7 @@
 # Generated by Django 1.11.8 on 2018-01-21 12:50
 from __future__ import unicode_literals
 
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations
 
 
@@ -16,6 +16,6 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='wcscurrentformscell',
             name='categories',
-            field=jsonfield.fields.JSONField(blank=True, default=dict, verbose_name='Categories'),
+            field=JSONField(blank=True, default=dict, verbose_name='Categories'),
         ),
     ]
diff --git a/combo/apps/wcs/migrations/0018_wcscurrentdraftscell_categories.py b/combo/apps/wcs/migrations/0018_wcscurrentdraftscell_categories.py
index a6d9b949..9ebd2376 100644
--- a/combo/apps/wcs/migrations/0018_wcscurrentdraftscell_categories.py
+++ b/combo/apps/wcs/migrations/0018_wcscurrentdraftscell_categories.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations
 
 
@@ -15,6 +15,6 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='wcscurrentdraftscell',
             name='categories',
-            field=jsonfield.fields.JSONField(blank=True, default=dict, verbose_name='Categories'),
+            field=JSONField(blank=True, default=dict, verbose_name='Categories'),
         ),
     ]
diff --git a/combo/apps/wcs/migrations/0021_card.py b/combo/apps/wcs/migrations/0021_card.py
index a6ccabfa..73773be6 100644
--- a/combo/apps/wcs/migrations/0021_card.py
+++ b/combo/apps/wcs/migrations/0021_card.py
@@ -2,7 +2,7 @@
 from __future__ import unicode_literals
 
 import django.db.models.deletion
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
 import combo.apps.wcs.models
@@ -41,7 +41,7 @@ class Migration(migrations.Migration):
                 ('last_update_timestamp', models.DateTimeField(auto_now=True)),
                 ('carddef_reference', models.CharField(max_length=150, verbose_name='Card Model')),
                 ('cached_title', models.CharField(max_length=150, verbose_name='Title')),
-                ('cached_json', jsonfield.fields.JSONField(blank=True, default=dict)),
+                ('cached_json', JSONField(blank=True, default=dict)),
                 ('groups', models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Groups')),
                 ('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.Page')),
             ],
diff --git a/combo/apps/wcs/migrations/0025_submission_categories.py b/combo/apps/wcs/migrations/0025_submission_categories.py
index 29c5ed90..ebc46d4e 100644
--- a/combo/apps/wcs/migrations/0025_submission_categories.py
+++ b/combo/apps/wcs/migrations/0025_submission_categories.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations
 
 
@@ -15,6 +15,6 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='backofficesubmissioncell',
             name='categories',
-            field=jsonfield.fields.JSONField(blank=True, default=dict, verbose_name='Categories'),
+            field=JSONField(blank=True, default=dict, verbose_name='Categories'),
         ),
     ]
diff --git a/combo/apps/wcs/models.py b/combo/apps/wcs/models.py
index 67b312b8..52e36bea 100644
--- a/combo/apps/wcs/models.py
+++ b/combo/apps/wcs/models.py
@@ -20,12 +20,12 @@ import copy
 import logging
 
 from django.conf import settings
+from django.contrib.postgres.fields import JSONField
 from django.db import models
 from django.forms import Select
 from django.forms import models as model_forms
 from django.utils.text import slugify
 from django.utils.translation import ugettext_lazy as _
-from jsonfield import JSONField
 from requests.exceptions import RequestException
 
 from combo import utils
@@ -65,7 +65,7 @@ class WcsFormCell(CellBase):
 
     cached_title = models.CharField(_('Title'), max_length=150)
     cached_url = models.URLField(_('URL'))
-    cached_json = JSONField(blank=True)
+    cached_json = JSONField(blank=True, default=dict)
 
     template_name = 'combo/wcs/form.html'
     add_as_link_label = _('add a form link')
@@ -425,7 +425,7 @@ class CategoriesValidityMixin(object):
 class WcsCurrentFormsCell(WcsUserDataBaseCell, CategoriesValidityMixin):
     variable_name = 'user_forms'
 
-    categories = JSONField(_('Categories'), blank=True)
+    categories = JSONField(_('Categories'), blank=True, default=dict)
     current_forms = models.BooleanField(_('Current Forms'), default=True)
     done_forms = models.BooleanField(_('Done Forms'), default=False)
     include_drafts = models.BooleanField(_('Include drafts'), default=False)
@@ -523,7 +523,7 @@ class WcsCurrentDraftsCell(WcsUserDataBaseCell, CategoriesValidityMixin):
     variable_name = 'current_drafts'
     template_name = 'combo/wcs/current_drafts.html'
 
-    categories = JSONField(_('Categories'), blank=True)
+    categories = JSONField(_('Categories'), blank=True, default=dict)
 
     class Meta:
         verbose_name = _('Current Drafts')
@@ -585,7 +585,10 @@ class WcsFormsOfCategoryCell(WcsCommonCategoryCell, WcsBlurpMixin):
         ],
     )
     manual_order = JSONField(
-        blank=True, verbose_name=_('Manual Order'), help_text=_('Use drag and drop to reorder forms')
+        blank=True,
+        default=dict,
+        verbose_name=_('Manual Order'),
+        help_text=_('Use drag and drop to reorder forms'),
     )
     limit = models.PositiveSmallIntegerField(_('Limit'), null=True, blank=True)
 
@@ -852,7 +855,7 @@ class WcsCardInfosCell(CardMixin, CellBase):
     without_user = models.BooleanField(_('Ignore the logged-in user'), default=False)
 
     cached_title = models.CharField(_('Title'), max_length=150)
-    cached_json = JSONField(blank=True)
+    cached_json = JSONField(blank=True, default=dict)
 
     is_enabled = classmethod(is_wcs_enabled)
 
@@ -982,7 +985,7 @@ class BackofficeSubmissionCell(WcsDataBaseCell, CategoriesValidityMixin):
     cache_duration = 600
     user_dependant = True
 
-    categories = JSONField(_('Categories'), blank=True)
+    categories = JSONField(_('Categories'), blank=True, default=dict)
 
     class Meta:
         verbose_name = _('Backoffice Submission')
diff --git a/combo/data/migrations/0013_parameterscell.py b/combo/data/migrations/0013_parameterscell.py
index 130f5ed8..6832c68f 100644
--- a/combo/data/migrations/0013_parameterscell.py
+++ b/combo/data/migrations/0013_parameterscell.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
 
@@ -33,7 +33,7 @@ class Migration(migrations.Migration):
                 ('empty_label', models.CharField(default=b'---', max_length=64, verbose_name='Empty label')),
                 (
                     'parameters',
-                    jsonfield.fields.JSONField(
+                    JSONField(
                         default=dict,
                         help_text='Must be a JSON list, containing dictionaries with 3 keys: name, value and optionnally roles; name must be a string, value must be a dictionary and roles must a list of role names. Role names limit the visibility of the choice.',
                         verbose_name='Parameters',
diff --git a/combo/data/migrations/0024_configjsoncell.py b/combo/data/migrations/0024_configjsoncell.py
index 8e2e4d7c..330f6132 100644
--- a/combo/data/migrations/0024_configjsoncell.py
+++ b/combo/data/migrations/0024_configjsoncell.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
 
@@ -36,7 +36,7 @@ class Migration(migrations.Migration):
                 ),
                 ('last_update_timestamp', models.DateTimeField(auto_now=True)),
                 ('key', models.CharField(max_length=50)),
-                ('parameters', jsonfield.fields.JSONField(default=dict, blank=True)),
+                ('parameters', JSONField(default=dict, blank=True)),
                 ('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)),
                 ('page', models.ForeignKey(to='data.Page', on_delete=models.CASCADE)),
             ],
diff --git a/combo/data/migrations/0033_auto_20180401_1300.py b/combo/data/migrations/0033_auto_20180401_1300.py
index 99813c28..b74ce64d 100644
--- a/combo/data/migrations/0033_auto_20180401_1300.py
+++ b/combo/data/migrations/0033_auto_20180401_1300.py
@@ -3,8 +3,8 @@
 from __future__ import unicode_literals
 
 import django.db.models.deletion
-import jsonfield.fields
 from django.conf import settings
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
 
@@ -25,7 +25,7 @@ class Migration(migrations.Migration):
                 ),
                 ('timestamp', models.DateTimeField(auto_now_add=True)),
                 ('comment', models.TextField(blank=True, null=True)),
-                ('serialization', jsonfield.fields.JSONField(blank=True, default=dict)),
+                ('serialization', JSONField(blank=True, default=dict)),
                 (
                     'page',
                     models.ForeignKey(
diff --git a/combo/data/migrations/0035_page_related_cells.py b/combo/data/migrations/0035_page_related_cells.py
index 3b26ab9e..530ff26d 100644
--- a/combo/data/migrations/0035_page_related_cells.py
+++ b/combo/data/migrations/0035_page_related_cells.py
@@ -2,7 +2,7 @@
 # Generated by Django 1.11.12 on 2018-06-02 11:03
 from __future__ import unicode_literals
 
-import jsonfield.fields
+from django.contrib.postgres.fields import JSONField
 from django.db import migrations
 
 
@@ -16,6 +16,6 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='page',
             name='related_cells',
-            field=jsonfield.fields.JSONField(blank=True, default=dict),
+            field=JSONField(blank=True, default=dict),
         ),
     ]
diff --git a/combo/data/models.py b/combo/data/models.py
index 938e8977..936d1f7a 100644
--- a/combo/data/models.py
+++ b/combo/data/models.py
@@ -34,6 +34,7 @@ from django.contrib import messages
 from django.contrib.auth.models import Group
 from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
 from django.contrib.contenttypes.models import ContentType
+from django.contrib.postgres.fields import JSONField
 from django.core import serializers
 from django.core.cache import cache
 from django.core.exceptions import ObjectDoesNotExist, PermissionDenied, ValidationError
@@ -54,7 +55,6 @@ from django.utils.six.moves.urllib import parse as urlparse
 from django.utils.text import slugify
 from django.utils.timezone import now
 from django.utils.translation import ugettext_lazy as _
-from jsonfield import JSONField
 
 from combo import utils
 from combo.utils import NothingInCacheException
@@ -209,7 +209,7 @@ class Page(models.Model):
     )
 
     # keep a cached list of cell types that are used in the page.
-    related_cells = JSONField(blank=True)
+    related_cells = JSONField(blank=True, default=dict)
 
     _level = None
 
@@ -614,7 +614,7 @@ class PageSnapshot(models.Model):
     timestamp = models.DateTimeField(auto_now_add=True)
     user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
     comment = models.TextField(blank=True, null=True)
-    serialization = JSONField(blank=True)
+    serialization = JSONField(blank=True, default=dict)
 
     class Meta:
         ordering = ('-timestamp',)
@@ -1948,7 +1948,7 @@ class ConfigJsonCell(JsonCellBase):
     objects = ConfigJsonCellManager()
 
     key = models.CharField(max_length=50)
-    parameters = JSONField(blank=True)
+    parameters = JSONField(blank=True, default=dict)
 
     @classmethod
     def get_cell_types(cls):
diff --git a/combo/utils/forms.py b/combo/utils/forms.py
index d95b5d8a..ea4d4fb9 100644
--- a/combo/utils/forms.py
+++ b/combo/utils/forms.py
@@ -14,6 +14,8 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+import json
+
 from django import forms
 from django.utils.datastructures import MultiValueDict
 from django.utils.safestring import mark_safe
@@ -31,6 +33,7 @@ class MultiSortWidget(forms.SelectMultiple):
         # reorder choices to get them in the current value order
         self_choices = self.choices[:]
         choices_dict = dict(self_choices)
+        value = json.loads(value)
         if value:
             for option in reversed(value.get('data')):
                 if option not in choices_dict:
diff --git a/requirements.txt b/requirements.txt
index ed4d9ace..5310548c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,7 +2,6 @@ Django>=1.8, <1.12
 -e git+http://git.entrouvert.org/debian/django-ckeditor.git#egg=django_ckeditor
 gadjo
 feedparser
-django-jsonfield
 requests
 XStatic-Leaflet
 XStatic_OpenSans
diff --git a/setup.py b/setup.py
index 0726a4a3..4567331f 100644
--- a/setup.py
+++ b/setup.py
@@ -164,7 +164,6 @@ setup(
         'django-ckeditor<4.5.4',
         'gadjo>=0.53',
         'feedparser<6' if sys.version_info < (3, 9) else 'feedparser>=6',
-        'django-jsonfield',
         'requests',
         'XStatic-Leaflet',
         'XStatic-Leaflet-GestureHandling',
diff --git a/tests/test_wcs.py b/tests/test_wcs.py
index 95835eae..b9292c30 100644
--- a/tests/test_wcs.py
+++ b/tests/test_wcs.py
@@ -1065,7 +1065,8 @@ def test_manager_forms_of_category_cell(mock_send, app, admin_user):
     assert resp.status_int == 302
 
 
-def test_manager_current_forms(app, admin_user):
+@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
+def test_manager_current_forms(mock_send, app, admin_user):
     page = Page(title='One', slug='one', template_name='standard')
     page.save()
     app = login(app)
-- 
2.30.2

