Super (type, obj): obj должен быть экземпляром или подтипом типа
Я работаю над небольшим приложением Django
и получаю сообщение об ошибке, super(type, obj): obj must be an instance or subtype of type
. Я получаю его из файла views.py
после введения функции get_object_or_404
. Файл views.py
, указанный ниже,
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()
здесь отображается полное сообщение об ошибке,
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
В models.py
line 18
находится qs_main = super(URL, self).all(*args, **kwargs)
, а файл models.py
находится здесь,
# 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'
Может кто-нибудь объяснить причину ошибки для меня и как ее решить? Я открыт для предоставления дополнительной информации, если требуется.
Ответы
Ответ 1
Вы должны вызывать super
с использованием класса UrlManager
качестве первого аргумента, а не модели URL
. super
не может быть вызван с несвязанным классом/типом:
Из документов,
super(type[, object-or-type])
: возвращает прокси-объект, который делегирует вызовы метода родительскому или родственному классу типа.
Так что вы не можете сделать:
>>> 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
Ты должен сделать:
qs_main = super(UrlManager, self).all(*args, **kwargs)
Или в Python 3:
qs_main = super().all(*args, **kwargs)
Ответ 2
Еще один способ возникновения этой ошибки - перезагрузка модуля с классом в записной книжке Jupiter.
Простое решение - перезапустить ядро.
http://thomas-cokelaer.info/blog/2011/09/382/
Ответ 3
Разработка в ответе @Oğuz Şerbetci, в python3 (не обязательно только в Jupyter), когда есть необходимость перезагрузить библиотеку, например, у нас есть class Parent
и class Child
определенные как
class Parent(object):
def __init__(self):
# do something
class Child(Parent):
def __init__(self):
super(self,Child).__init__(self)
тогда, если вы сделаете это
import library.Child
reload(library)
Child()
вы получите TypeError: super(type, obj): obj must be an instance or subtype of type
, решение состоит в том, чтобы просто повторно импортировать класс после перезагрузки
import library.Child
reload(library)
import library.Child
Child()
Ответ 4
Еще один интересный способ заключается в том, что слияние ветвей дублирует класс, так что в файле у вас есть два определения для одного и того же имени, например
class A(Foo):
def __init__(self):
super(A, self).__init__()
#...
class A(Foo):
def __init__(self):
super(A, self).__init__()
#...
Если вы попытаетесь создать экземпляр из статической ссылки на первое определение A, как только он попытается вызвать super
, внутри метода __init__
A
будет ссылаться на второе определение A
, поскольку он был перезаписан. Решение - конечно, - удалить дублирующее определение класса, поэтому оно не будет перезаписано.
Это может показаться чем-то, что никогда не произойдет, но это случилось со мной, когда я не обращал достаточно пристального внимания на слияние двух ветвей. Мои тесты не удались с сообщением об ошибке, описанным в вопросе, поэтому я думал, что остану здесь свои выводы, хотя он точно не отвечает на конкретный вопрос.