super(type, obj): obj must be an instance or subtype of type

I work on a small Django app and get an error tells me, super(type, obj): obj must be an instance or subtype of type. I get it from the views.py file after introducing the function get_object_or_404. The views.py file provided below,

from django.shortcuts import render, get_object_or_404    
from django.http import HttpResponse, HttpResponseRedirect     
from django.views import View     
from .models import URL


# function based view 
def redirect_view(request, shortcode=None, *args, **kwargs):
    obj = get_object_or_404(URL, shortcode=shortcode)
    return HttpResponse("Hello World, the shortcode is {shortcode}".format(shortcode = obj.url))


# class based view 
class ShortenerView(View):

    def get(self, request, shortcode=None,  *args, **kwargs):
        obj = get_object_or_404(URL, shortcode=shortcode)
        return HttpResponse("Hello World 1, the shortcode is {shortcode}".format(shortcode = obj.url))

    def post(self, request, *args, **kwargs):
        return HttpResponse()

the full error message is here,

TypeError at /b/p6jzbp/
super(type, obj): obj must be an instance or subtype of type
Request Method: GET
Request URL:    http://127.0.0.1:8000/b/p6jzbp/
Django Version: 1.11
Exception Type: TypeError
Exception Value:    
super(type, obj): obj must be an instance or subtype of type
Exception Location: /Users/Chaklader/Documents/Projects/UrlShortener/src/shortener/models.py in all, line 18

The line 18 in the models.py is qs_main = super(URL, self).all(*args, **kwargs) and the models.py file is here,

#  will look for the "SHORTCODE_MAX" in the settings and 
#  if not found, will put the value of 15 there 
SHORTCODE_MAX = getattr(settings, "SHORTCODE_MAX", 15)



class UrlManager(models.Manager):

    def all(self, *args, **kwargs):
        qs_main = super(URL, self).all(*args, **kwargs)
        qs      = qs_main.filter(active = True)
        return qs

    def refresh_shortcodes(self, items = None):

        qs = URL.objects.filter(id__gte=1)
        new_codes = 0

        if items is not None and isinstance(items, int):
            qs = qs.order_by('-id')[:items]

        for q in qs:
            q.shortcode = create_shortcode(q)
            print (q.id, " ", q.shortcode)
            q.save()
            new_codes += 1

        return "# new codes created {id}".format(id = new_codes)


class URL(models.Model):

    url         =  models.CharField(max_length = 220, )
    shortcode   =  models.CharField(max_length = SHORTCODE_MAX, blank = True, unique = True)
    updated     =  models.DateTimeField(auto_now = True)
    timestamp   =  models.DateTimeField(auto_now_add = True)
    active      = models.BooleanField(default = True)

    objects = UrlManager()

    def save(self, *args, **kwargs):

        if self.shortcode is  None or self.shortcode == "":
            self.shortcode = create_shortcode(self)

        super(URL, self).save(*args, **kwargs)

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

    def __unicode__(self):
        return str(self.url)

    # class Meta:
    #   ordering = '-id'

Can someone explain the the reason of error to me and how to solve it? I'm open to provide more informations IF required.


Solution 1:

Another way this error can occur is when you reload the module with the class in a Jupiter notebook.

Easy solution is to restart the kernel.

http://thomas-cokelaer.info/blog/2011/09/382/

Check out @Mike W's answer for more detail.

Solution 2:

You should call super using the UrlManager class as first argument not the URL model. super cannot called be with an unrelated class/type:

From the docs,

super(type[, object-or-type]): Return a proxy object that delegates method calls to a parent or sibling class of type.

So you cannot do:

>>> class D:
...    pass
... 
>>> class C:
...    def __init__(self):
...        super(D, self).__init__()
... 
>>> C()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __init__
TypeError: super(type, obj): obj must be an instance or subtype of type

You should do:

qs_main = super(UrlManager, self).all(*args, **kwargs)

Or in Python 3:

qs_main = super().all(*args, **kwargs)

Solution 3:

Elaborating in @Oğuz Şerbetci's answer, in python3 (not necessary only in Jupyter), when there is the need to reload a library, for example we have class Parent and class Child defined as

class Parent(object):
    def __init__(self):
        # do something

class Child(Parent):
    def __init__(self):
        super(Child, self).__init__(self)

then if you do this

import library.Child
reload(library)

Child()

you will get TypeError: super(type, obj): obj must be an instance or subtype of type, the solution is just to re import the class after the reload

import library.Child
reload(library)
import library.Child

Child()

Solution 4:

For Jupyter only You can get his issue in because reload logic have some bugs (issue)

Here is a simple solution/workaround that works for me until issue is not fixed

  1. Add typo like 1001xx at the bottom of the file which you call in the cell
  2. Run your cell - you will see some exception, just skip it
  3. Remove typo which was added on step 1
  4. Run the cell
  5. Profit