Python 在Django,一个一个、多个和一个外国钥匙字段之间有什么区别?

Python 在Django,一个一个、多个和一个外国钥匙字段之间有什么区别?,python,django,many-to-many,foreign-key-relationship,one-to-one,Python,Django,Many To Many,Foreign Key Relationship,One To One,我对Django模型中的关系有点难以理解 有人能解释一下一个一个、多个和外国钥匙之间的区别吗?这里有两个问题: 一对一、多对多和外键关系(一般)有什么区别 他们与Django的具体区别是什么 这两个问题都很容易通过简单的谷歌搜索得到答案,但由于我无法在上面找到这个问题的确切答案,所以我将继续回答 请注意,在Django中,应该只在关系的一侧定义关系 外侨 外键关系通常称为多对一关系。请注意,这种关系的反面是一对多(Django提供了访问工具)。顾名思义,许多对象可能与一个对象相关 Person

我对Django模型中的关系有点难以理解


有人能解释一下一个一个、多个和外国钥匙之间的区别吗?

这里有两个问题:

  • 一对一、多对多和外键关系(一般)有什么区别
  • 他们与Django的具体区别是什么 这两个问题都很容易通过简单的谷歌搜索得到答案,但由于我无法在上面找到这个问题的确切答案,所以我将继续回答

    请注意,在Django中,应该只在关系的一侧定义关系


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

    Person >--| Birthplace
       ^           ^
       |           |
      Many        One 
    
    在本例中,一个人可能只有一个出生地,但一个出生地可能与许多人有关。让我们看看Django中的这个例子。假设这些是我们的模型:

    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
    
    您可以看到,
    出生地
    模型中没有定义任何关系,而
    外键
    关系是在
    个人
    模型中定义的。假设我们创建了以下模型实例(显然不是Python语法):

    • 出生地:德克萨斯州达拉斯
    • 出生地:纽约市,纽约
    • 人:约翰·史密斯,出生地:(德克萨斯州达拉斯)
    • 人:玛丽亚·李,出生地:(德克萨斯州达拉斯)
    • 人物:丹尼尔·李,出生地:(纽约市,纽约)
    现在我们可以看到Django如何使用这些关系(请注意,
    /manage.py shell
    是您的朋友!)

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

    birthplace = models.ForeignKey(Birthplace, related_name="people")
    
    现在,我们可以用一个漂亮的名字来访问这种反向关系:

    >> place.people.all()
    [<Person: John Smith>, <Person: Maria Lee>]
    
    让我们看看这个在Django。我不会费心定义用户模型,因为Django为我们定义了它。但是请注意,Django建议使用
    Django.contrib.auth.get\u user\u model()
    导入用户,因此我们将这样做。剖面模型可定义如下:

    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)
    
    >> 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>]
    
    我们只需要一个拥有配置文件的用户就可以在shell中进行测试:

    • 用户:johndt6
    • 简介:用户:johndt6,“猕猴桃”,“诸如此类”
    现在,您可以从用户模型轻松访问用户配置文件:

    >> 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>
    
    让我们将我们的模型定义为:

    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))
    
    请注意,Django将为
    orders
    字段创建一个
    RelatedManager
    ,以访问多对多关系

    让我们创建模型的以下实例(使用我不一致的语法!):

    • 命令:“宇宙飞船”,“美国宇航局”
    • 命令:“潜艇”,“美国海军”
    • 命令:“赛车”,“纳斯卡”
    • 项目:订单:[]
    • 项目:订单:[(订单:“宇宙飞船”、“NASA”)]
    • 项目:订单:[(订单:“宇宙飞船”、“NASA”),(订单:“赛车”、“NASCAR”)]
    我们可以通过以下方式访问这些关系:

    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)
    
    >> 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>]
    
    因此,可以分别读取关系的每个“边”或方向。把它们挤在一起很方便

    扩展其中一种关系可能更有意义:

                   +---- John Smith
                   |
     Dallas|-------+---- Jane Doe
                   |
                   +---- Joe Smoe
    
    资源 由@MarcB提供

    Django文件:


    这是一个DB概念,并不特定于Django:外键是如何指定这些关系的。我要补充的是,使用
    ManyToManyField
    在数据库中创建一个额外的表,该表将包含3个字段:pk和对连接表的2个引用(表1\u id,表2\u id)
    ManyToManyField
    是标记的最佳选择(例如,如果您想用标记标记特定项目/产品/位置)。以下是ManyToManyField中间表中的文档-。
    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))
    
    >> 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>]
    
    >> order = Order.objects.filter(customer="NASA")[0]
    >> order.project_set.all()
    [<Project: Project 0>, <Project: Project 2>]
    
    A --< B
    A >-- B
    
                   +---- John Smith
                   |
     Dallas|-------+---- Jane Doe
                   |
                   +---- Joe Smoe