Opened 10 years ago

Closed 9 years ago

Last modified 9 years ago

#419 closed enhancement (duplicate)

Create meta.AbstractModel

Reported by: adrian Owned by: adrian
Component: Metasystem Version:
Severity: enhancement Keywords:
Cc: eric@… Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

class BaseModel(meta.Model):
    foo = meta.CharField(maxlength=200)

class FirstChild(BaseModel):
    bar = meta.CharField(maxlength=10)

class SecondChild(BaseModel):
    bar = meta.CharField(maxlength=10)

In this example, BaseModel only exists as an "abstract class" -- its only purpose is to be extended. We don't want to install SQL for it, and we don't want it to be available via the API. So we could introduce a meta.AbstractModel for models that serve this purpose.

Attachments (1)

django-core-meta-__init__.py.diff (1.5 KB) - added by eric@… 10 years ago.
Proposed "no_table" patch to django/core/meta/init.py

Download all attachments as: .zip

Change History (5)

comment:1 Changed 10 years ago by adrian

  • priority changed from normal to low
  • Type changed from defect to enhancement

comment:2 Changed 10 years ago by eric@…

  • Cc eric@… added

Here's a proposed patch that acheives the same result, but without creating a meta.AbstractModel. It passes the django unit tests existing as of today.

To summarize, it modifies django/core/meta/init.py to:

  1. check for a (new) meta attribute "no_table"
  2. if no_table is true, keep the model class out of the module's list of "_MODEL"s

The result is that the model isn't included in other functions that
operate on meta.MODEL classes while still allowing inheritance.

I've only tested it lightly, with the existing unit tests and my simple
"experiment" classes.

If you like the fix, please tell me how you like your patch submissions
formatted and/or what other test(s) you'd like to see. I'll then clean
it up and write unit tests like the existing ones that generate the
model example documentation.

Eric.

[ewalstad@pasauran django_src]$ diff -u
django/core/meta/__init__.py.orig django/core/meta/__init__.py
--- django/core/meta/__init__.py.orig   2005-09-18 14:51:18.000000000
-0700
+++ django/core/meta/__init__.py        2005-09-18 15:59:20.000000000
-0700
@@ -412,6 +412,11 @@
         # attribute order.
         fields.sort(lambda x, y: x.creation_counter - y.creation_counter)

+        # Should this class generate database tables (Default is Yes)?
+        # This has the ultimate effect of keeping this class out of the _MODELS
+        # list.
+        create_table = not (meta_attrs.pop('no_table', False))
+
         # If this model is a subclass of another model, create an Options
         # object by first copying the base class's _meta and then updating it
         # with the overrides from this class.
@@ -673,7 +678,9 @@
             # contain this list:
             # [<class 'django.models.polls.Poll'>, <class 'django.models.polls.Choice'>]
             # Don't do this if replaces_module is set.
-            app_package.__dict__.setdefault('_MODELS', []).append(new_class)
+            # Exclude models where the user has set 'no_table = True'
+            if create_table:
+                app_package.__dict__.setdefault('_MODELS', []).append(new_class)

         # Cache the app label.
         opts.app_label = app_label
@@ -725,6 +732,7 @@
     def __repr__(self):
         return '<%s object>' % self.__class__.__name__

+
 ############################################
 # HELPER FUNCTIONS (CURRIED MODEL METHODS) #
 ############################################

[ewalstad@pasauran django_src]$ python tests/runtests.py
Running tests with database 'postgresql'
All tests passed.

experiment.py file:

from django.core import meta

class MyBaseClass(meta.Model):
    """This class will not result in any tables being generated by django"""
    created_on = meta.DateTimeField(auto_now_add=True)
    modified_on = meta.DateTimeField(auto_now=True)
    class META:
        no_table = True

class MyDerived(MyBaseClass):
    """This class will have tables generated and will include the:
     - created_on and
     - modified_on fields
    which are inherited from the 'MyBaseClass' class.
    """
    name = meta.CharField(maxlength=25)
    class META:
       module_name = 'my_derived_class'

class MyOtherDerived(MyDerived):
    """This class will not result in any tables being generated by django and
    it will include all the fields inherited from both 'MyBaseClass' and
    'MyDerived' as well as those fields defined here.
    """
    color = meta.CharField(maxlength=25)
    class META:
        module_name = 'my_other_derived'
        # Explicitly set the no_table flag so that this class doesn't result in
        # a table being created.
        no_table = True

class MyLastDerived(MyOtherDerived):
    """This class will have tables generated and will include the:
     - created_on and
     - modified_on fields
    which are inherited from the 'MyBaseClass' class,
     - name
    which is inherited from the 'MyDerived' class and
     - color
    which is inherited from the 'MyOtherDerived' class as well as those fields
    defined here.
    """
    size = meta.IntegerField(choices=((0, 'small'),
                                      (1, 'medium'),
                                      (2, 'large'),
                                      ))
    class META:
        module_name = 'my_last_derived'

[ewalstad@pasauran django_src]$ django-admin.py sql experiment

BEGIN;
CREATE TABLE experiment_my_derived_class (
    id serial NOT NULL PRIMARY KEY,
    modified_on timestamp with time zone NOT NULL,
    created_on timestamp with time zone NOT NULL,
    name varchar(25) NOT NULL
);
CREATE TABLE experiment_my_last_derived (
    id serial NOT NULL PRIMARY KEY,
    color varchar(25) NOT NULL,
    modified_on timestamp with time zone NOT NULL,
    created_on timestamp with time zone NOT NULL,
    name varchar(25) NOT NULL,
    size integer NOT NULL
); 

Mailing list posting: http://groups.google.com/group/django-users/browse_frm/thread/75aebf82055172cf/c0cea4033973f7c8?q=no_table&rnum=1#c0cea4033973f7c8

Changed 10 years ago by eric@…

Proposed "no_table" patch to django/core/meta/init.py

comment:3 Changed 9 years ago by Andreas

I am using the no_table-patch in my project and it works fine. It's quite useful, I think it would be no mistake to include this in the trunk.

comment:4 Changed 9 years ago by adrian

  • Resolution set to duplicate
  • Status changed from new to closed

This will be fixed in magic-removal with mixins.

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