I have a class defined inside another class like this. Basically I am trying to override the save method in db.Model--it actually just the django.db.models.Model. But when I run this block of code, I see the an NameError.
class GameCenterDB:
class GameCenterDBConfig:
class Config:
db_for_read = "game_center_db.slave"
db_for_write = "default"
class PublisherTab(GameCenterDBConfig, db.Model):
publisher_id = db.PositiveIntegerField(primary_key=True)
name = db.CharField(max_length=100)
create_time = db.PositiveIntegerField()
update_time = db.PositiveIntegerField()
class Meta:
db_table = u'publisher_tab'
def save(self, *args, **kwargs):
curr_time = int(time.time())
if not self.create_time:
self.create_time = curr_time
self.update_time = curr_time
# See the line below, this triggers an error
# NameError: global name 'PublisherTab' is not defined
super(PublisherTab, self).save(*args, **kwargs)
According to my understanding, when it is inside GameCenterDB, I should be able to use PublisherTab directly right?
NameError: global name 'PublisherTab' is not defined
Change save method like this will solve the error. But I just do not understand why.
def save(self, *args, **kwargs):
curr_time = int(time.time())
if not self.create_time:
self.create_time = curr_time
self.update_time = curr_time
super(GameCenterDB.PublisherTab, self).save(*args, **kwargs)
Also, seems that class PublisherTab(GameCenterDBConfig, db.Model): is interpreted without any error and the mixin worked. Why GameCenterDBConfig can be used without any problem?
解决方案
"According to my understanding, when it is inside GameCenterDB, I should be able to use PublisherTab directly right?"
Wrong. Python requires full qualification of class members with either the class or variable (typically 'self') prefix. This is true of any member variable declared within a class. E.g.:
class Foo:
class Bar:
quux = 1
def f(self):
print "Foo.Bar.quux: %d" % Foo.Bar.quux
print "self.Bar.quux: %d" % self.Bar.quux
foo = Foo()
foo.f()
Now consider this example:
# scope is top-level module
class Foo:
# scope is Foo
class Bar:
# scope is Foo.Bar
quux = 1
# scope is Foo
Bar.quux = 2 # [A]
try:
print "x: %d" % x
except NameError:
print "x gave an error because it is outside scope"
def f(self):
# scope is Foo when we are defining but not when we are running!
try:
print "Bar.quux: %d" % Bar.quux
except NameError:
print "Bar.quux gave us an error because it is outside scope"
print "Foo.Bar.quux: %d" % Foo.Bar.quux
print "self.Bar.quux: %d" % self.Bar.quux
print "x is in scope: %d" % x
# scope is top-level module again
x = 456
foo = Foo()
foo.f()
I've added the code at [A]. The program now prints "2" not "1".
Why don't you need to qualify Bar.quux at [A] but you do inside f()?
Because when [A] is run, the script is inside the scope of class Foo.
But when foo.f() is run, the script is inside the scope of the module because that is where you are calling it from. That's why you need to explicitly declare self in the method definition, and foo.f() is syntactic sugar for Foo.f(foo).
This is one of the less pleasing parts of Python. It makes sense is hard to understand.