95

構文の他に、django 抽象モデルを使用することと、django モデルでプレーンな Python 継承を使用することの違いは何ですか? 長所と短所?

更新: 私の質問が誤解されていたと思います。抽象モデルと django.db.models.Model から継承するクラスの違いについて回答を受け取りました。 私は実際に、django抽象クラス(Meta:abstract = True)から継承するモデルクラスと、たとえば「オブジェクト」(models.Modelではない)から継承するプレーンなPythonクラスの違いを知りたいです。

次に例を示します。

class User(object):
   first_name = models.CharField(..

   def get_username(self):
       return self.username

class User(models.Model):
   first_name = models.CharField(...

   def get_username(self):
       return self.username

   class Meta:
       abstract = True

class Employee(User):
   title = models.CharField(...
4

6 に答える 6

168

私は実際に、django抽象クラス(Meta:abstract = True)から継承するモデルクラスと、たとえば「オブジェクト」(models.Modelではない)から継承するプレーンなPythonクラスの違いを知りたいです。

Django は のサブクラスのテーブルのみを生成するmodels.Modelため、前者は...

class User(models.Model):
   first_name = models.CharField(max_length=255)

   def get_username(self):
       return self.username

   class Meta:
       abstract = True

class Employee(User):
   title = models.CharField(max_length=255)

...次の行に沿って、単一のテーブルが生成されます...

CREATE TABLE myapp_employee
(
    id         INT          NOT NULL AUTO_INCREMENT,
    first_name VARCHAR(255) NOT NULL,
    title      VARCHAR(255) NOT NULL,
    PRIMARY KEY (id)
);

...後者は...

class User(object):
   first_name = models.CharField(max_length=255)

   def get_username(self):
       return self.username

class Employee(User):
   title = models.CharField(max_length=255)

...テーブルは生成されません。

多重継承を使用して、このようなことを行うことができます...

class User(object):
   first_name = models.CharField(max_length=255)

   def get_username(self):
       return self.username

class Employee(User, models.Model):
   title = models.CharField(max_length=255)

...テーブルを作成しますが、クラスで定義されたフィールドを無視するUserため、このようなテーブルになります...

CREATE TABLE myapp_employee
(
    id         INT          NOT NULL AUTO_INCREMENT,
    title      VARCHAR(255) NOT NULL,
    PRIMARY KEY (id)
);
于 2013-05-30T14:19:54.643 に答える
38

抽象モデルは、各サブ子の列のセット全体を含むテーブルを作成しますが、「プレーンな」Python 継承を使用すると、リンクされたテーブルのセット (別名「複数テーブル継承」) が作成されます。2 つのモデルがある場合を考えてみましょう。

class Vehicle(models.Model):
  num_wheels = models.PositiveIntegerField()


class Car(Vehicle):
  make = models.CharField(…)
  year = models.PositiveIntegerField()

が抽象モデルの場合Vehicle、単一のテーブルが作成されます。

app_car:
| id | num_wheels | make | year

ただし、プレーンな Python 継承を使用する場合は、次の 2 つのテーブルが作成されます。

app_vehicle:
| id | num_wheels

app_car:
| id | vehicle_id | make | model

車の車輪の数もvehicle_idある行へのリンクはどこにありますか。app_vehicle

これで、Django はこれをオブジェクト形式にうまくまとめnum_wheelsて、 の属性としてアクセスできるようCarにしますが、データベース内の基になる表現は異なります。


アップデート

更新された質問に対処するために、Django 抽象クラスからの継承と Python からの継承の違いobjectは、前者がデータベース オブジェクトとして扱われ (そのため、そのテーブルがデータベースに同期されます)、動作がModel. プレーンな Python から継承するobjectと、クラス (およびそのサブクラス) にこれらの性質がまったくなくなります。

于 2013-05-20T17:55:01.917 に答える
10

他の回答で見たことがないものを追加したかっただけです。

Python クラスとは異なり、モデルの継承ではフィールド名の非表示は許可されていません。

たとえば、次のようなユースケースで問題を実験しました。

django の auth PermissionMixinから継承するモデルがありました:

class PermissionsMixin(models.Model):
    """
    A mixin class that adds the fields and methods necessary to support
    Django's Group and Permission model using the ModelBackend.
    """
    is_superuser = models.BooleanField(_('superuser status'), default=False,
        help_text=_('Designates that this user has all permissions without '
                    'explicitly assigning them.'))
    groups = models.ManyToManyField(Group, verbose_name=_('groups'),
        blank=True, help_text=_('The groups this user belongs to. A user will '
                                'get all permissions granted to each of '
                                'his/her group.'))
    user_permissions = models.ManyToManyField(Permission,
        verbose_name=_('user permissions'), blank=True,
        help_text='Specific permissions for this user.')

    class Meta:
        abstract = True

    # ...

related_name次に、特にgroupsフィールドの をオーバーライドしたいミックスインを作成しました。したがって、多かれ少なかれ次のようになりました。

class WithManagedGroupMixin(object):
    groups = models.ManyToManyField(Group, verbose_name=_('groups'),
        related_name="%(app_label)s_%(class)s",
        blank=True, help_text=_('The groups this user belongs to. A user will '
                            'get all permissions granted to each of '
                            'his/her group.'))

この2つのミックスインを次のように使用していました:

class Member(PermissionMixin, WithManagedGroupMixin):
    pass

ええ、私はこれがうまくいくと思っていましたが、うまくいきませんでした。しかし、私が得たエラーはモデルをまったく指していなかったので、問題はより深刻でした。何が問題なのかわかりませんでした。

これを解決しようとしているときに、ランダムに mixin を変更して抽象モデル mixin に変換することにしました。エラーは次のように変わりました。

django.core.exceptions.FieldError: Local field 'groups' in class 'Member' clashes with field of similar name from base class 'PermissionMixin'

ご覧のとおり、このエラーは何が起こっているかを説明しています。

私の意見では、これは大きな違いでした:)

于 2013-06-01T13:26:39.043 に答える