[python] 장고 추상 모델 대 일반 상속

구문 외에도 django 추상 모델을 사용하는 것과 django 모델에서 일반 Python 상속을 사용하는 것의 차이점은 무엇입니까? 장점과 단점?

업데이트 : 내 질문이 오해되었다고 생각하고 추상 모델과 django.db.models.Model에서 상속하는 클래스의 차이점에 대한 응답을 받았습니다. 실제로 django 추상 클래스 (Meta : abstract = True)에서 상속하는 모델 클래스와 ‘object'(model.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(...



답변

실제로 django 추상 클래스 (Meta : abstract = True)에서 상속하는 모델 클래스와 ‘object'(model.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)
);


답변

추상 모델은 각 하위 하위 항목에 대한 전체 열 집합이있는 테이블을 생성하는 반면 “일반”Python 상속을 사용하면 연결된 테이블 집합 ( “다중 테이블 상속”이라고 함)이 생성됩니다. 두 가지 모델이있는 경우를 고려하십시오.

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 상속을 사용하는 경우 두 개의 테이블이 있습니다.

app_vehicle:
| id | num_wheels

app_car:
| id | vehicle_id | make | model

자동차의 바퀴 수가 vehicle_id있는 행에 대한 링크는 어디에 있습니까 app_vehicle?

이제 Django는 이것을 객체 형태로 멋지게 조합 num_wheels하여에 속성으로 액세스 할 수 Car있지만 데이터베이스의 기본 표현은 다릅니다.


최신 정보

업데이트 된 질문을 해결하기 위해 Django 추상 클래스에서 상속 object하는 것과 Python에서 상속하는 것의 차이점 은 전자가 데이터베이스 개체로 취급되고 (따라서 테이블이 데이터베이스에 동기화 됨) Model. 일반 Python에서 상속 object하면 클래스 (및 하위 클래스)에 이러한 특성이 제공되지 않습니다.


답변

주요 차이점은 모델에 대한 데이터베이스 테이블이 생성되는 방식입니다. abstract = TrueDjango 없이 상속을 사용하면 각 모델에 정의 된 필드를 보유하는 부모 및 자식 모델 모두에 대해 별도의 테이블이 생성됩니다.

abstract = True기본 클래스에 사용 하는 경우 Django는 필드가 기본 클래스 또는 상속 클래스에 정의되어 있는지 여부에 관계없이 기본 클래스에서 상속하는 클래스에 대한 테이블 만 만듭니다.

장단점은 애플리케이션의 아키텍처에 따라 다릅니다. 다음 예제 모델이 주어집니다.

class Publishable(models.Model):
    title = models.CharField(...)
    date = models.DateField(....)

    class Meta:
        # abstract = True

class BlogEntry(Publishable):
    text = models.TextField()


class Image(Publishable):
    image = models.ImageField(...)

는 IF Publishable클래스는 추상적하지 장고는 열 publishables에 대한 테이블을 생성합니다 titledate및 별도의 테이블 BlogEntryImage. 이 솔루션의 장점 은 블로그 항목 또는 이미지에 관계없이 기본 모델에 정의 된 필드에 대해 모든 게시 가능 항목에서 쿼리 할 수 ​​있다는 것 입니다. 그러나 따라서 Django는 예를 들어 이미지에 대한 쿼리를 수행하는 경우 조인을 수행해야합니다. Publishable abstract = TrueDjango를 만들면 Publishable모든 필드 (또한 상속 된 필드)를 포함하는 블로그 항목 및 이미지에 대한 테이블이 생성되지 않습니다 . 이것은 get과 같은 작업에 조인이 필요하지 않기 때문에 편리합니다.

모델 상속에 대한 Django의 문서 도 참조하세요 .


답변

다른 답변에서 보지 못한 것을 추가하고 싶었습니다.

파이썬 클래스와 달리 필드 이름 숨기기는 허용되지 않습니다. 모델 상속 .

예를 들어 다음과 같은 사용 사례에 대한 문제를 실험했습니다.

나는 django의 인증 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_namegroups필드. 그래서 거의 다음과 같았습니다.

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.'))

나는 다음과 같이이 두 가지 믹스 인을 사용했습니다.

class Member(PermissionMixin, WithManagedGroupMixin):
    pass

네, 이것이 작동 할 것으로 예상했지만 작동하지 않았습니다. 그러나 문제는 더 심각했습니다. 제가받은 오류가 모델을 전혀 가리 키지 않았기 때문에 무엇이 잘못되었는지 전혀 몰랐습니다.

이 문제를 해결하는 동안 무작위로 믹스 인을 변경하고 추상 모델 믹스 인으로 변환하기로 결정했습니다. 오류가 다음과 같이 변경되었습니다.

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

보시다시피이 오류는 무슨 일이 일어나고 있는지 설명합니다.

내 의견으로는 이것은 큰 차이였습니다. 🙂


답변

가장 큰 차이점은 User 클래스를 상속 할 때입니다. 한 버전은 단순한 클래스처럼 작동하고 다른 버전은 Django 모델처럼 작동합니다.

기본 “객체”버전을 상속하는 경우 Employee 클래스는 표준 클래스 일 뿐이며 first_name은 데이터베이스 테이블의 일부가되지 않습니다. 양식을 만들거나 다른 Django 기능을 사용할 수 없습니다.

models.Model 버전을 상속하면 Employee 클래스는 Django Model 의 모든 메서드를 갖게 되며 first_name 필드를 양식에서 사용할 수있는 데이터베이스 필드로 상속합니다.

문서에 따르면 추상 모델은 “데이터베이스 수준에서 자식 모델 당 하나의 데이터베이스 테이블 만 생성하면서 Python 수준에서 공통 정보를 추출하는 방법을 제공합니다.”


답변

별도의 테이블을 만들지 않고 ORM이 데이터베이스에 조인을 만들 필요가 없기 때문에 대부분의 경우 추상 클래스를 선호합니다. 그리고 추상 클래스를 사용하는 것은 Django에서 매우 간단합니다.

class Vehicle(models.Model):
    title = models.CharField(...)
    Name = models.CharField(....)

    class Meta:
         abstract = True

class Car(Vehicle):
    color = models.CharField()

class Bike(Vehicle):
    feul_average = models.IntegerField(...)


답변