{"id":6221,"date":"2022-12-25T02:10:46","date_gmt":"2022-12-25T02:10:46","guid":{"rendered":"https:\/\/www.pythontutorial.net\/?page_id=6221"},"modified":"2023-08-12T09:45:09","modified_gmt":"2023-08-12T09:45:09","slug":"django-one-to-many","status":"publish","type":"page","link":"https:\/\/www.pythontutorial.net\/django-tutorial\/django-one-to-many\/","title":{"rendered":"Django One-To-Many Relationship"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you&#8217;ll learn about one-to-many relationships in Django and how to use the ForeignKey to model them.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='introduction-to-the-django-one-to-many-relationships'>Introduction to the Django one-to-many relationships <a href=\"#introduction-to-the-django-one-to-many-relationships\" class=\"anchor\" id=\"introduction-to-the-django-one-to-many-relationships\" title=\"Anchor for Introduction to the Django one-to-many relationships\">#<\/a><\/h2>\n\n\n\n<p>In a one-to-many relationship, a row in a table is associated with one or more rows in another table. For example, a department may have one or more employees and each employee belongs to one department. <\/p>\n\n\n\n<p>The relationship between departments and employees is a one-to-many relationship. Conversely, the relationship between employees and departments is a many-to-one relationship.<\/p>\n\n\n\n<p>To create a one-to-many relationship in Django, you use <code>ForeignKey<\/code>. For example, the following uses the <code>ForeignKey<\/code> to create a one-to-many relationship between <code>Department<\/code> and <code>Employee<\/code> models:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-code-table\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> django.db <span class=\"hljs-keyword\">import<\/span> models\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Contact<\/span><span class=\"hljs-params\">(models.Model)<\/span>:<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    phone = models.CharField(max_length=<span class=\"hljs-number\">50<\/span>, unique=<span class=\"hljs-literal\">True<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>    address = models.CharField(max_length=<span class=\"hljs-number\">50<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">__str__<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> self.phone\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Department<\/span><span class=\"hljs-params\">(models.Model)<\/span>:<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    name = models.CharField(max_length=<span class=\"hljs-number\">255<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>    description = models.TextField(null=<span class=\"hljs-literal\">True<\/span>, blank=<span class=\"hljs-literal\">True<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">__str__<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> self.name\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Employee<\/span><span class=\"hljs-params\">(models.Model)<\/span>:<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    first_name = models.CharField(max_length=<span class=\"hljs-number\">100<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>    last_name = models.CharField(max_length=<span class=\"hljs-number\">100<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    contact = models.OneToOneField(\n<\/span><\/span><span class='shcb-loc'><span>        Contact,\n<\/span><\/span><span class='shcb-loc'><span>        on_delete=models.CASCADE,\n<\/span><\/span><span class='shcb-loc'><span>        null=<span class=\"hljs-literal\">True<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    )\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><mark class='shcb-loc'><span>    department = models.ForeignKey(\n<\/span><\/mark><mark class='shcb-loc'><span>        Department,\n<\/span><\/mark><mark class='shcb-loc'><span>        on_delete=models.CASCADE\n<\/span><\/mark><mark class='shcb-loc'><span>    )\n<\/span><\/mark><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">__str__<\/span><span class=\"hljs-params\">(self)<\/span>:<\/span>\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">f'<span class=\"hljs-subst\">{self.first_name}<\/span> <span class=\"hljs-subst\">{self.last_name}<\/span>'<\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How it works.<\/p>\n\n\n\n<p>First, define the <code>Department<\/code> model class.<\/p>\n\n\n\n<p>Second, modify the <code>Employee<\/code> class by adding the one-to-many relationship using the <code>ForeignKey<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">department = models.ForeignKey(\n   Department,\n   on_delete=models.CASCADE\n)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the <code>ForeignKey<\/code>, we pass the <code>Department<\/code> as the first argument and the <code>on_delete<\/code> keyword argument as <code>models.CASCADE<\/code>.<\/p>\n\n\n\n<p>The <code>on_delete=models.CASCADE<\/code> indicates that if a department is deleted, all employees associated with the department are also deleted.<\/p>\n\n\n\n<p class=\"note\">Note that you define the <code>ForeignKey<\/code> field in the many-side of the relationship.<\/p>\n\n\n\n<p>Third, <a href=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-migrations\/\">make migrations<\/a> using the <code>makemigrations<\/code> command:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">python manage.py makemigrations<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Django will issue the following message:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">It is impossible to add a non-nullable field 'department' to employee without specifying a default. This is because the database needs something to populate existing rows.\nPlease select a fix:\n 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)\n 2) Quit and manually define a default value in models.py.\nSelect an option:<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the <code>Employee<\/code> model, we define the <code>department<\/code> field as a non-nullable field. Therefore, Django needs a default value to update the <code>department<\/code> field (or <code>department_id<\/code> column) for the existing rows in the database table. <\/p>\n\n\n\n<p>Even if the <code>hr_employees<\/code> table doesn&#8217;t have any rows, Django also requests you to provide a default value.<\/p>\n\n\n\n<p>As clearly shown in the message, Django provides you with two options. You need to enter 1 or 2 to select the corresponding option.<\/p>\n\n\n\n<p>In the first option, Django requests a one-off default value. If you enter 1, then Django will show the Python command line:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">&gt;&gt;&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this case, you can use any valid value in Python e.g., <code><a href=\"https:\/\/www.pythontutorial.net\/advanced-python\/python-none\/\">None<\/a><\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span><span class=\"hljs-literal\">None<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Once you provide a default value, Django will make the migrations like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">Migrations for 'hr':\n  hr\\migrations\\0002_department_employee_department.py\n    - Create model Department\n    - Add field department to employee<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"374\" height=\"144\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2023\/01\/django_orm_employee_department.png\" alt=\"\" class=\"wp-image-6416\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2023\/01\/django_orm_employee_department.png 374w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2023\/01\/django_orm_employee_department-300x116.png 300w\" sizes=\"auto, (max-width: 374px) 100vw, 374px\" \/><\/figure>\n\n\n\n<p>In the database, Django creates the <code>hr_department<\/code> and adds the <code>department_id<\/code> column to the <code>hr_employee<\/code> table. The <code>department_id<\/code> column of the <code>hr_employee<\/code> table links to the <code>id<\/code> column of the <code>hr_department<\/code> table.<\/p>\n\n\n\n<p>If you select the second option by entering the number 2, Django will allow you to manually define the default value for the department field. In this case, you can add a default value to the <code>department<\/code> field in the <code>models.py<\/code> like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-code-table\"><span class='shcb-loc'><span>department = models.ForeignKey(\n<\/span><\/span><span class='shcb-loc'><span>   Department,\n<\/span><\/span><span class='shcb-loc'><span>   on_delete=models.CASCADE,\n<\/span><\/span><mark class='shcb-loc'><span>   default=<span class=\"hljs-literal\">None<\/span>\n<\/span><\/mark><span class='shcb-loc'><span>)\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>After that, you can make the migrations using the <code>makemigrations<\/code> command:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">python manage.py makemigrations<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>It&#8217;ll show the following output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">Migrations for 'hr':\n  hr\\migrations\\0002_department_employee_department.py\n    - Create model Department\n    - Add field department to employee<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If the <code>hr_employee<\/code> table has any rows, you need to remove all of them before migrating the new migrations:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">python<\/span> <span class=\"hljs-selector-tag\">manage<\/span><span class=\"hljs-selector-class\">.py<\/span> <span class=\"hljs-selector-tag\">shell_plus<\/span>\n&gt;&gt;&gt; <span class=\"hljs-selector-tag\">Employee<\/span><span class=\"hljs-selector-class\">.objects<\/span><span class=\"hljs-selector-class\">.all<\/span>()<span class=\"hljs-selector-class\">.delete<\/span>()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Then you can make the changes to the database using the <code>migrate<\/code> command:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">python manage.py migrate<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">Operations to perform:\n  Apply all migrations: admin, auth, contenttypes, hr, sessions\nRunning migrations:\n  Applying hr.0002_department_employee_department... OK<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Another way to deal with this is to reset migrations that we will cover in the reset migrations tutorial.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='interacting-with-models'>Interacting with models <a href=\"#interacting-with-models\" class=\"anchor\" id=\"interacting-with-models\" title=\"Anchor for Interacting with models\">#<\/a><\/h2>\n\n\n\n<p>First, run the <code>shell_plus<\/code> command:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">python manage.py shell_plus<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, create a new department with the name <code>IT<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>d = Department(name=<span class=\"hljs-string\">'IT'<\/span>,description=<span class=\"hljs-string\">'Information Technology'<\/span>)\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>d.save()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Third, create two employees and assign them to the <code>IT<\/code> department:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>e = Employee(first_name=<span class=\"hljs-string\">'John'<\/span>,last_name=<span class=\"hljs-string\">'Doe'<\/span>,department=d)\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>e.save()\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>e = Employee(first_name=<span class=\"hljs-string\">'Jane'<\/span>,last_name=<span class=\"hljs-string\">'Doe'<\/span>,department=d)\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>e.save()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Fourth, access the <code>department<\/code> object from the <code>employee<\/code> object:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>e.department \n&lt;Department: IT&gt;\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>e.department.description\n<span class=\"hljs-string\">'Information Technology'<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Fif,  get all employees of a department using use the <code>employee_set<\/code> attribute like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>d.employee_set.all()\n&lt;QuerySet &#91;&lt;Employee: John Doe&gt;, &lt;Employee: Jane Doe&gt;]&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Note that we did not define the <code>employee_set<\/code> property in the <code>Department<\/code> model. Internally, Django automatically added the <code>employee_set<\/code> property to the <code>Department<\/code> model when we defined the one-to-many relationship using the <code>ForeignKey<\/code>.<\/p>\n\n\n\n<p>The <code>all()<\/code> method of the <code>employee_set<\/code> returns a <code>QuerySet<\/code> that contains all employees who belong to the department.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='using-select_related-to-join-employee-with-department'>Using select_related() to join employee with department <a href=\"#using-select_related-to-join-employee-with-department\" class=\"anchor\" id=\"using-select_related-to-join-employee-with-department\" title=\"Anchor for Using select_related() to join employee with department\">#<\/a><\/h2>\n\n\n\n<p>Exit the <code>shell_plus<\/code> and execute it again. This time we add the <code>--print-sql<\/code> option to display the generated SQL that Django will execute against the database:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">python manage.py shell_plus --print-sql<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The following returns the first employee:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql\">&gt;&gt;&gt; e = Employee.objects.first()\n<span class=\"hljs-keyword\">SELECT<\/span> <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span>,\n       <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"first_name\"<\/span>,\n       <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"last_name\"<\/span>,\n       <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"contact_id\"<\/span>,\n       <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span>\n  <span class=\"hljs-keyword\">FROM<\/span> <span class=\"hljs-string\">\"hr_employee\"<\/span>\n <span class=\"hljs-keyword\">ORDER<\/span> <span class=\"hljs-keyword\">BY<\/span> <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span> <span class=\"hljs-keyword\">ASC<\/span>\n <span class=\"hljs-keyword\">LIMIT<\/span> <span class=\"hljs-number\">1<\/span>\nExecution <span class=\"hljs-built_in\">time<\/span>: <span class=\"hljs-number\">0.003000<\/span>s &#91;<span class=\"hljs-keyword\">Database<\/span>: <span class=\"hljs-keyword\">default<\/span>]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>To access the department of the first employee, you use the <code>department<\/code> attribute:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql\">&gt;&gt;&gt; e.department \n<span class=\"hljs-keyword\">SELECT<\/span> <span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span>,\n       <span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"name\"<\/span>,\n       <span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"description\"<\/span>\n  <span class=\"hljs-keyword\">FROM<\/span> <span class=\"hljs-string\">\"hr_department\"<\/span>\n <span class=\"hljs-keyword\">WHERE<\/span> <span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span> = <span class=\"hljs-number\">1<\/span>\n <span class=\"hljs-keyword\">LIMIT<\/span> <span class=\"hljs-number\">21<\/span>\nExecution <span class=\"hljs-built_in\">time<\/span>: <span class=\"hljs-number\">0.013211<\/span>s &#91;<span class=\"hljs-keyword\">Database<\/span>: <span class=\"hljs-keyword\">default<\/span>]\n&lt;Department: IT&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this case, Django executes two queries. The first query selects the first employee and the second query selects the department of the selected employee.<\/p>\n\n\n\n<p>If you select N employees to display them on a web page, then you need to execute N + 1 query to get both employees and their departments. The first query (1) selects the N employees and the N queries select N departments for each employee. This issue is known as the N + 1 query problem.<\/p>\n\n\n\n<p>To fix the N + 1 query problem, you can use the <code>select_related()<\/code> method to select both employees and departments using a single query. For example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql\">&gt;&gt;&gt; Employee.objects.select_related('department').all()\n<span class=\"hljs-keyword\">SELECT<\/span> <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span>,\n       <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"first_name\"<\/span>,   \n       <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"last_name\"<\/span>,    \n       <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"contact_id\"<\/span>,   \n       <span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span>,\n       <span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span>,\n       <span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"name\"<\/span>,\n       <span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"description\"<\/span>\n  <span class=\"hljs-keyword\">FROM<\/span> <span class=\"hljs-string\">\"hr_employee\"<\/span>\n <span class=\"hljs-keyword\">INNER<\/span> <span class=\"hljs-keyword\">JOIN<\/span> <span class=\"hljs-string\">\"hr_department\"<\/span>\n    <span class=\"hljs-keyword\">ON<\/span> (<span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"department_id\"<\/span> = <span class=\"hljs-string\">\"hr_department\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span>)\n <span class=\"hljs-keyword\">LIMIT<\/span> <span class=\"hljs-number\">21<\/span>\nExecution <span class=\"hljs-built_in\">time<\/span>: <span class=\"hljs-number\">0.012124<\/span>s &#91;<span class=\"hljs-keyword\">Database<\/span>: <span class=\"hljs-keyword\">default<\/span>]\n&lt;QuerySet &#91;&lt;Employee: John Doe&gt;, &lt;Employee: Jane Doe&gt;]&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this example, Django executes only one query that joins the <code>hr_employee<\/code> and <code>hr_department<\/code> tables.<\/p>\n\n\n\n<p class=\"note\"><a href=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/12\/django_orm_3.zip\" target=\"_blank\" rel=\"noreferrer noopener\">Download the Django one-to-many relationship source code<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='summary'>Summary <a href=\"#summary\" class=\"anchor\" id=\"summary\" title=\"Anchor for Summary\">#<\/a><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>In a one-to-many relationship, a row in a table is associated with one or more rows in another table.<\/li>\n\n\n\n<li>Use <code>ForeignKey<\/code> to establish a one-to-many relationship between models in Django.<\/li>\n\n\n\n<li>Define the <code>ForeignKey<\/code> in the model of the &#8220;many&#8221; side of the relationship.<\/li>\n\n\n\n<li>Use the <code>select_related()<\/code> method to join two or more tables in the one-to-many relationships.<\/li>\n<\/ul>\n<div class=\"helpful-block-content\" data-title=\"\">\n\t<header>\n\t\t<div class=\"wth-question\">Was this tutorial helpful ?<\/div>\n\t\t<div class=\"wth-thumbs\">\n\t\t\t<button\n\t\t\t\tdata-post=\"6221\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-one-to-many\/\"\n\t\t\t\tdata-post-title=\"Django One-To-Many Relationship\"\n\t\t\t\tdata-response=\"1\"\n\t\t\t\tclass=\"wth-btn-rounded wth-yes-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\tclass=\"feather feather-thumbs-up block w-full h-full\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> Yes <\/span>\n\t\t\t<\/button>\n\n\t\t\t<button\n\t\t\t\tdata-response=\"0\"\n\t\t\t\tdata-post=\"6221\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-one-to-many\/\"\n\t\t\t\tdata-post-title=\"Django One-To-Many Relationship\"\n\t\t\t\tclass=\"wth-btn-rounded wth-no-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> No <\/span>\n\t\t\t<\/button>\n\t\t<\/div>\n\t<\/header>\n\n\t<div class=\"wth-form hidden\">\n\t\t<div class=\"wth-form-wrapper\">\n\t\t\t<div class=\"wth-title\"><\/div>\n\t\t\t<textarea class=\"wth-message\"><\/textarea>\n\t\t\t<input type=\"button\" name=\"wth-submit\" class=\"wth-btn wth-btn-submit\" id=\"wth-submit\" \/>\n\t\t\t<input type=\"button\" class=\"wth-btn wth-btn-cancel\" value=\"Cancel\" \/>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, you&#8217;ll learn about one-to-many relationships in Django and how to use the ForeignKey to model them.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":5531,"menu_order":24,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-6221","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/6221","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/comments?post=6221"}],"version-history":[{"count":0,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/6221\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/5531"}],"wp:attachment":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/media?parent=6221"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}