diff --git a/newsbox/admin.py b/newsbox/admin.py
index 995fbd8be20d81c794ac508d5878faedb1060175..4502056a6eb7c56c5354305b1e720b1944e59bb2 100644
--- a/newsbox/admin.py
+++ b/newsbox/admin.py
@@ -7,7 +7,7 @@ import copy
 import itertools
 
 # Django imports
-from django.conf.urls import url
+from django.urls import re_path
 from django.contrib import admin
 from django.contrib import messages
 from django.contrib.admin.models import CHANGE
@@ -19,7 +19,7 @@ try:
     # Django imports
     from django.urls import reverse
 except ImportError:
-    from django.core.urlresolvers import reverse
+    from django.urls import reverse
 
 # Django imports
 from django.http import HttpResponseForbidden
@@ -27,8 +27,8 @@ from django.http import HttpResponseRedirect
 from django.shortcuts import get_object_or_404
 from django.utils import formats
 from django.utils.html import format_html
-from django.utils.translation import ugettext_lazy as _
-from django.utils.translation import ungettext_lazy
+from django.utils.translation import gettext_lazy as _
+from django.utils.translation import ngettext_lazy
 
 # Third Party
 import six
@@ -147,6 +147,10 @@ class NewsboxBaseAdmin(admin.ModelAdmin):
         pfields.update({'newsbox_slug': ('newsbox_title',)})
         return pfields
 
+    @admin.display(
+        description=_('published'),
+        ordering='newsbox_status',
+    )
     def changestatus_link(self, obj):
         if obj.newsbox_status == obj.STATUS_PUBLISHED:
             title = _('Unpublish this %s') % six.text_type(
@@ -166,15 +170,15 @@ class NewsboxBaseAdmin(admin.ModelAdmin):
             obj.get_newsbox_status_display()
         )
 
-    changestatus_link.admin_order_field = 'newsbox_status'
-    changestatus_link.short_description = _('published')
 
+    @admin.display(
+        description=_('pub. date')
+    )
     def newsbox_date_short(self, obj):
         return format_html('<span title="{}">{}</span>',
             formats.date_format(obj.newsbox_publication_start_date, 'DATETIME_FORMAT'),
             formats.date_format(obj.newsbox_publication_start_date, 'SHORT_DATE_FORMAT')
         )
-    newsbox_date_short.short_description = _('pub. date')
 
     def get_fieldsets(self, request, obj=None):
         """
@@ -183,20 +187,22 @@ class NewsboxBaseAdmin(admin.ModelAdmin):
         fieldsets = super(NewsboxBaseAdmin, self).get_fieldsets(request, obj)
         return copy.deepcopy(fieldsets)
 
+    @admin.display(
+        description=_('Title')
+    )
     def get_newsbox_title(self, obj):
         return obj.newsbox_title
-    get_newsbox_title.short_description = _('Title')
 
     def get_urls(self):
         url_prefix = '%s_%s_' % (self.model._meta.model_name, self.model._meta.app_label)
         return [
-            url(r'^([0-9]+)/change-status/$',
+            re_path(r'^([0-9]+)/change-status/$',
                 self.admin_site.admin_view(self.change_status),
                 name='%schange_status' % url_prefix,),
-            url(r'^([0-9]+)/publish/$',
+            re_path(r'^([0-9]+)/publish/$',
                 self.admin_site.admin_view(self.publish_one),
                 name='%spublish_one' % url_prefix,),
-            url(r'^([0-9]+)/unpublish/$',
+            re_path(r'^([0-9]+)/unpublish/$',
                 self.admin_site.admin_view(self.unpublish_one),
                 name='%sunpublish_one' % url_prefix,)
         ] + super(NewsboxBaseAdmin, self).get_urls()
@@ -256,6 +262,9 @@ class NewsboxBaseAdmin(admin.ModelAdmin):
         self.unpublish(request, self.model.objects.filter(pk=news_id))
         return HttpResponseRedirect(request.GET.get('next', '../../'))
 
+    @admin.action(
+        description=_('Publish selected %(verbose_name_plural)s')
+    )
     def publish(self, request, queryset):
         """
         Marks selected news items as published
@@ -290,13 +299,15 @@ class NewsboxBaseAdmin(admin.ModelAdmin):
                 'objtype': self.model._meta.verbose_name,
                 'objtitle': last_obj_ok, })
         else:
-            messages.success(request, ungettext_lazy(
+            messages.success(request, ngettext_lazy(
                 '%(nb)d %(objtype)s has been published',
                 '%(nb)d %(objtype)s have been published',
                 ok) % {'nb': ok,
                        'objtype': self.model._meta.verbose_name_plural,})
-    publish.short_description = _('Publish selected %(verbose_name_plural)s')
 
+    @admin.action(
+        description=_('Archive selected %(verbose_name_plural)s')
+    )
     def unpublish(self, request, queryset):
         """
         Marks selected news items as unpublished
@@ -331,12 +342,11 @@ class NewsboxBaseAdmin(admin.ModelAdmin):
                 'objtype': self.model._meta.verbose_name,
                 'objtitle': last_obj_ok, })
         else:
-            messages.success(request, ungettext_lazy(
+            messages.success(request, ngettext_lazy(
                 '%(nb)d %(objtype)s has been unpublished',
                 '%(nb)d %(objtype)s have been unpublished',
                 ok) % {'nb': ok,
                        'objtype': self.model._meta.verbose_name_plural})
-    unpublish.short_description = _('Archive selected %(verbose_name_plural)s')
 
     def ensure_slug_uniq_queryset(self, request, obj, slug):
         y, m, d = (obj.newsbox_publication_start_date.year,
@@ -373,6 +383,9 @@ class NewsboxAdmin(NewsboxBaseAdmin):
 
 class NewsboxExpiredAdmin(NewsboxBaseAdmin):
 
+    @admin.display(
+        description=_('publication')
+    )
     def newsbox_publication_dates_short(self, obj):
         output = []
         title = []
@@ -397,7 +410,6 @@ class NewsboxExpiredAdmin(NewsboxBaseAdmin):
         output = ('<span> %s </span>' % _('to')).join(output)
         return format_html('<abbr class="newsbox_pub_dates %s" title="%s">%s</abbr>' % (
             css_class, title, output))
-    newsbox_publication_dates_short.short_description = _('publication')
 
     def get_fieldsets(self, request, obj=None):
         fieldsets = super(NewsboxExpiredAdmin, self).get_fieldsets(request, obj)
diff --git a/newsbox/models.py b/newsbox/models.py
index 2b6d00e9c32cd2ec06c17aaab2198a06bf8d5daf..a758a07da1b668a19e204a9b301d94945a370f42 100644
--- a/newsbox/models.py
+++ b/newsbox/models.py
@@ -14,14 +14,14 @@ try:
     # Django imports
     from django.urls import reverse
 except ImportError:
-    from django.core.urlresolvers import reverse
+    from django.urls import reverse
 
 # Django imports
 from django.db import models
 from django.utils.functional import lazy
 from django.utils.safestring import mark_safe
 from django.utils.timezone import now
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
 
 # Third Party
 import six
diff --git a/newsbox/urls.py b/newsbox/urls.py
index 5e3bac93492d87876e5baad2cf54f06d692cd26c..3aef07f71ec1561f20ccc7b2db52c2c0511dcd7d 100644
--- a/newsbox/urls.py
+++ b/newsbox/urls.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-from django.conf.urls import include, url
+from django.urls import include, re_path
 
 from .models import newsbox_models
 from .views import NewsboxArchiveView, NewsboxYearArchiveView, \
@@ -86,23 +86,23 @@ def get_urls(
 
         if archive_view:
             view = _get_view(archive_view, model, **archive_view_kwargs)
-            model_urls.append(url(root_url, view, name='%slist' % name_prefix))
+            model_urls.append(re_path(root_url, view, name='%slist' % name_prefix))
 
         if year_archive_view:
             view = _get_view(year_archive_view, model, **year_archive_view_kwargs)
-            model_urls.append(url(year_url, view, name='%slist' % name_prefix))
+            model_urls.append(re_path(year_url, view, name='%slist' % name_prefix))
 
         if month_archive_view:
             view = _get_view(month_archive_view, model, **month_archive_view_kwargs)
-            model_urls.append(url(month_url, view, name='%slist' % name_prefix))
+            model_urls.append(re_path(month_url, view, name='%slist' % name_prefix))
 
         if day_archive_view:
             view = _get_view(day_archive_view, model, **day_archive_view_kwargs)
-            model_urls.append(url(day_url, view, name='%slist' % name_prefix))
+            model_urls.append(re_path(day_url, view, name='%slist' % name_prefix))
 
         if detail_view:
             view = _get_view(detail_view, model, **detail_view_kwargs)
-            model_urls.append(url(slug_url, view, name='%sdetail' % name_prefix))
+            model_urls.append(re_path(slug_url, view, name='%sdetail' % name_prefix))
         if model_urls:
-            urls.append(url(r'^%s' % prefix, include(model_urls, namespace=namespace)))
+            urls.append(re_path(r'^%s' % prefix, include(model_urls, namespace=namespace)))
     return urls
diff --git a/newsbox_cms/admin.py b/newsbox_cms/admin.py
index 19b61b1b7280097134075204e1f2bd34455feacf..6ca594f0a9193cf026bb8fe9437ba2ee767db434 100644
--- a/newsbox_cms/admin.py
+++ b/newsbox_cms/admin.py
@@ -9,12 +9,12 @@ try:
     # Django imports
     from django.urls import reverse
 except ImportError:
-    from django.core.urlresolvers import reverse
+    from django.urls import reverse
 
 # Django imports
 from django.utils import formats
 from django.utils.html import format_html
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
 
 # Third Party
 import six
@@ -71,6 +71,10 @@ def CustomModelCMSAdminFactory(
                 title = six.text_type(obj)
             return title
 
+        @admin.display(
+            description=edit_link_short_description,
+            ordering=edit_link_admin_order_field,
+        )
         def edit_link(self, obj):
             """
             build the change list edit link
@@ -96,8 +100,6 @@ def CustomModelCMSAdminFactory(
                 title=self.edit_link_title(obj, object_title),
                 edit_label=_("edit object's parameters"))
 
-        edit_link.short_description = edit_link_short_description
-        edit_link.admin_order_field = edit_link_admin_order_field
 
         def get_list_display(self, request):
             list_display = super(CustomModelCMSAdmin, self).get_list_display(request)
diff --git a/newsbox_cms/cms_plugins.py b/newsbox_cms/cms_plugins.py
index 46c609a98319f37a2ad71a0c0d3ce7f5799edd23..81ec9160be4775c0ea0279fae4950dc55ae8cec1 100644
--- a/newsbox_cms/cms_plugins.py
+++ b/newsbox_cms/cms_plugins.py
@@ -3,7 +3,7 @@ from __future__ import unicode_literals
 
 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
 from django.template.loader import select_template
-from django.utils.translation import ugettext as _
+from django.utils.translation import gettext as _
 from cms.plugin_base import CMSPluginBase
 from newsbox.models import NewsboxBase
 from newsbox_cms import compat
diff --git a/newsbox_cms/models.py b/newsbox_cms/models.py
index ff71ff29d5c24209a6a2e5536f51461c3439d725..8459fb878d66ec4c9293b4f99ca5bacdb4e3d4cf 100644
--- a/newsbox_cms/models.py
+++ b/newsbox_cms/models.py
@@ -4,8 +4,8 @@ from __future__ import unicode_literals
 
 # Django imports
 from django.db import models
-from django.utils.translation import ugettext_lazy as _
-from django.utils.translation import ungettext_lazy
+from django.utils.translation import gettext_lazy as _
+from django.utils.translation import ngettext_lazy
 
 # Third Party
 from cms.models.fields import PageField
@@ -49,7 +49,7 @@ class NewsboxPluginBase(CMSPlugin):
 
     def __str__(self):
         if self.numitems > 0:
-            return six.text_type(ungettext_lazy(
+            return six.text_type(ngettext_lazy(
                 'Display of a news',
                 'Display of %(nb)d news',
                 self.numitems
diff --git a/newsbox_i18n/admin.py b/newsbox_i18n/admin.py
index 569b735266dd0007626e59c2b83df19c25f168f2..87c12df38d85bdfcf4815c7a2215c1254b044d35 100644
--- a/newsbox_i18n/admin.py
+++ b/newsbox_i18n/admin.py
@@ -5,7 +5,7 @@ import copy
 from django.conf import settings
 from parler.admin import TranslatableAdmin
 from django.utils.html import format_html
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
 
 
 def edit_translation_links(obj):
diff --git a/newsbox_i18n/models.py b/newsbox_i18n/models.py
index b9718e47388d8262c0ca1c3da364b52a6a2b33e2..58d305a00d0a843af20ddaf2b2b18777617d0b7f 100644
--- a/newsbox_i18n/models.py
+++ b/newsbox_i18n/models.py
@@ -6,10 +6,10 @@ try:
     # Django imports
     from django.urls import reverse
 except ImportError:
-    from django.core.urlresolvers import reverse
+    from django.urls import reverse
 # Django imports
 from django.utils.translation import get_language
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
 
 # Third Party
 from newsbox.models import NewsboxManager
diff --git a/tests/myapp/admin.py b/tests/myapp/admin.py
index 7af6cbf25d78968d49645d277323b89b063c6e25..759f36ed79fd23b0170df99839aaf5135a9cc49f 100644
--- a/tests/myapp/admin.py
+++ b/tests/myapp/admin.py
@@ -6,30 +6,31 @@ from newsbox.admin import NewsboxAdmin, NewsboxSEOAdmin, NewsboxExpiredAdmin
 from .models import News, NewsSEO, NewsExpired, NewsComplete, NewsExtended
 
 
+@admin.register(News)
 class NewsAdmin(NewsboxAdmin):
     pass
 
-admin.site.register(News, NewsAdmin)
 
 
+@admin.register(NewsSEO)
 class NewsSEOAdmin(NewsboxSEOAdmin):
     pass
 
-admin.site.register(NewsSEO, NewsSEOAdmin)
 
 
+@admin.register(NewsExpired)
 class NewsExpiredAdmin(NewsboxExpiredAdmin):
     pass
 
-admin.site.register(NewsExpired, NewsExpiredAdmin)
 
 
+@admin.register(NewsComplete)
 class NewsCompleteAdmin(NewsboxSEOAdmin, NewsboxExpiredAdmin):
     pass
 
-admin.site.register(NewsComplete, NewsCompleteAdmin)
 
 
+@admin.register(NewsExtended)
 class NewsExtendedAdmin(NewsboxSEOAdmin, NewsboxExpiredAdmin):
     def get_fieldsets(self, request, obj=None):
         fieldsets = super(NewsExtendedAdmin, self).get_fieldsets(request, obj)
@@ -43,4 +44,3 @@ class NewsExtendedAdmin(NewsboxSEOAdmin, NewsboxExpiredAdmin):
         list_display.append('seo_field')
         return list_display
 
-admin.site.register(NewsExtended, NewsExtendedAdmin)
diff --git a/tests/myapp/urls.py b/tests/myapp/urls.py
index 7f4fa8d6b94d6b323a09b1331fbf60f7962f857f..00f6b8927a3d3e3acfbee3e378dc4099d693a112 100644
--- a/tests/myapp/urls.py
+++ b/tests/myapp/urls.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-from django.conf.urls import url, include
+from django.urls import include, path
 from django.contrib import admin
 from newsbox.urls import get_urls
 
@@ -12,4 +12,4 @@ news_urls = get_urls(archive_view={'paginate_by': 1},
                      day_archive_view={'paginate_by': 1})
 
 admin.autodiscover()
-urlpatterns = [url(r'^admin/', include(admin.site.urls)), ] + news_urls
+urlpatterns = [path('admin/', include(admin.site.urls)), ] + news_urls
diff --git a/tests/myapp_all/admin.py b/tests/myapp_all/admin.py
index 7d30b6050dc0e3ee5d83781abd00563122a37b8c..80b328249cd15a2fb83c9c83282d828d3860a549 100644
--- a/tests/myapp_all/admin.py
+++ b/tests/myapp_all/admin.py
@@ -10,18 +10,19 @@ from newsbox_i18n.admin import NewsboxI18NAdmin
 from .models import News, NewsComplete, NewsExtended
 
 
+@admin.register(News)
 class NewsAdmin(NewsboxI18NAdmin, NewsboxCMSAdmin):
     pass
 
-admin.site.register(News, NewsAdmin)
 
 
+@admin.register(NewsComplete)
 class NewsCompleteAdmin(NewsboxI18NAdmin, NewsboxCMSAdmin, NewsboxSEOAdmin, NewsboxExpiredAdmin):
     pass
 
-admin.site.register(NewsComplete, NewsCompleteAdmin)
 
 
+@admin.register(NewsExtended)
 class NewsExtendedAdmin(NewsboxI18NAdmin, NewsboxCMSAdmin, NewsboxSEOAdmin, NewsboxExpiredAdmin):
     def get_fieldsets(self, request, obj=None):
         fieldsets = super(NewsExtendedAdmin, self).get_fieldsets(request, obj)
@@ -35,4 +36,3 @@ class NewsExtendedAdmin(NewsboxI18NAdmin, NewsboxCMSAdmin, NewsboxSEOAdmin, News
         list_display.append('seo_field')
         return list_display
 
-admin.site.register(NewsExtended, NewsExtendedAdmin)
diff --git a/tests/myapp_all/migrations/0001_initial.py b/tests/myapp_all/migrations/0001_initial.py
index cddfa827af0c1ecc315af4c27aaa64e98720c5dd..8d0c21a380f8e5e77eaa5bb462e2c8b284eb5e8f 100644
--- a/tests/myapp_all/migrations/0001_initial.py
+++ b/tests/myapp_all/migrations/0001_initial.py
@@ -64,7 +64,7 @@ class Migration(migrations.Migration):
                 ('newsbox_title', models.CharField(max_length=255, verbose_name='title')),
                 ('newsbox_slug', models.SlugField(help_text='The part of the title that is used in the URL', verbose_name='slug')),
                 ('newsbox_canonical_url', models.URLField(help_text='Ce champ vous permet d\'indiquer aux moteurs de recherche l\'URL "officielle" d\'un contenu dupliqu\xe9. Si votre contenu provient d\'une autre page (de votre site ou non), alors vous devriez indiquer l\'URL de ce contenu "source" afin d\'\xe9viter que les moteurs de recherches ne vous p\xe9nalisent pour du "contenu dupliqu\xe9". Vous pouvez consultez <a target="_blank" href="http://www.webrankinfo.com/dossiers/techniques/url-canonique">le dossier de webrankinfo</a> \xe0 ce sujet ou <a target="_blank" href="https://support.google.com/webmasters/answer/139066?hl=fr#2">l\'aide google</a>.', null=True, verbose_name='canonical URL', blank=True)),
-                ('master', models.ForeignKey(related_name='translations', editable=False, to='myapp_all.NewsComplete', null=True)),
+                ('master', models.ForeignKey(on_delete=models.CASCADE, related_name='translations', editable=False, to='myapp_all.NewsComplete', null=True)),
             ],
             options={
                 'managed': True,
@@ -109,7 +109,7 @@ class Migration(migrations.Migration):
                 ('newsbox_title', models.CharField(max_length=255, verbose_name='title')),
                 ('newsbox_slug', models.SlugField(help_text='The part of the title that is used in the URL', verbose_name='slug')),
                 ('newsbox_canonical_url', models.URLField(help_text='Ce champ vous permet d\'indiquer aux moteurs de recherche l\'URL "officielle" d\'un contenu dupliqu\xe9. Si votre contenu provient d\'une autre page (de votre site ou non), alors vous devriez indiquer l\'URL de ce contenu "source" afin d\'\xe9viter que les moteurs de recherches ne vous p\xe9nalisent pour du "contenu dupliqu\xe9". Vous pouvez consultez <a target="_blank" href="http://www.webrankinfo.com/dossiers/techniques/url-canonique">le dossier de webrankinfo</a> \xe0 ce sujet ou <a target="_blank" href="https://support.google.com/webmasters/answer/139066?hl=fr#2">l\'aide google</a>.', null=True, verbose_name='canonical URL', blank=True)),
-                ('master', models.ForeignKey(related_name='translations', editable=False, to='myapp_all.NewsExtended', null=True)),
+                ('master', models.ForeignKey(on_delete=models.CASCADE, related_name='translations', editable=False, to='myapp_all.NewsExtended', null=True)),
             ],
             options={
                 'managed': True,
@@ -123,7 +123,7 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='NewsPlugin',
             fields=[
-                ('cmsplugin_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin')),
+                ('cmsplugin_ptr', models.OneToOneField(on_delete=models.CASCADE, parent_link=True, auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin')),
                 ('title', models.CharField(help_text='Title to display before the list', max_length=255, null=True, verbose_name='Title', blank=True)),
                 ('numitems', models.PositiveSmallIntegerField(default=2, help_text='Number of news to display. "0" allow you to display ALL news', verbose_name='Number of news')),
                 ('with_pager', models.BooleanField(default=False, verbose_name='Display a pager')),
@@ -142,7 +142,7 @@ class Migration(migrations.Migration):
                 ('newsbox_summary', djangocms_text_ckeditor.fields.HTMLField(verbose_name='summary')),
                 ('newsbox_title', models.CharField(max_length=255, verbose_name='title')),
                 ('newsbox_slug', models.SlugField(help_text='The part of the title that is used in the URL', verbose_name='slug')),
-                ('master', models.ForeignKey(related_name='translations', editable=False, to='myapp_all.News', null=True)),
+                ('master', models.ForeignKey(on_delete=models.CASCADE, related_name='translations', editable=False, to='myapp_all.News', null=True)),
             ],
             options={
                 'managed': True,
diff --git a/tests/myapp_all/urls.py b/tests/myapp_all/urls.py
index f07fc5981e96390b4402488328e038b8939427d3..87fbfa57c2a46e5908487cf62b68151129c7fb6d 100644
--- a/tests/myapp_all/urls.py
+++ b/tests/myapp_all/urls.py
@@ -1,13 +1,13 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-from django.conf.urls import url, include
+from django.urls import include, path
 from django.conf.urls.i18n import i18n_patterns
 from django.contrib import admin
 
 admin.autodiscover()
 
 urlpatterns = i18n_patterns(
-    url(r'^admin/', include(admin.site.urls)),
-    url(r'', include('cms.urls')),
+    path('admin/', include(admin.site.urls)),
+    path('', include('cms.urls')),
 )
diff --git a/tests/myapp_all/urls_news.py b/tests/myapp_all/urls_news.py
index e65edfaaab710eec35279bc02fd54084e983ecce..717bbe094c9a389f25246dedc72e35222ea7182f 100644
--- a/tests/myapp_all/urls_news.py
+++ b/tests/myapp_all/urls_news.py
@@ -2,13 +2,13 @@
 
 from __future__ import unicode_literals
 
-from django.conf.urls import url
+from django.urls import re_path
 from newsbox_i18n.views import NewsboxI18NDetailView
 
 from .models import News
 
 urlpatterns = [
-    url(
+    re_path(
         r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/(?P<slug>[0-9a-zA-Z_-]+)/$',
         NewsboxI18NDetailView.as_view(model=News,),
         name='news_detail'),
diff --git a/tests/myapp_cms/admin.py b/tests/myapp_cms/admin.py
index 1f2a71b7889ffa55fd1628702d163e952de71024..383f684d8d9175bafb26b1396277967c27401f19 100644
--- a/tests/myapp_cms/admin.py
+++ b/tests/myapp_cms/admin.py
@@ -8,18 +8,19 @@ from newsbox.admin import NewsboxSEOAdmin, NewsboxExpiredAdmin
 from .models import News, NewsComplete, NewsExtended
 
 
+@admin.register(News)
 class NewsAdmin(NewsboxCMSAdmin):
     pass
 
-admin.site.register(News, NewsAdmin)
 
 
+@admin.register(NewsComplete)
 class NewsCompleteAdmin(NewsboxCMSAdmin, NewsboxSEOAdmin, NewsboxExpiredAdmin):
     pass
 
-admin.site.register(NewsComplete, NewsCompleteAdmin)
 
 
+@admin.register(NewsExtended)
 class NewsExtendedAdmin(NewsboxCMSAdmin, NewsboxSEOAdmin, NewsboxExpiredAdmin):
     def get_fieldsets(self, request, obj=None):
         fieldsets = super(NewsExtendedAdmin, self).get_fieldsets(request, obj)
@@ -33,4 +34,3 @@ class NewsExtendedAdmin(NewsboxCMSAdmin, NewsboxSEOAdmin, NewsboxExpiredAdmin):
         list_display.append('seo_field')
         return list_display
 
-admin.site.register(NewsExtended, NewsExtendedAdmin)
diff --git a/tests/myapp_cms/migrations/0001_initial.py b/tests/myapp_cms/migrations/0001_initial.py
index 32ca51418436aacdf23d8233946c2ef2b58e9e63..36d318cc0e45e747ca5d86234e57725ed7adef8f 100644
--- a/tests/myapp_cms/migrations/0001_initial.py
+++ b/tests/myapp_cms/migrations/0001_initial.py
@@ -90,7 +90,7 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='NewsPlugin',
             fields=[
-                ('cmsplugin_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin')),
+                ('cmsplugin_ptr', models.OneToOneField(on_delete=models.CASCADE, parent_link=True, auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin')),
                 ('title', models.CharField(help_text='Title to display before the list', max_length=255, null=True, verbose_name='Title', blank=True)),
                 ('numitems', models.PositiveSmallIntegerField(default=2, help_text='Number of news to display. "0" allow you to display ALL news', verbose_name='Number of news')),
                 ('with_pager', models.BooleanField(default=False, verbose_name='Display a pager')),
diff --git a/tests/myapp_cms/urls.py b/tests/myapp_cms/urls.py
index f72345034567432c6526ab17089054dcf6de343f..7b1e14bc2db8867d218d106fba2bc07ab8806187 100644
--- a/tests/myapp_cms/urls.py
+++ b/tests/myapp_cms/urls.py
@@ -1,12 +1,12 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-from django.conf.urls import url, include
+from django.urls import include, path
 from django.contrib import admin
 
 admin.autodiscover()
 
 urlpatterns = [
-    url(r'^admin/', include(admin.site.urls)),
-    url(r'', include('cms.urls')),
+    path('admin/', include(admin.site.urls)),
+    path('', include('cms.urls')),
 ]
diff --git a/tests/myapp_cms/urls_news.py b/tests/myapp_cms/urls_news.py
index 689b4be0a4621be2236cf8670aae67cf7f8e8f8b..6abbc26adaa2f71f135a3f3171ea38c3c1186ea1 100644
--- a/tests/myapp_cms/urls_news.py
+++ b/tests/myapp_cms/urls_news.py
@@ -1,13 +1,13 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-from django.conf.urls import url
+from django.urls import re_path
 from newsbox.views import NewsboxDetailView
 
 from .models import News
 
 urlpatterns = [
-    url(
+    re_path(
         r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/(?P<slug>[0-9a-zA-Z_-]+)/$',
         NewsboxDetailView.as_view(
             model=News,),
diff --git a/tests/myapp_i18n/migrations/0001_initial.py b/tests/myapp_i18n/migrations/0001_initial.py
index d20f4771fc47f57cd1cb1f6fdcb06e12a195ff67..119c9e9db6fec53415f5a4d180cec5a8263b70e7 100644
--- a/tests/myapp_i18n/migrations/0001_initial.py
+++ b/tests/myapp_i18n/migrations/0001_initial.py
@@ -60,7 +60,7 @@ class Migration(migrations.Migration):
                 ('newsbox_meta_description', models.TextField(max_length=255, null=True, verbose_name='meta description', blank=True)),
                 ('newsbox_meta_keywords', models.CharField(max_length=255, null=True, verbose_name='meta keywords', blank=True)),
                 ('newsbox_canonical_url', models.URLField(help_text='Ce champ vous permet d\'indiquer aux moteurs de recherche l\'URL "officielle" d\'un contenu dupliqu\xe9. Si votre contenu provient d\'une autre page (de votre site ou non), alors vous devriez indiquer l\'URL de ce contenu "source" afin d\'\xe9viter que les moteurs de recherches ne vous p\xe9nalisent pour du "contenu dupliqu\xe9". Vous pouvez consultez <a target="_blank" href="http://www.webrankinfo.com/dossiers/techniques/url-canonique">le dossier de webrankinfo</a> \xe0 ce sujet ou <a target="_blank" href="https://support.google.com/webmasters/answer/139066?hl=fr#2">l\'aide google</a>.', null=True, verbose_name='canonical URL', blank=True)),
-                ('master', models.ForeignKey(related_name='translations', editable=False, to='myapp_i18n.NewsComplete', null=True)),
+                ('master', models.ForeignKey(on_delete=models.CASCADE, related_name='translations', editable=False, to='myapp_i18n.NewsComplete', null=True)),
             ],
             options={
                 'managed': True,
@@ -105,7 +105,7 @@ class Migration(migrations.Migration):
                 ('newsbox_meta_description', models.TextField(max_length=255, null=True, verbose_name='meta description', blank=True)),
                 ('newsbox_meta_keywords', models.CharField(max_length=255, null=True, verbose_name='meta keywords', blank=True)),
                 ('newsbox_canonical_url', models.URLField(help_text='Ce champ vous permet d\'indiquer aux moteurs de recherche l\'URL "officielle" d\'un contenu dupliqu\xe9. Si votre contenu provient d\'une autre page (de votre site ou non), alors vous devriez indiquer l\'URL de ce contenu "source" afin d\'\xe9viter que les moteurs de recherches ne vous p\xe9nalisent pour du "contenu dupliqu\xe9". Vous pouvez consultez <a target="_blank" href="http://www.webrankinfo.com/dossiers/techniques/url-canonique">le dossier de webrankinfo</a> \xe0 ce sujet ou <a target="_blank" href="https://support.google.com/webmasters/answer/139066?hl=fr#2">l\'aide google</a>.', null=True, verbose_name='canonical URL', blank=True)),
-                ('master', models.ForeignKey(related_name='translations', editable=False, to='myapp_i18n.NewsExtended', null=True)),
+                ('master', models.ForeignKey(on_delete=models.CASCADE, related_name='translations', editable=False, to='myapp_i18n.NewsExtended', null=True)),
             ],
             options={
                 'managed': True,
@@ -125,7 +125,7 @@ class Migration(migrations.Migration):
                 ('newsbox_slug', models.SlugField(help_text='The part of the title that is used in the URL', verbose_name='slug')),
                 ('newsbox_summary', models.TextField(verbose_name='summary')),
                 ('newsbox_body', models.TextField(verbose_name='body', blank=True)),
-                ('master', models.ForeignKey(related_name='translations', editable=False, to='myapp_i18n.News', null=True)),
+                ('master', models.ForeignKey(on_delete=models.CASCADE, related_name='translations', editable=False, to='myapp_i18n.News', null=True)),
             ],
             options={
                 'managed': True,
diff --git a/tests/myapp_i18n/urls.py b/tests/myapp_i18n/urls.py
index dd7d8864f4c6e84011a00e92e0d63512d57960e1..4f8805792673b1b7539c4878f07de4d7f6f527f4 100644
--- a/tests/myapp_i18n/urls.py
+++ b/tests/myapp_i18n/urls.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-from django.conf.urls import url, include
+from django.urls import include, path
 from django.conf.urls.i18n import i18n_patterns
 from django.contrib import admin
 from newsbox.urls import get_urls
@@ -15,4 +15,4 @@ news_urls = get_urls(archive_view={'paginate_by': 1},
                      detail_view=NewsboxI18NDetailView)
 
 admin.autodiscover()
-urlpatterns = [url(r'^admin/', include(admin.site.urls))] + i18n_patterns(*news_urls)
+urlpatterns = [path('admin/', include(admin.site.urls))] + i18n_patterns(*news_urls)