[英]Get and set ForeignKey directly in Django
我正在尝试使用从具有复合外键的mysql数据库创建的Django模型。
我的models.py
像这样。
class Make(models.Model):
idmake = models.IntegerField(primary_key=True)
make = models.CharField(max_length=20L, unique=True, blank=True)
def __unicode__(self):
return self.make
class Meta:
db_table = 'make'
class Models(models.Model):
idmodels = models.IntegerField(primary_key=True, unique=True)
make = models.ForeignKey(Make, db_column='make', to_field='make')
model = models.CharField(max_length=45L, unique=True)
resource_type = models.CharField(max_length=7L)
def __unicode__(self):
return self.model
class Meta:
db_table = 'models'
class Systems(models.Model):
idsystems = models.IntegerField(primary_key=True, unique=True)
make = models.ForeignKey(Models, null=True, db_column='make', blank=True, related_name='system_make')
model = models.ForeignKey(Models, null=True, db_column='model', to_field = 'model', blank=True, related_name='system_model')
serial_num = models.CharField(max_length=45L, blank=True)
service_tag = models.CharField(max_length=45L, blank=True)
mac = models.CharField(max_length=45L, unique=True)
现在,当我尝试访问Systems的make
字段时,出现ValueError
。
>>> s = Systems.objects.get(pk=1)
>>> s.model
<Models: model11>
>>> s.model.make
<Make: make1>
>>> s.make
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/lib/python2.7/site-packages/django/db/models/fields/related.py", line 384, in __get__
rel_obj = qs.get(**params)
File "/usr/lib/python2.7/site-packages/django/db/models/query.py", line 395, in get
clone = self.filter(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/django/db/models/query.py", line 669, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/usr/lib/python2.7/site-packages/django/db/models/query.py", line 687, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/usr/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1271, in add_q
can_reuse=used_aliases, force_having=force_having)
File "/usr/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1202, in add_filter
connector)
File "/usr/lib/python2.7/site-packages/django/db/models/sql/where.py", line 71, in add
value = obj.prepare(lookup_type, value)
File "/usr/lib/python2.7/site-packages/django/db/models/sql/where.py", line 339, in prepare
return self.field.get_prep_lookup(lookup_type, value)
File "/usr/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 1003, in get_prep_lookup
return super(IntegerField, self).get_prep_lookup(lookup_type, value)
File "/usr/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 322, in get_prep_lookup
return self.get_prep_value(value)
File "/usr/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 997, in get_prep_value
return int(value)
ValueError: invalid literal for int() with base 10: 'make1'
我不允许更改数据库中的表和关系。 我是Django的新手,我无法找出解决此问题的正确方法。 基本上,我希望能够直接获取和设置Systems
模型的make
字段。 有人可以指导我如何去做吗? 我最初的想法是我必须创建一个自定义的ForeignKey
字段。
我怀疑您的代码与您的数据库架构不匹配。 在这一行:
make = models.ForeignKey(Models, null=True, db_column='make', blank=True, related_name='system_make')
Models
应该是Make
,不是吗? 而且您的Systems.model
具有to_field = 'model'
,您是否错过了Systems.make
to_field='make'
? 我建议您删除整个数据库,运行syncdb
并再次创建测试数据。 然后查看错误是否仍然发生。
您的代码的更多提示:
如您定义的to_field = 'model'
和to_field='make'
,您最好考虑为make
和model
字段添加db_index=True
。 否则,当数据集很大时,查询性能可能会很差
如果要将Make.make
和Models.model
设置为唯一并建立索引,则它们似乎已被视为主键。 在您的情况下,真的需要idmake
和idmodels
吗?
primary_key=True
保证唯一。 unique=True
多余的
Django转换使用单数形式定义模型。 即,使用Model
System
,而不是Models
Systems
。 另外,通常我们使用id
而不是idmake
idmodels
。 这些只是转换,由您决定
我发现了答案,而不是偶然。 愿意分享给面临类似问题的任何人。 直接从Systems
访问make
>>> s = Systems.objects.get(pk=1)
>>> s.model
<Models: model11>
>>> s.model.make
<Make: make1>
>>> s.make_id
u'make1'
直接从Systems
对象设置make
>>> s.make_id = Models.objects.get(model='model21').make.make
>>> s.save()
>>> s.make_id
u'make2'
被警告。 如果Models的get方法返回多个模型对象或不返回任何模型对象,则此方法将无效。 例如,如果我的Models
表为:
然后
>>>> Models.objects.get(model='unknown').make.make
Traceback (most recent call last):
....
MultipleObjectsReturned: get() returned more than one Models -- it returned 2!
>>> Models.objects.get(model='not known').make.make
Traceback (most recent call last):
....
DoesNotExist: Models matching query does not exist.
我倒是程序员需要对这些事情保持谨慎。
编辑从@ZZY的评论到这个答案以及他自己的答案
class Models(models.Model):
idmodels = models.IntegerField(primary_key=True, unique=True)
make = models.ForeignKey(Make, db_column='make', to_field='make')
model = models.CharField(max_length=45L, unique=True)
resource_type = models.CharField(max_length=7L)
def __unicode__(self):
return self.model
class Meta:
db_table = 'models'
unique_together = ("make", "model")
而且还因为model
在现场Models
是独一无二的,应该不会出现在正确的表格由我描述的场景
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.