Django中的OneToOne,ManyToMany和ForeignKey字段有什么区别? [英] Whats the difference between a OneToOne, ManyToMany, and a ForeignKey Field in Django?

查看:255
本文介绍了Django中的OneToOne,ManyToMany和ForeignKey字段有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Django模型中,我有点难以理解关系。有人可以解释OneToOne,ManyToMany和ForeignKey之间有什么不同吗?

解决方案那么,这里有两个问题:


  1. 一对一,多对多许多和外键关系

  2. 它们与Django有什么不同。

这两个问题都可以通过简单的Google搜索轻松解决,但是由于我无法在SO上找到这个问题的确切答案,我会继续前进,并回答。

请注意,在Django中,关系只能在关系的一边定义。






ForeignKey



外键关系通常称为多对一关系。请注意,这种关系的反向是一对多的(Django提供了访问工具)。顾名思义,许多对象可能与一个对象有关。

  Person<  - >出生地

在这个例子中,一个人可能只有一个出生地,但一个出生地可能与许多人。我们来看看Django中的这个例子。假设这些是我们的模型:
$ b $ pre $ 类Birthplace(models.Model):
city = models.CharField(max_length = 75)
state = models.CharField(max_length = 25)

def __unicode __(self):
return.join(self.city,,,self。状态)

类Person(models.Model):
name = models.CharField(max_length = 50)
birthplace = models.ForeignKey(出生地)

def __unicode __(self):
return self.name

你可以看到没有关系在 Birthplace 模型中定义, Person 模型。假设我们创建了以下模型(显然不是Python语法):
$ b $ ul

  • 出生地:Texas,Dallas

  • 出生地:纽约纽约市

  • 个人:约翰·史密斯出生地:(美国得克萨斯州达拉斯)
  • 出生地:(得克萨斯州达拉斯)

  • 个人:Daniel Lee,出生地:(纽约市,纽约)


    现在我们可以看到Django如何使用这些关系(请注意, ./ manage.py shell 是您的朋友!):

     >> from somewhere.models import Birthplace,Person 
    >> Person.objects.all()
    [< Person:John Smith>,< Person:Maria Lee>,< Person:Daniel Lee>]
    >> Birthplace.objects.all()
    [< Birthplace:Dallas,Texas>,< Birthplace:New York City,New York>]

    您可以看到我们创建的模型。现在让我们来看看某个人的出生地:

     >> person = Person.object.get(name =John Smith)
    >>人。出生地
    <出生地:得克萨斯州达拉斯>
    >> person.birthplace.city
    达拉斯

    假设您想查看所有给定的人出生地。正如我刚才所说,Django允许你访问反向关系。默认情况下,Django创建一个管理器(< model> _set ,其中<> RelatedManager ) code $< model>< / code>是您的小型名称。

     >> ; place = Birthplace.objects.get(city =Dallas)
    >> place.person_set.all()
    [< Person:John Smith>,< Person:Maria Lee>]

    请注意,我们可以通过在模型关系中设置 related_name 关键字参数来更改此管理器的名称。因此,我们将 Person 模型中的 birthplace 字段更改为:

      birthplace = models.ForeignKey(Birthplace,related_name =people)

    现在,我们可以用一个漂亮的名字来访问这个反向关系:

     >> place.people.all()
    [< Person:John Smith>,< Person:Maria Lee>]






    一对一



    一对一关系非常相似多对一的关系,除了限制两个对象具有唯一的关系。一个例子是一个用户和一个配置文件(它存储关于用户的信息)。没有两个用户共享相同的配置文件。让我们看看在Django这个。我不打算定义用户模型,因为Django为我们定义了它。但请注意,Django建议使用 django.contrib.auth.get_user_model()来导入用户,这就是我们要做的。 profile模型可以定义如下:

    $ p $ class Profile(models.Model):
    user = models.OneToOneField (settings.AUTH_USER_MODEL)#请注意,Django建议从关系定义的设置中获取用户
    fruit = models.CharField(max_length = 50,help_text =Favorite Fruit)
    facebook = models.CharField( (self.fruit,,self.facebook)
    (自我):
    return $b



    $

    所有我们需要的是一个拥有配置文件的用户在shell中测试这个:




    • 用户:johndt6

    • 用户:johndt6,Kiwi,blah_blah / ul>

      现在,您可以轻松地从User模型访问用户的个人资料:

       >> user = User.objects.all()[0] 
      >> user.username
      johndt6
      >> user.profile
      < Profile:Kiwi blah_blah>
      >> user.profile.fruit
      Kiwi
      >> profile = Profile.objects.get(user = user)
      >> profile.user
      < User:johndt6>

      当然,您可以使用 related_name自定义反向关系的名称






      多对多



      多对多的关系可能有点棘手。我首先要说的是,多对多的领域是混乱的,应尽可能地避免。鉴于此,在许多情况下,多对多关系是合理的。



      两个模型之间的多对多关系定义为零,一或第一模型的更多对象可能与第二模型的零个,一个或多个对象有关。举一个例子,让我们设想一个公司,通过项目来定义他们的工作流程。一个项目可能与没有订单,只有一个订单或许多订单有关。一个订单可能与没有项目,一个项目或许多有关。让我们定义我们的模型,如下所示:

      $ p $ class Order(models.Model):
      product = models.CharField(max_length = 150)#请注意,在现实中,这可能会更好地服务于一个产品模型
      customer = models.CharField(max_length = 150)#客户也可以这样说

      def __unicode __(self):
      return.join(self.productfor,self.customer)

      class Project(models.Model):
      orders = models .ManyToManyField(Order)

      def __unicode __(self):
      return.join(Project,str(self.id))

      请注意,Django会为订单创建 RelatedManager
      $ b

      让我们创建下面的对象(用我不一致的语法!):

      $>
      $ b


      • 订单:宇宙飞船,美国航空航天局

      • 订购:赛车,NASCAR
        项目:订单:[]

      • 项目:订单:[(订单:Spaceship,NASA)]订单:[(Order:Spaceship,NASA),(Order:Race car,NASCAR)]


      我们可以如下访问这些关系:

       >> Project.objects.all()
      [< Project:Project 0>,< Project:Project 1>,< Project:Project 2>]
      >> for proj in Project.objects.all():
      .. print(proj)
      .. proj.orders.all()#注意我们必须访问`orders`
      .. ()
      项目0
      []

      项目1
      [<命令:NASA的太空船>> ;]

      Project 2
      [< Order:Spaceship for NASA>,< Order:Race car for NASC>]

      请注意,美国航空航天局的订单与2个项目有关,而美国海军的订单与无关。另外请注意,一个项目没有订单,一个有多个。



      我们也可以像以前一样访问关系:

       >> order = Order.objects.filter(customer =NASA)[0] 
      >> order.project_set.all()
      [< Project:Project 0>,< Project:Project 2>]






      资源



      对数据库关系的很好的解释由@MarcB提供

      基数维基百科

      Django文档:



      models.ForeignKey

      models.OneToOneField



      models.ManyToManyField



      一对一关系 a>



      多对多的关系


      I'm having a little difficulty getting my head around relationships in Django models.

      Could someone explain what the difference is between a OneToOne, ManyToMany and ForeignKey?

      解决方案

      Well, there's essentially two questions here:

      1. What is the difference (in general) between one to one, many to many, and foreign key relations
      2. What are their differences specific to Django.

      Both of these questions are quite easily answered through a simple Google search, but as I cannot find an exact dupe of this question on SO, I'll go ahead and answer.

      Note that in Django, relationships should only be defined on one side of the relationship.


      ForeignKey

      A foreign key relationship is generally known as a many-to-one relationship. Note that the reverse of this relationship is one-to-many (which Django provides tools to access). As the name implies, many objects may be related to one.

      Person <--> Birthplace
      

      In this example, a person may only have one birthplace, but a birthplace may be related to many people. Let's look at this example in Django. Say these are our models:

      class Birthplace(models.Model):
          city = models.CharField(max_length=75)
          state = models.CharField(max_length=25)
      
          def __unicode__(self):
              return "".join(self.city, ", ", self.state)
      
      class Person(models.Model):
          name = models.CharField(max_length=50)
          birthplace = models.ForeignKey(Birthplace)
      
          def __unicode__(self):
              return self.name
      

      You can see that no relations are defined within the Birthplace model, and a ForeignKey relationship is defined within the Person model. Say that we create the following models (obviously not in Python syntax):

      • Birthplace: Dallas, Texas
      • Birthplace: New York City, New York
      • Person: John Smith, Birthplace : (Dallas, Texas)
      • Person: Maria Lee, Birthplace : (Dallas, Texas)
      • Person: Daniel Lee, Birthplace : (New York City, New York)

      Now we can see how Django lets us use these relations (note that the ./manage.py shell is your friend!):

      >> from somewhere.models import Birthplace, Person
      >> Person.objects.all()
      [<Person: John Smith>, <Person: Maria Lee>, <Person: Daniel Lee>]
      >> Birthplace.objects.all()
      [<Birthplace: Dallas, Texas>, <Birthplace: New York City, New York>]
      

      You can see our created models. Now let's checkout someone's birthplace:

      >> person = Person.object.get(name="John Smith")
      >> person.birthplace
      <Birthplace: Dallas, Texas>
      >> person.birthplace.city
      Dallas
      

      Let's say you want to see all people with a given birthplace. As I said earlier, Django allows you to access reverse relations. By default, Django creates a manager (RelatedManager) on your model to handle this, named <model>_set, where <model> is your model name in lowercase.

      >> place = Birthplace.objects.get(city="Dallas")
      >> place.person_set.all()
      [<Person: John Smith>, <Person: Maria Lee>]
      

      Note that we can change the name of this manager by setting the related_name keyword argument in our model relation. So, we would change the birthplace field in the Person model to:

      birthplace = models.ForeignKey(Birthplace, related_name="people")
      

      Now, we can access that reverse relationship with a pretty name:

      >> place.people.all()
      [<Person: John Smith>, <Person: Maria Lee>]
      


      One-to-one

      A one-to-one relationship is quite similar to a many-to-one relationship, except that it restricts two objects to having a unique relationship. An example of this would be a User and a Profile (which stores information about the user). No two users share the same profile. Let's look at this in Django. I won't bother to define the user model, as Django defines it for us. Do note, however, that Django suggests using django.contrib.auth.get_user_model() to import the user, so that's what we'll do. The profile model may be defined as follows:

      class Profile(models.Model):
          user = models.OneToOneField(settings.AUTH_USER_MODEL) # Note that Django suggests getting the User from the settings for relationship definitions
          fruit = models.CharField(max_length=50, help_text="Favorite Fruit")
          facebook = models.CharField(max_length=100, help_text="Facebook Username")
      
          def __unicode__(self):
              return "".join(self.fruit, " ", self.facebook)
      

      All we need is one user with a profile to test this out in the shell:

      • User: johndt6
      • Profile: user : johndt6, "Kiwi", "blah_blah"

      Now you may easily access the user's profile from the User model:

      >> user = User.objects.all()[0]
      >> user.username
      johndt6
      >> user.profile
      <Profile: Kiwi blah_blah>
      >> user.profile.fruit
      Kiwi
      >> profile = Profile.objects.get(user=user)
      >> profile.user
      <User: johndt6>
      

      Of course, you may customize the name of the reverse relation using the related_name argument as above.


      Many-to-many

      Many-to-many relationships can be a bit tricky. Let me start by saying that many-to-many fields are messy, and should be avoided when possible. Given that, there are plenty of situations where a many-to-many relationship makes sense.

      A many-to-many relationship between two models defines that zero, one or more objects of the first model may be related to zero, one or more objects of the second model. As an example, let's envision a company that defines their workflow through projects. A project may be related to no orders, only one order, or many orders. An order may be related to no projects, one project, or many. Let's define our models as so:

      class Order(models.Model):
          product = models.CharField(max_length=150)  # Note that in reality, this would probably be better served by a Product model
          customer = models.CharField(max_length=150)  # The same may be said for customers
      
          def __unicode__(self):
              return "".join(self.product, " for ", self.customer)
      
      class Project(models.Model):
          orders = models.ManyToManyField(Order)
      
          def __unicode__(self):
              return "".join("Project ", str(self.id))
      

      Note that Django will create a RelatedManager for the orders field to access the many-to-many relationship.

      Let's create the following objects (in my inconsistent syntax!):

      • Order: "Spaceship", "NASA"
      • Order: "Submarine", "US Navy"
      • Order: "Race car", "NASCAR"
      • Project: orders: []
      • Project: orders: [(Order: "Spaceship", "NASA")]
      • Project: orders: [(Order: "Spaceship", "NASA"), (Order: "Race car", "NASCAR")]

      We can access these relationships as follows:

      >> Project.objects.all()
      [<Project: Project 0>, <Project: Project 1>, <Project: Project 2>]
      >> for proj in Project.objects.all():
      ..     print(proj)
      ..     proj.orders.all()  # Note that we must access the `orders`
      ..                        # field through its manager
      ..     print("")
      Project 0
      []
      
      Project 1
      [<Order: Spaceship for NASA>]
      
      Project 2
      [<Order: Spaceship for NASA>, <Order: Race car for NASCAR>]
      

      Note that the NASA order is related to 2 projects, and the US Navy order is related to none. Also note that one project has no orders, and one has multiple.

      We may also access the relationship in reverse in the same way we have before:

      >> order = Order.objects.filter(customer="NASA")[0]
      >> order.project_set.all()
      [<Project: Project 0>, <Project: Project 2>]
      


      Resources

      Good explanation of db relationships provided by @MarcB

      Wikipedia page on Cardinality

      Django Docs:

      models.ForeignKey

      models.OneToOneField

      models.ManyToManyField

      One-to-one Relationships

      Many-to-many Relationships

      这篇关于Django中的OneToOne,ManyToMany和ForeignKey字段有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆