我想定义一组模型/对象,允许一个表示关系:field_set有许多字段,其中字段是django.db.model字段对象(IPAddressField,FilePathField等)。
我的目标是拥有支持以下类型的'api'的ORM模型。
从控制器视图中可以说:
# Desired api below
def homepage(request):
from mymodels.models import ProfileGroup, FieldSet, Field
group = ProfileGroup()
group.name = 'Profile Information'
group.save()
geographicFieldSet = FieldSet()
# Bind this 'field set' to the 'profile group'
geographicFieldSet.profilegroup = group
address_field = Field()
address_field.name = 'Street Address'
address_field.f = models.CharField(max_length=100)
# Bind this field to the geo field set
address_field.fieldset = geographicFieldSet
town_field = Field()
town_field.name = 'Town / City'
town_field.f = models.CharField(max_length=100)
# Bind this field to the geo field set
town_field.fieldset = geographicFieldSet
demographicFieldSet = FieldSet()
demographicFieldSet.profilegroup = group
age_field = Field()
age_field.name = 'Age'
age_field.f = models.IntegerField()
# Bind this field to the demo field set
age_field.fieldset = demographicFieldSet
# Define a 'weight_field' here similar to 'age' above.
for obj in [geographicFieldSet, town_field, address_field,
demographicFieldSet, age_field, weight_field]:
obj.save()
# Id also add some methods to these model objects so that they
# know how to render themselves on the page...
return render_to_response('page.templ', {'profile_group':group})
基本上我想支持'逻辑分组的字段',因为我看到自己支持许多不同类型的“字段集”,因此我希望有意义的抽象。
我想定义这个模型,以便我可以定义一组字段,其中字段数是任意的,字段类型也是如此。所以我可能有一个字段组'Geographic',其中包括字段'State'(CharField w / choices),'Town'(TextField)等。
到目前为止,我想出了什么:
class ProfileGroup(models.Model):
name = models.CharField(max_length=200)
# FieldSets have many Fields
class FieldSet(models.Model):
name = models.CharField(max_length=200)
profilegroup = models.ForeignKey(ProfileGroup)
class Field(models.Model):
f = models.Field()
fieldset = models.ForeignKey(FieldSet)
虽然使用这些模型会在shell中产生错误,但最终不允许我存储任意字段。
In [1]: from splink.profile_accumulator.models import Field, FieldSet, ProfileGroup
In [2]: import django.db
In [3]: profile_group = ProfileGroup()
In [4]: profile_group.name = 'profile group name'
In [5]: profile_group.save()
In [6]: field_set = FieldSet()
In [7]: field_set.name = 'field set name'
In [8]: field_set.profilegroup = profile_group
In [9]: field_set.save()
In [10]: field = Field()
In [11]: field.name = 'field name'
In [12]: field.f = django.db.models.FileField()
In [13]: field.save()
---------------------------------------------------------------------------
ProgrammingError Traceback (most recent call last)
/var/www/splinkpage.com/splinkpage.pinax/splink/<ipython console> in <module>()
/usr/lib/pymodules/python2.5/django/db/models/base.pyc in save(self, force_insert, force_update)
309 raise ValueError("Cannot force both insert and updating in "
310 "model saving.")
--> 311 self.save_base(force_insert=force_insert, force_update=force_update)
312
313 save.alters_data = True
/usr/lib/pymodules/python2.5/django/db/models/base.pyc in save_base(self, raw, cls, force_insert, force_update)
381 if values:
382 # Create a new record.
--> 383 result = manager._insert(values, return_id=update_pk)
384 else:
385 # Create a new record with defaults for everything.
/usr/lib/pymodules/python2.5/django/db/models/manager.pyc in _insert(self, values, **kwargs)
136
137 def _insert(self, values, **kwargs):
--> 138 return insert_query(self.model, values, **kwargs)
139
140 def _update(self, values, **kwargs):
/usr/lib/pymodules/python2.5/django/db/models/query.pyc in insert_query(model, values, return_id, raw_values)
890 part of the public API.
891 """
892 query = sql.InsertQuery(model, connection)
893 query.insert_values(values, raw_values)
--> 894 return query.execute_sql(return_id)
/usr/lib/pymodules/python2.5/django/db/models/sql/subqueries.pyc in execute_sql(self, return_id)
307
308 def execute_sql(self, return_id=False):
--> 309 cursor = super(InsertQuery, self).execute_sql(None)
310 if return_id:
311 return self.connection.ops.last_insert_id(cursor,
/usr/lib/pymodules/python2.5/django/db/models/sql/query.pyc in execute_sql(self, result_type)
1732
1733 cursor = self.connection.cursor()
-> 1734 cursor.execute(sql, params)
1735
1736 if not result_type:
/usr/lib/pymodules/python2.5/django/db/backends/util.pyc in execute(self, sql, params)
17 start = time()
18 try:
---> 19 return self.cursor.execute(sql, params)
20 finally:
21 stop = time()
ProgrammingError: can't adapt
所以我想知道这是完全错误的方法,还是我需要使用django的模型类来获得我想要的东西。
答案 0 :(得分:1)
我发现代码有几个问题。首先,使用此类定义:
class Field(models.Model):
f = models.Field()
fieldset = models.ForeignKey(FieldSet)
类models.Field不应该直接用于字段定义。它是Django中所有字段类型的基类,因此缺少特定字段类型的特定功能。
第二个问题是以下一行:
In [12]: field.f = django.db.models.FileField()
当您分配f
实例的属性Field
时,您应该提供要保存到数据库的特定值。例如,如果您使用CharField
进行Field.f
定义,则可以在此处指定字符串。 models.Field
没有特定的可分配值。您正在尝试分配一些明显无法保存到数据库的内容。这是modles.FileField
定义。
因此,由于两个原因,Django很难“调整”您分配给字段属性的值。首先,没有为models.Field
类型定义的值,因为它是“抽象类”,或者是特定字段类型定义的基类。其次,您不能将“字段定义”分配给属性,并希望将其保存到数据库。
我理解你的困惑。从DB和Django的角度来看,你基本上都在尝试做不可能的事情。
我想虽然可以解决您的设计问题。如果你详细描述了你想要实现的目标,那么有人可能会给你一个提示。
答案 1 :(得分:0)
在SQL中,不存在具有可变列数或变量类型列的表。另外,据我所知,Django不会在运行时修改数据库布局 - 即不会调用ALTER TABLE
语句。
在django中,必须在运行应用程序之前完全定义数据模型。
您可能会发现this doc page与“多对一”关系的使用相关。
示例:
#profile
class ProfileGroup(models.Model):
...
#fieldset
class FieldSet(models.Model):
profile = models.ForeignKey(ProfileGroup)
#field 1
class Address(models.Model)
owner = models.ForeignKey(FieldSet,related_name='address')
#related name above adds accessor function address_set to Profile
#more fields like street address, zip code, etc
#field 2
class Interest(models.Model)
owner = models.ForeignKey(FieldSet,related_name='interest')
description = models.CharField()
#etc.
填充并访问字段:
f = FieldSet()
f.interest_set.create(description='ping pong')
f.address_set.create(street='... ', zip='... ')
f.save()
addresses = f.address_set.all()
interests = f.interest_set.all()
#there are other methods to work with sets
在这种情况下,设置模拟表Profile中的变量字段。但是,在数据库中,兴趣和地址数据存储在单独的表中,其中包含指向Profile的外键链接。
如果你想访问具有一个访问者功能的所有内容 - 你可以写一些包含所有相关集的调用。
即使您无法动态修改模型,也可以添加新模型然后发出
manage.py syncdb
这将在db中创建新表。但是,您将无法使用“syncdb”修改现有表中的字段 - django不会这样做。您必须手动输入SQL命令。 (据说web2py平台会自动处理这个,但遗憾的是web2py还没有很好的文档记录,但它在API的质量方面可能会超过django,值得一看)
答案 2 :(得分:0)
为什么不这样做?
class Info(models.Model):
info_type = models.ForeignKey('InfoType', blank=False, null=False, default='')
info_int = models.IntegerField(null=True, blank=True)
info_img = models.ImageField(upload_to='info',null=True, blank=True)
info_date = models.DateTimeField(null=True, blank=True)
info_text = models.TextField(null=True, blank=True)
info_bool = models.BooleanField(null=True, blank=True)
info_char = models.CharField(max_length=128,null=True, blank=True)
info_dec = models.DecimalField(max_digits=20, decimal_places=12, null=True, blank=True)
info_float = models.FloatField(null=True, blank=True)
parent_info = models.ForeignKey('self', blank=True, null=True)
class InfoType(models.Model):
type = models.CharField(max_length=64, blank=False, null=False, default='')
info_field = models.CharField(max_length=32, blank=False, null=False, default='')
因此,根据我们选择的类型,我们知道在哪个字段中我们可以找到值