【问题标题】:How does a model relate to another model via Foreignkey?一个模型如何通过外键与另一个模型相关联?
【发布时间】:2012-05-02 14:59:23
【问题描述】:

所以我一直在网上浏览了一下,但我找不到我要找的东西。首先说我有

class Contact(models.Model):
    nickname = models.CharField(max_length=25)
    number = models.CharField(max_length=25)
    note = models.TextField()

class Telephone(models.Model):
    contact = models.ForeignKey('Contact')

那么我将如何保存昵称/号码/不,然后能够根据我可以给他们所有的标签找到所有这些?

假设我希望当我使用 Telephone.objects.filter(contact=jill) 时,将提供基于 jill 实例的所有信息?如果我希望能够编辑吉尔并通过不同的保存给她多个号码,这可能吗? (但吉尔不是她的昵称,它是我放在那里的标签。)有点不好的例子,但说我只想通过一些可通过电话过滤的命名实例找到联系人中的所有信息,这可能吗?还是外键不是我要找的?

【问题讨论】:

  • 您通过Django Tutorial 工作了吗?它做得很好,可以让您很好地了解 ForeignKeys(和其他东西)是如何工作的。
  • 我有'ish'我的意思是我最初是这样做的,但是当我这样做时,我没有任何即时需要使用外键,所以我或多或少只是浏览了这些部分。我得回去再读一遍。
  • 是的,只是看了看,并没有说太多。但是,我开始认为外键不是我需要使用的,但这并不能真正解决我的问题,因为它只是给了我一个新的

标签: python django model foreign-key-relationship


【解决方案1】:
Telephone.objects.filter(contact__nickname='jill')

documentation on making queries

 what if i wanted to be able to edit jill and give her more than one number via
 different saves is this possible?

是的。要在联系人对象中提供多个电话号码,有两种方法 - 通过ForeignKey 的一对一关系,或多对多关系。我建议你通读文档中的models topic

编辑

您可以在模型布局中的每次保存中为 Jill 提供多个电话号码。

假设 Jill 有一条新线路,因此您想添加一个新电话号码。按照你现在的结构,你首先必须在通讯录中找到“Jill”,然后给她一个新的电话号码:

jill = Contact.objects.get(nickname='jill') # assuming you only have one jill
new_num = Telephone.objects.create(contact=jill,number=5551212)

现在,如果您想要 Jill 的所有联系人,您可以:

call_jill = Telephone.objects.filter(contact=jill) # if you already pulled jill
call_jill = Telephone.objects.filter(contact__nickname='jill')

另一种方法是使用ManyToMany

   class Telephone(models.Model):
      number = models.PhoneNumberField()

   class Contact(models.Model):
      # your normal fields
      phones = models.ManyToMany(Telephone)

现在,你可以这样做了:

   jills_phones = Contact.objects.get(nickname='jill').phones.all()

添加新手机:

   jill = Contact.objects.get(nickname='jill')
   jill.phones.add(Telephone.objects.create(number=5551212))
   jill.save()

你也可以反过来,找出这是谁的手机:

   phone = Telephone.objects.get(number=5551212)
   whose_is_it = phone.contact_set.all()

那么有什么区别呢?

它们听起来很相似,但差异很微妙。一个简单的类比很容易。一个制造商可以拥有多辆汽车,但一辆汽车只能拥有一个制造商 - 这是汽车和制造商之间的一对一关系。

一个披萨可以有很多配料,每个配料可以放在多个披萨上。在这种情况下,Pizza 与 Toppings 有 ManyToMany 关系。

您可能认为我可以使用ForeignKey 来做到这一点。你是对的,但考虑一下这种情况:

假设您开始时没有浇头。因此,您将橄榄制作为浇头,然后将其添加到比萨饼中。太好了。

现在您希望同样的比萨饼也有青椒。现在你被卡住了,因为一个披萨只能有一个浇头(由于ForeignKey)。

因此,您最终创建了第三个模型,其中包含对比萨饼和浇头的引用。因此,您无需在比萨饼上添加配料,而是将它们放在另一个模型上:

class Pizza(models.Model):
   topping = models.ForeignKey('Topping')

class Topping(models.Model):
   name = models.CharField(max_length=100)

class AssembledPizza(models.Model):
   topping = models.ForeignKey('Topping')
   pizza = models.ForeignKey('Pizza')

但是,如果您使用 ManyToMany 以正确的方式进行操作,您将拥有:

class Pizza(models.Model):
   toppings = models.ManyToMany('Topping')

class Topping(models.Model):
   name = models.CharField(max_length=100)

那么你会这样做:

在这里,我假设您是一家新餐厅并且没有浇头。有关更多信息,请参阅create 的文档。

veggie = Pizza()
veggie.toppings.add(Topping.objects.create(name='Olives'))
veggie.toppings.add(Topping.objects.create(name='Peppers'))
veggie.save()

我希望这能澄清一点。

【讨论】:

  • 好的,但是我怎样才能从 jill 那里得到所有的数字呢?
  • 这就是第一行 Telephone.objects.filter(contact__nickname='jill') 所做的。
  • 所以我假设它获取了“吉尔”的所有信息?那么我怎么能过滤掉它,让它只有数字,没有音符,也没有 dict 键说这是吉尔?假设它是一本字典?
  • 要获取有关“联系”模型中的“吉尔”的信息,您必须首先过滤该jill = Contact.objects.filter(nickname='jill')。然后你必须得到那个型号的电话。请参阅我的更新答案。
  • 我想我还有一个问题。为什么要使用与电话链接的多对多字段,您可以在 Contact 中包含 number = models.PhoneNumberField(),然后调用 jills_phones = Contact.objects.get(nickname='jill').number.all()?我想还有其他事情我没有考虑,但在这方面它似乎是多余的
猜你喜欢
  • 2017-06-18
  • 2022-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多