장고 추상 모델 대 일반 상속
구문 외에도 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
하면 클래스 (및 하위 클래스)에 이러한 특성이 제공되지 않습니다.
다른 답변에서 보지 못한 것을 추가하고 싶었습니다.
Unlike with python classes, field name hiding is not permited with model inheritance.
For example, I have experimented issues with an use case as follows:
I had a model inheriting from django's 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
# ...
Then I had my mixin which among other things I wanted it to override the related_name
of the groups
field. So it was more or less like this:
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.'))
I was using this 2 mixins as follows:
class Member(PermissionMixin, WithManagedGroupMixin):
pass
So yeah, I expected this to work but it didn't. But the issue was more serious because the error I was getting wasn't pointing to the models at all, I had no idea of what was going wrong.
While trying to solve this I randomly decided to change my mixin and convert it to an abstract model mixin. The error changed to this:
django.core.exceptions.FieldError: Local field 'groups' in class 'Member' clashes with field of similar name from base class 'PermissionMixin'
As you can see, this error does explain what is going on.
This was a huge difference, in my opinion :)
The main difference is how the databases tables for the models are created. If you use inheritance without abstract = True
Django will create a separate table for both the parent and the child model which hold the fields defined in each model.
If you use abstract = True
for the base class Django will only create a table for the classes that inherit from the base class - no matter if the fields are defined in the base class or the inheriting class.
Pros and cons depend on the architecture of your application. Given the following example models:
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 the Publishable
class is not abstract Django will create a table for publishables with the columns title
and date
and separate tables for BlogEntry
and Image
. The advantage of this solution would be that you are able to query across all publishables for fields defined in the base model, no matter if they are blog entries or images. But therefore Django will have to do joins if you e.g. do queries for images... If making Publishable
abstract = True
Django will not create a table for Publishable
, but only for blog entries and images, containing all fields (also the inherited ones). This would be handy because no joins would be needed to an operation such as get.
Also see Django's documentation on model inheritance.
The main difference is when you inherit the User class. One version will behave like a simple class, and the other will behave like a Django modeel.
If you inherit the base "object" version, your Employee class will just be a standard class, and first_name won't become part of a database table. You can't create a form or use any other Django features with it.
If you inherit the models.Model version, your Employee class will have all the methods of a Django Model, and it will inherit the first_name field as a database field that can be used in a form.
According to the documentation, an Abstract Model "provides a way to factor out common information at the Python level, whilst still only creating one database table per child model at the database level."
참고URL : https://stackoverflow.com/questions/16655097/django-abstract-models-versus-regular-inheritance
'development' 카테고리의 다른 글
gem 기본 확장을 빌드하는 데 실패했습니다 — Rails 설치 (0) | 2020.10.23 |
---|---|
Android : ListView의 List 항목에서 Button에 대한 onClick 이벤트를 설정하는 방법 (0) | 2020.10.23 |
런타임시 Entity Framework 변경 연결 (0) | 2020.10.23 |
테스트 대상 X에 오류가 발생했습니다 (예기치 않은 조기 종료, 작업이 부트 스트랩을 완료하지 않음-다시 시작하지 않음) (0) | 2020.10.23 |
ActiveRecord를 사용하면 after_update 중에 레코드의 이전 값을 가져올 수있는 방법이 있습니까? (0) | 2020.10.23 |