【发布时间】:2010-03-23 15:30:39
【问题描述】:
我想以编程方式向 Django 模型添加属性。在类创建时(模型类的定义时)。之后模型在运行时不会改变。例如,假设我想定义一个Car 模型类,并希望在给定货币列表的情况下为每种货币添加一个price 属性(数据库列)。 (这个货币列表应该被认为是一个不会改变运行时的常量。我不想要这些价格的相关模型。)
最好的方法是什么?
我有一个我认为可行的方法,但它并不完全正确。这就是我尝试这样做的方式,使用上面的汽车示例:
from django.db import models
class Car(models.Model):
name = models.CharField(max_length=50)
currencies = ['EUR', 'USD']
for currency in currencies:
Car.add_to_class('price_%s' % currency.lower(), models.IntegerField())
乍一看,这确实很有效:
$ ./manage.py syncdb
Creating table shop_car
$ ./manage.py dbshell
shop=# \d shop_car
Table "public.shop_car"
Column | Type | Modifiers
-----------+-----------------------+-------------------------------------------------------
id | integer | not null default nextval('shop_car_id_seq'::regclass)
name | character varying(50) | not null
price_eur | integer | not null
price_usd | integer | not null
Indexes:
"shop_car_pkey" PRIMARY KEY, btree (id)
但是当我尝试创建一辆新汽车时,它不再起作用了:
>>> from shop.models import Car
>>> mycar = Car(name='VW Jetta', price_eur=100, price_usd=130)
>>> mycar
<Car: Car object>
>>> mycar.save()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/django/db/models/base.py", line 410, in save
self.save_base(force_insert=force_insert, force_update=force_update)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/django/db/models/base.py", line 495, in save_base
result = manager._insert(values, return_id=update_pk)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/django/db/models/manager.py", line 177, in _insert
return insert_query(self.model, values, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/django/db/models/query.py", line 1087, in insert_query
return query.execute_sql(return_id)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/django/db/models/sql/subqueries.py", line 320, in execute_sql
cursor = super(InsertQuery, self).execute_sql(None)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/django/db/models/sql/query.py", line 2369, in execute_sql
cursor.execute(sql, params)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/django/db/backends/util.py", line 19, in execute
return self.cursor.execute(sql, params)
ProgrammingError: column "price_eur" specified more than once
LINE 1: ...NTO "shop_car" ("name", "price_eur", "price_usd", "price_eur...
^
但显然,我的代码似乎运行了多次,导致“price_eur”属性被添加了多次。
评论:最初我使用“在运行时”的措辞(“我想在运行时以编程方式向 Django 模型添加属性。”)。这个措辞不是最好的。我真正想要的是在“模型定义时间”或“类创建时间”添加这些字段。
【问题讨论】:
-
在相关说明中 - 我知道以这种方式以编程方式添加字段很丑陋。更“漂亮”的方式是使用相关模型。但这不是这里的问题,因为在这种情况下增加数据库复杂性和降低性能根本不值得。
-
“性能降低”?你量过吗?您将很难看到这种完全匹配关系连接的效果。
-
@S.Lott:是的。我没有准确测量过这种特殊情况,但我有一些大型数据集的示例(在连接的一侧),其中额外的 SQL 连接只是某些查询中的大性能问题。当然,您可能是对的,在这种特殊情况下,它可能没有那么大的影响。
-
这不是一个大数据集。这是几种不同货币的价格。试试看。很容易用假数据来装配这两个模型并获得性能数据。通常,获得性能数据比探索棘手、微妙的代码更有价值。
标签: python django django-models