{"id":6275,"date":"2022-12-27T07:57:40","date_gmt":"2022-12-27T07:57:40","guid":{"rendered":"https:\/\/www.pythontutorial.net\/?page_id=6275"},"modified":"2023-01-19T02:05:30","modified_gmt":"2023-01-19T02:05:30","slug":"django-manytomanyfield-through","status":"publish","type":"page","link":"https:\/\/www.pythontutorial.net\/django-tutorial\/django-manytomanyfield-through\/","title":{"rendered":"Django ManyToManyField Through"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you&#8217;ll learn how to add extra fields to the <code>ManyToManyField<\/code> using the through argument.<\/p>\n\n\n\n<p>In a <a href=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-many-to-many\/\">many-to-many relationship<\/a>, multiple rows in a table are associated with multiple rows in another table. To establish a many-to-many relationship, relational databases use a third table called the join table and create two <a href=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-one-to-many\/\">one-to-many relationships<\/a> from the source tables.<\/p>\n\n\n\n<p>Typically, the join table contains the id values of the source tables so that rows in one table can relate to the rows in the other table.<\/p>\n\n\n\n<p>Sometimes, you may want to add extra fields to the join table. For example, each employee may have multiple jobs during his\/her career. <\/p>\n\n\n\n<p>To track when an employee takes a job, you can add the <code>begin_date<\/code> and <code>end_date<\/code> fields to the join table.<\/p>\n\n\n\n<p>To do that in Django, you use the <code>ManyToManyField<\/code> with the <code>through<\/code> argument. <\/p>\n\n\n\n<p>For example, the following shows how to associate an employee with multiple jobs through the assignments:<\/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\"><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 class=\"hljs-comment\"># ...<\/span>\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Job<\/span><span class=\"hljs-params\">(models.Model)<\/span>:<\/span>\n    title = models.CharField(max_length=<span class=\"hljs-number\">255<\/span>)\n    employees = models.ManyToManyField(Employee, through=<span class=\"hljs-string\">'Assignment'<\/span>)\n\n    <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 class=\"hljs-keyword\">return<\/span> self.title\n\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Assignment<\/span><span class=\"hljs-params\">(models.Model)<\/span>:<\/span>\n    employee = models.ForeignKey(Employee, on_delete=models.CASCADE)\n    position = models.ForeignKey(Job, on_delete=models.CASCADE)\n    begin_date = models.DateField()\n    end_date = models.DateField(default=date(<span class=\"hljs-number\">9999<\/span>, <span class=\"hljs-number\">12<\/span>, <span class=\"hljs-number\">31<\/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<ul class=\"wp-block-list\">\n<li>First, define the <code>Job<\/code> model, add the <code>employees<\/code> attribute that uses the <code>ManyToManyField<\/code>, and pass <code>Assignment<\/code> as the <code>through<\/code> argument.<\/li>\n\n\n\n<li>Second, define the <code>Assignment<\/code> class that has two foreign keys, one links to the <code>Employee<\/code> model, and the other links to the <code>Job<\/code> model. Also, add the <code>begin_date<\/code> and <code>end_date<\/code> attributes to the <code>Assignment<\/code> model.<\/li>\n<\/ul>\n\n\n\n<p>Run the <code>makemigrations<\/code> to make new migrations:<\/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\">python manage.py makemigrations<\/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>Output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">Migrations <span class=\"hljs-keyword\">for<\/span> <span class=\"hljs-string\">'hr'<\/span>:\n  hr\\migrations\\<span class=\"hljs-number\">0005<\/span>_assignment_job_assignment_job.py\n    - Create model Assignment\n    - Create model Job\n    - Add field job to assignment<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><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>And execute the <code>migrate<\/code> command to apply the changes to the database:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">python manage.py migrate<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><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>Output:<\/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\">Operations to perform:\n  Apply all migrations: admin, auth, contenttypes, hr, sessions\nRunning migrations:\n  Applying hr<span class=\"hljs-number\">.0005<\/span>_assignment_job_assignment_job... OK<\/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>Behind the scenes, Django creates the <code>hr_job<\/code> and <code>hr_assignment<\/code> tables in the database:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"845\" height=\"224\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/12\/Django-through-in-many-to-many.png\" alt=\"\" class=\"wp-image-6282\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/12\/Django-through-in-many-to-many.png 845w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/12\/Django-through-in-many-to-many-300x80.png 300w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/12\/Django-through-in-many-to-many-768x204.png 768w\" sizes=\"auto, (max-width: 845px) 100vw, 845px\" \/><\/figure>\n\n\n\n<p>The <code>hr_assignment<\/code> is the join table. Besides the <code>employee_id<\/code> and <code>position_id<\/code> fields, it has the <code>begin_date<\/code> and <code>end_date<\/code> fields.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='creating-new-jobs'>Creating new jobs <a href=\"#creating-new-jobs\" class=\"anchor\" id=\"creating-new-jobs\" title=\"Anchor for Creating new jobs\">#<\/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-6\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">python manage.py shell_plus<\/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>Second, create three new positions:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>j1 = Job(title=<span class=\"hljs-string\">'Software Engineer I'<\/span>)\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>j1.save()\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>j2 = Job(title=<span class=\"hljs-string\">'Software Engineer II'<\/span>) \n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>j2.save() \n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>j3 = Job(title=<span class=\"hljs-string\">'Software Engineer III'<\/span>)\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>j3.save()\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>Job.objects.all()\n&lt;QuerySet &#91;&lt;Job: Software Engineer I&gt;, &lt;Job: Software Engineer II&gt;, &lt;Job: Software Engineer III&gt;]&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><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<h2 class=\"wp-block-heading\" id='creating-instances-for-the-intermediate-models'>Creating instances for the intermediate models <a href=\"#creating-instances-for-the-intermediate-models\" class=\"anchor\" id=\"creating-instances-for-the-intermediate-models\" title=\"Anchor for Creating instances for the intermediate models\">#<\/a><\/h2>\n\n\n\n<p>First, find the employee with the name <code>John Doe<\/code> and <code>Jane Doe<\/code>:<\/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\"><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>e1 = Employee.objects.filter(first_name=<span class=\"hljs-string\">'John'<\/span>,last_name=<span class=\"hljs-string\">'Doe'<\/span>).first()\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>e1\n&lt;Employee: John Doe&gt;\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>e2 = Employee.objects.filter(first_name=<span class=\"hljs-string\">'Jane'<\/span>, last_name=<span class=\"hljs-string\">'Doe'<\/span>).first()\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>e2\n&lt;Employee: Jane Doe&gt;<\/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>Second, create instances of the intermediate model (<code>Assignment<\/code>):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" 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-keyword\">from<\/span> datetime <span class=\"hljs-keyword\">import<\/span> date\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>a1 = Assignment(employee=e1,job=j1, begin_date=date(<span class=\"hljs-number\">2019<\/span>,<span class=\"hljs-number\">1<\/span>,<span class=\"hljs-number\">1<\/span>), end_date=date(<span class=\"hljs-number\">2021<\/span>,<span class=\"hljs-number\">12<\/span>,<span class=\"hljs-number\">31<\/span>))\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>a1.save()\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>a2 = Assignment(employee=e1,job=j2, begin_date=date(<span class=\"hljs-number\">2022<\/span>,<span class=\"hljs-number\">1<\/span>,<span class=\"hljs-number\">1<\/span>))\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>a2.save()\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>a3 = Assignment(employee=e2, job=j1, begin_date=date(<span class=\"hljs-number\">2019<\/span>, <span class=\"hljs-number\">3<\/span>, <span class=\"hljs-number\">1<\/span>))\n<span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>a3.save()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><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, find the employees that hold the <code>Software Engineer I<\/code> position (<code>p1<\/code>):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>j1.employees.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-10\"><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>Behind the scenes, Django executes the following query:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">SELECT\n  <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>\nFROM <span class=\"hljs-string\">\"hr_employee\"<\/span>\nINNER JOIN <span class=\"hljs-string\">\"hr_assignment\"<\/span>\n  ON (<span class=\"hljs-string\">\"hr_employee\"<\/span>.<span class=\"hljs-string\">\"id\"<\/span> = <span class=\"hljs-string\">\"hr_assignment\"<\/span>.<span class=\"hljs-string\">\"employee_id\"<\/span>)\nWHERE <span class=\"hljs-string\">\"hr_assignment\"<\/span>.<span class=\"hljs-string\">\"job_id\"<\/span> = <span class=\"hljs-number\">1<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><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>Similarly, you can find all employees that hold the <code>Software Engineer II<\/code> position:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>j2.employees.all()\n&lt;QuerySet &#91;&lt;Employee: John Doe&gt;]&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><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<h2 class=\"wp-block-heading\" id='removing-instances-of-the-intermediate-model-instances'>Removing instances of the intermediate model instances <a href=\"#removing-instances-of-the-intermediate-model-instances\" class=\"anchor\" id=\"removing-instances-of-the-intermediate-model-instances\" title=\"Anchor for Removing instances of the intermediate model instances\">#<\/a><\/h2>\n\n\n\n<p>First, remove <code>Jane Doe<\/code> (<code>e2<\/code>) from the <code>Software Engineer II<\/code> job using the <code>remove()<\/code> method:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>j2.employees.remove(e2) <\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><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>Second, remove all employees from <code>Software Engineer I<\/code> job using the <code>clear()<\/code> method:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">&gt;&gt;&gt; <\/span>j1.employees.clear() <\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><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>The <code>j1<\/code> job should not have any employees now:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">&gt;&gt;&gt; <span class=\"hljs-selector-tag\">j1<\/span><span class=\"hljs-selector-class\">.employees<\/span><span class=\"hljs-selector-class\">.all<\/span>() \n&lt;<span class=\"hljs-selector-tag\">QuerySet<\/span> <span class=\"hljs-selector-attr\">&#91;]<\/span>&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><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 class=\"note\"><a href=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2023\/01\/django_orm_6.zip\">Download the 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>Use the <code>through<\/code> argument in the <code>ManyToManyField<\/code> to add extra fields to the many-to-many relationship.<\/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=\"6275\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-manytomanyfield-through\/\"\n\t\t\t\tdata-post-title=\"Django ManyToManyField Through\"\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=\"6275\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-manytomanyfield-through\/\"\n\t\t\t\tdata-post-title=\"Django ManyToManyField Through\"\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>Summary: in this tutorial, you&#8217;ll learn how to add extra fields to the ManyToManyField using the through argument. In a many-to-many relationship, multiple rows in a table are associated with multiple rows in another table. To establish a many-to-many relationship, relational databases use a third table called the join table and create two one-to-many relationships [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":5531,"menu_order":26,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-6275","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/6275","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=6275"}],"version-history":[{"count":0,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/6275\/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=6275"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}