rpq*_*rpq 75 python django django-models
除了语法之外,使用django抽象模型和使用普通Python继承与django模型之间的区别是什么?优点和缺点?
更新:我认为我的问题被误解了,我收到了关于抽象模型和继承自django.db.models.Model的类之间差异的回复. 我实际上想知道继承自django抽象类(Meta:abstract = True)的模型类与继承自say,'object'(而不是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(...
Run Code Online (Sandbox Code Playgroud)
Aya*_*Aya 130
我实际上想知道继承自django抽象类(Meta:abstract = True)的模型类与继承自say,'object'(而不是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)
Run Code Online (Sandbox Code Playgroud)
...将导致生成一个表,沿着......的行...
CREATE TABLE myapp_employee
(
id INT NOT NULL AUTO_INCREMENT,
first_name VARCHAR(255) NOT NULL,
title VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
);
Run Code Online (Sandbox Code Playgroud)
......而后者......
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)
Run Code Online (Sandbox Code Playgroud)
...不会导致生成任何表.
您可以使用多重继承来执行此类操作...
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)
Run Code Online (Sandbox Code Playgroud)
...会创建一个表,但它会忽略User
类中定义的字段,所以你最终会得到一个像这样的表...
CREATE TABLE myapp_employee
(
id INT NOT NULL AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
);
Run Code Online (Sandbox Code Playgroud)
mip*_*adi 32
抽象模型为每个子项创建一个包含整个列集的表,而使用"普通"Python继承创建一组链接表(也称为"多表继承").考虑一下你有两个模型的情况:
class Vehicle(models.Model):
num_wheels = models.PositiveIntegerField()
class Car(Vehicle):
make = models.CharField(…)
year = models.PositiveIntegerField()
Run Code Online (Sandbox Code Playgroud)
如果Vehicle
是抽象模型,您将拥有一个表:
app_car:
| id | num_wheels | make | year
Run Code Online (Sandbox Code Playgroud)
但是,如果使用纯Python继承,则会有两个表:
app_vehicle:
| id | num_wheels
app_car:
| id | vehicle_id | make | model
Run Code Online (Sandbox Code Playgroud)
到那vehicle_id
一行的链接在哪里app_vehicle
也会有汽车的轮子数量.
现在,Django将以对象形式很好地将它放在一起,这样您就可以num_wheels
作为属性访问Car
,但数据库中的底层表示将是不同的.
为了解决您更新的问题,继承Django抽象类和继承Python的区别在于object
前者被视为数据库对象(因此它的表被同步到数据库)并且它具有a的行为Model
.继承普通的Python object
赋予类(及其子类)这些特性.
主要区别在于如何创建模型的数据库表.如果在没有abstract = True
Django的情况下使用继承,则会为父模型和子模型创建一个单独的表,该表包含每个模型中定义的字段.
如果您使用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(...)
Run Code Online (Sandbox Code Playgroud)
如果Publishable
该类不是抽象的Django会创建一个表与列publishables title
与date
和单独的表BlogEntry
和Image
.此解决方案的优势在于,无论是博客条目还是图像,您都可以在所有可发布项中查询基本模型中定义的字段.但是因此,如果您对图像进行查询,Django将不得不进行连接...如果让Publishable
abstract = True
Django不会为Publishable
包含所有字段(也包括继承的字段)的博客条目和图像创建表格.这样很方便,因为get等操作不需要连接.
另请参阅Django关于模型继承的文档.
只是想添加一些我在其他答案中没有看到的东西.
例如,我已经尝试了一个用例的问题,如下所示:
我有一个继承自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
# ...
Run Code Online (Sandbox Code Playgroud)
然后我得到了我的mixin,除其他外,我希望它覆盖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.'))
Run Code Online (Sandbox Code Playgroud)
我使用这2个mixins如下:
class Member(PermissionMixin, WithManagedGroupMixin):
pass
Run Code Online (Sandbox Code Playgroud)
所以,是的,我希望这可行,但事实并非如此.但问题更严重,因为我得到的错误根本没有指向模型,我不知道出了什么问题.
在尝试解决这个问题时,我随机决定改变我的mixin并将其转换为抽象模型mixin.错误更改为:
django.core.exceptions.FieldError: Local field 'groups' in class 'Member' clashes with field of similar name from base class 'PermissionMixin'
Run Code Online (Sandbox Code Playgroud)
如您所见,此错误确实解释了发生了什么.
在我看来,这是一个巨大的差异:)
归档时间: |
|
查看次数: |
47341 次 |
最近记录: |