I have just started playing with Django and found it a pleasure to set
up web site (even just a toy system so far) using the frame work. Thank
you very much!
I have a data model case that I think probably is quite common to other
people too, and I did not find a way to do it with current Django, so I
wonder whether the developers can take a look of it.
My situation is:
I have quite a few data model classes that share some common fields, so
I have the following model code:
--------------------
class Common(models.Model):
# common fields
......
class Model_A(Common):
# extra fields
......
class Model_B(Common):
# extra fields
......
-------------------
That works, except that a database table will be created for "Common",
which will never be used by itself.
So I will just keep "Common" table empty, not a big deal. But, to make
it more elegant (which I suspect a lot of Python programmers are
obsessed about), can we add some kind of mechanism to tell Django that
"Common" is an "abstract model" that is not intended to be used by
itself, so no table needs to be created?
Thank you for giving it a thought.
Best regards.
Wanrong
A search of the archive of this list will reveal a lot of prior
discussion and information on this topic.
--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."
class common(models.Model):
...
Meta:
create_db_schema = False
class Model_B(models.Model):
...
Meta:
create_db_schema = True
But for this, you'll need to wait for #3163 [1] to be checked-in (and
it's still waitting for tests).
Cheers,
Marc
1: http://code.djangoproject.com/ticket/3163
> --~--~---------~--~----~------------~-------~--~----~
> You received this message because you are subscribed to the Google Groups "Django developers" group.
> To post to this group, send email to django-d...@googlegroups.com
> To unsubscribe from this group, send email to django-develop...@googlegroups.com
> For more options, visit this group at http://groups.google.com/group/django-developers?hl=en
> -~----------~----~----~----~------~----~------~--~---
>
--
http://www.marcfargas.com -- will be finished some day.
This is great news. I am glad I have not re-written all my models with
all those duplicated stuff (I am sure that wouldn't make me feel I am
following the "DRY" principle).
Is it possible to give any prediction when this great stuff will be
checked in? Thanks a lot.
Wanrong
You can always try to give a hand writting suchs tests. Once the ticket
has everything it should it doesn't take too long to get checked-in
unless: a) no committer sees it (unlikely), b) somebody has concerns
about the ticket, unlikely as it's marked "Accepted".
So, if you feel brave enought you can take a look at
http://www.djangoproject.com/documentation/contributing/ and try to get
the ticket's patches to good shape ;)
Marc.
El dom, 13-01-2008 a las 23:04 -0500, Wanrong Lin escribió:
>
> Hi, Marc,
>
> This is great news. I am glad I have not re-written all my models with
> all those duplicated stuff (I am sure that wouldn't make me feel I am
> following the "DRY" principle).
>
> Is it possible to give any prediction when this great stuff will be
> checked in? Thanks a lot.
>
> Wanrong
>
> Marc Fargas wrote:
> > Hi Wanrong,
> > Maybe you could live with something like:
> >
> > class common(models.Model):
> > ...
> > Meta:
> > create_db_schema = False
> >
> > class Model_B(models.Model):
> > ...
> > Meta:
> > create_db_schema = True
> >
> > But for this, you'll need to wait for #3163 [1] to be checked-in (and
> > it's still waitting for tests).
> >
> > Cheers,
> > Marc
> >
> > 1: http://code.djangoproject.com/ticket/3163
> >
> > El s�b, 12-01-2008 a las 14:15 -0500, Wanrong Lin escribi�:
Thanks a lot for this. Look forward to the new version.
Wanrong
Thanks for the update. I just tried the patch (on svn 7020), and found
two problems:
1. Even though the models with "create_db_schema=False" actually will no
longer have tables created in the database, when "syncdb.py" runs the
message still says those tables are created.
2. (More serious) if I have two models, Model_A and Model_B. Model_A
has "create_db_schema=False" and Model_B inherits from Model_A. In the
administration interface if I create a record for Model_B, it saves with
no problem, but when I click on the record name trying to access it, I
will get an exception complaining that the table for Model_A does not
exist (error code 1146). Actually, even without your patch, and the
table for Model_A does exist, I will still get the same exception. So
the problem probably is not caused by your patch, but something related
to using inherited models.
Thanks you for your work and I am hoping sometime soon you or somebody
can get this nailed down.
Wanrong
Thank you very much.
Wanrong
This is a dirty hack mind you, but a rather effective one- I
personally use it for when I need to create common structures w/in
tables and need to able to change the structure definitions in a
single spot. If you did the following-
def add_common_fields(local_scope):
local_scope['field1'] = models.IntegerField(blank=True,
null=True)
local_scope['field2'] = models.CharField(maxlength=255,
blank=True, null=True)
# other common definitions, same thing, updating the passed in
# dict
you could then just do
class Model_A(models.Model):
add_common_fields(locals())
# other fields
class Model_B(models.Model):
add_common_fields(locals())
# other fields.
Pros of the approach:
1) you're easily able to add common fields to model definitions, and
it Just Works (TM)
2) since the class scope is executed in order, via shifting around the
add_common_fields invocation you can shift the sql column definition
as needed.
Cons:
1) exploits the fact locals() in class scope is a mutable dict- I've
yet to see commentary indicating this will change anytime soon for
cpython, but I've no idea if this works in ironpython/jython (assume
so due to metaclass semantics, but I've not tested it).
2) if you've never seen that trick before and come across it in code,
it's likely going to confuse the hell out of the person examining it.
Comments likely warranted to combat that.
3) inheritance would be a bit more pythonic (although inheritance
requires some funkyness to be able to control field ordering).
You probably could fold the approach above into a metaclass if desired
also- would be a bit more pythonic possibly.
Either way, it's a useful trick, so hopefully it helps-
~brian
This is a dirty hack mind you, but a rather effective one- I
personally use it for when I need to create common structures w/in
tables and need to able to change the structure definitions in a
single spot. If you did the following-
def add_common_fields(local_scope):
local_scope['field1'] = models.IntegerField(blank=True,
null=True)
local_scope['field2'] = models.CharField(maxlength=255,
blank=True, null=True)
# other common definitions, same thing, updating the passed in
# dict
you could then just do
class Model_A(models.Model):
add_common_fields(locals())
# other fields
class Model_B(models.Model):
add_common_fields(locals())
# other fields.
You probably could fold the approach above into a metaclass if desired
also- would be a bit more pythonic possibly.
I see only one particular fault with this approach- if you ever add
functionality to allow N inheriting parents, instead of a single line
of inheritance. Django internally has a rather voodoo-rific
creation_counter in the Field class namespace, that serves as an
instance count for each Field derivative instantiated, and it uses
that creation_counter to determine where to insert the Field
derivative into the Models fields list (which maps out to the sql
column ordering).
If you ever try to extend your metaclass approach to allow mixing
multiple parents (which makes sense, imo), the sql column ordering
would be dependant on the order of imports.
Aside from that, nifty approach although I think I'd try to mangle the
ModelMixinBase instance so it was invokable, and then use it like so-
class ResultModel(MixinBaseA(), MixinBaseB()):
specific_1 = models.IntegerField()
The reason I'd try that direction is due to the creation_counter
voodoo- if you could slightly bastardize ModelMixinBase.__call__ so
that it was able return clones of the fields (with the
creation_counter incremented), it would solve the sql field order
issue I mentioned above while enabling N parent inheritance.
Just a thought.
~brian