我在一个小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()
Run Code Online (Sandbox Code Playgroud)
完整的错误消息在这里,
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
Run Code Online (Sandbox Code Playgroud)
将line 18在models.pyIS 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'
Run Code Online (Sandbox Code Playgroud)
有人可以向我解释错误的原因以及如何解决它?如果需要,我愿意提供更多信息.
Oğu*_*tci 50
发生此错误的另一种方法是在Jupiter笔记本中使用类重新加载模块.
http://thomas-cokelaer.info/blog/2011/09/382/
Mos*_*oye 17
您应该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
Run Code Online (Sandbox Code Playgroud)
你应该做:
qs_main = super(UrlManager, self).all(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
或者在Python 3中:
qs_main = super().all(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
Mik*_*e W 12
在阐述@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)
Run Code Online (Sandbox Code Playgroud)
那么如果你这样做
import library.Child
reload(library)
Child()
Run Code Online (Sandbox Code Playgroud)
您将获得TypeError: super(type, obj): obj must be an instance or subtype of type,解决方案是在重新加载后重新导入类
import library.Child
reload(library)
import library.Child
Child()
Run Code Online (Sandbox Code Playgroud)
小智 7
我找到的解决这个问题的最佳解决方案只能使用 python 3。然后你不需要指定“super”的参数,那么你就不会再像这样编写你的类时出现错误:
class D:
pass
class C(D):
def __init__(self):
super().__init__()# no arguments given to super()
Run Code Online (Sandbox Code Playgroud)
另一种有趣的方法是,如果分支的合并重复了该类,那么在文件中您有相同名称的两个定义,例如
class A(Foo):
def __init__(self):
super(A, self).__init__()
#...
class A(Foo):
def __init__(self):
super(A, self).__init__()
#...
Run Code Online (Sandbox Code Playgroud)
如果您尝试从对 A 的第一个定义的静态引用创建实例,一旦它尝试super在__init__方法内调用 ,A将引用 的第二个定义A,因为它已被覆盖。当然,解决方案是删除类的重复定义,这样它就不会被覆盖。
这看起来似乎永远不会发生,但它就发生在我身上,当时我没有足够关注两个分支的合并。我的测试因问题中描述的错误消息而失败,所以我想我应该将我的发现留在这里,即使它没有完全回答具体问题。