Opened 17 years ago

Closed 17 years ago

#6575 closed (invalid)

Changeset 7098 brakes model class creation if one uses own django.db.model.base.Model class

Reported by: moep Owned by: Malcolm Tredinnick
Component: Database layer (models, ORM) Version: dev
Severity: Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Changeset 7098 brakes model class creation if one uses an own django.db.model.base.Model replacement class.

The problem is that ModelBase.__new__ assumes that a class that is a subclass of Model automatically has a _meta attribute.
That is not necessarily the case. If you use a custom replacement for Model that extends Model it is a subclass of Model but
doesn't have a meta attribute.

file mymodel.py

from django.db import modfrom django.db import models

class MyModelBase(models.base.ModelBase):
	pass

class MyModel(models.base.Model):
	pass

class Foo(MyModel):
	pass
$ import mymodel
>>> AttributeError: type object 'MyModel' has no attribute '_meta'

The problem is that you cannot so easily decide whether a class that extends Model is a Model Class or not. You could
of course check whether Class has a _meta attribute but that isn't a nice solution.

I think the only clean way to test if a class that extends Model is actually a Model is to use a special class from which
you can derive. But that's is why Model exists in the first place (except for metaclassing) I think.

So we need a design decision here, whether we add a new class that extends and replaces models.Model, we add a "ugly"
test if class has a _meta attribute or don't allow replacing model.Model at all.


Change History (3)

comment:1 by moep, 17 years ago

One can add a Fake meta class to work around this problem.

from django.db import modfrom django.db import models

class MyModelBase(models.base.ModelBase):
	pass

class FakeMeta(object):
	parents = []
	fields = []

class MyModel(models.base.Model):
	_meta = FakeMeta()

class Foo(MyModel):
	pass

comment:2 by Malcolm Tredinnick, 17 years ago

Owner: changed from nobody to Malcolm Tredinnick

comment:3 by Malcolm Tredinnick, 17 years ago

Resolution: invalid
Status: newclosed

The problem here isn't subclasses of Model. Otherwise, for example, the model_inheritance tests wouldn't even import properly.

The problem with your example is that you've replaced the metaclass without replacing the functionality. ModelBase ensures that every subclass of Model has a _meta attribute. You've removed that condition and so your code breaks. If you're going to replace the metaclass, you must continue to fill in the class structure correctly in your replacement __new__.

Note: See TracTickets for help on using tickets.
Back to Top