Я хотел бы добавить атрибуты к моделям 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 программно, во время выполнения».). Эта формулировка была не самой лучшей. Я действительно хотел добавить эти поля в «время определения модели» или «время создания класса».