【问题标题】:Mulitple Foriegn keys in same table in Django?Django中同一张表中的多个外键?
【发布时间】:2016-05-14 09:39:46
【问题描述】:

我想在 Django 中创建一个将数据存储在模型中的表单,该模型包含 1) 巴士服务名称 2) 源 3) 目的地 4)trip_distance 和 5)entry_timestamp。

我还想将服务名称、源名称和目标名称保存在单独的数据库表中。因此,用户可以在填写表单时从下拉菜单中选择这些。

class Service(models.Model):
    service_name = models.CharField(max_length = 30)
    entry_timestamp = models.DateTimeField(auto_now_add = True)

    def __unicode__(self):
        return self.service_name

class Source(models.Model):
    source_name = models.CharField(max_length = 30)
    entry_timestamp = models.DateTimeField(auto_now_add = True)

    def __unicode__(self):
        return self.source_name

class Destination(models.Model):
    destination_name = models.CharField(max_length = 30)
    entry_timestamp = models.DateTimeField(auto_now_add = True)

    def __unicode__(self):
        return self.destination_name

class EntryForm(models.Model):
    service= models.ForeignKey(Service)
    source = models.ForeignKey(Source)
    destination = models.ForeignKey(Destination)
    trip_distance = models.PositiveIntegerField()
    entry_timestamp = models.DateTimeField(auto_now_add = True)

class GlobalOption(models.Model):
    config_option = models.CharField(max_length=30)
    value = models.CharField(max_length = 30)

这是我想出的。

现在,当我尝试通过 shell 创建 EntryForm 时,出现以下错误

q = Service.objects.get(pk=1)
>>> q
<Service: Rajasthan Roadways>
q.entryform_set.create(source = 'Midwest',destination = 'Sahara',trip_distance = 10000)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/fields/related.py", line 752, in create
    return super(RelatedManager, self.db_manager(db)).create(**kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 127, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 346, in create
    obj = self.model(**kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 468, in __init__
    setattr(self, field.name, rel_obj)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/fields/related.py", line 635, in __set__
    self.field.rel.to._meta.object_name,
ValueError: Cannot assign "'Midwest'": "EntryForm.source" must be a "Source" instance.

我怎样才能更好地设计这个?我可以通过管理员手动创建 EntryForm 对象,然后它就可以工作了。

在这个 django 教程中,一个类似的行有效并且没有给出这个错误

>>> q = Question.objects.get(pk=1)

# Display any choices from the related object set -- none so far.
>>> q.choice_set.all()
[]

# Create three choices.
>>> q.choice_set.create(choice_text='Not much', votes=0)

为什么我不能类似地创建 EntryForm 对象?我也想要一个表格来将数据保存到这个模型中,我可以命名它吗?

【问题讨论】:

  • 如何解决什么source 字段是 ForeignKey。由于错误状态,您不能分配诸如'Midwest' 之类的字符串。它必须是 Source 对象。您可以首先创建一个Source 对象,然后将其用作EntryForm.source 的值。顺便说一句,将模型命名为 EntryForm 非常令人困惑,因为它不是表单。
  • 是的,但最好将您的模型命名为 Entry 并为实际的 Django Form 类保留名称 EntryForm
  • 我怎样才能更好地设计这些模型?对这个问题进行建模的最佳方法是什么,其中我有一个表用于条目,另外几个表用于源和目标等?
  • 选择字段很简单CharFields,不是 ForeignKeys。我建议你从头开始阅读教程。您的问题(什么是最好的方法...)超出了本网站的范围。

标签: django database-design django-models


【解决方案1】:

在 cmets 中,您询问如何设置模型。您可以将SourceDestination 归为一个模型,称之为Place,因为它们似乎都指的是地点。

class Service(models.Model):
    service_name = models.CharField(max_length = 30)
    entry_timestamp = models.DateTimeField(auto_now_add = True)

    def __unicode__(self):
        return self.service_name

class Place(models.Model):
    source_name = models.CharField(max_length = 30)
    entry_timestamp = models.DateTimeField(auto_now_add = True)

    def __unicode__(self):
        return self.source_name

class Connection(models.Model):
    service= models.ForeignKey(Service, related_name='connections')
    source = models.ForeignKey(Place, related_name='departing_connections')
    destination = models.ForeignKey(Place, related_name='arriving_connections')
    trip_distance = models.PositiveIntegerField()
    entry_timestamp = models.DateTimeField(auto_now_add = True)

只有在您的 Connection 模型中,您才能再次将它们分成 sourcedestination 字段。添加related_name 使其更易于阅读,例如

p = Place.objects.get(pk=1)

from_here = p.departing_connections.all()

this_year = from_here.filter(service__entry_timestamp__year=date.today().year

在添加 Connections 之前,您需要添加 ServicePlace 对象,以便关联的连接。

【讨论】:

  • 那很好。但是,就我的使用而言,永远不会有离开的连接,只有到达的连接。所以我想为源和目标创建一个单独的表,以便用户可以从较小的源和目标列表中进行选择。
猜你喜欢
  • 1970-01-01
  • 2019-02-18
  • 1970-01-01
  • 2013-06-03
  • 1970-01-01
  • 1970-01-01
  • 2016-10-15
  • 1970-01-01
  • 2020-08-05
相关资源
最近更新 更多