<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: DoriDoro</title>
    <description>The latest articles on DEV Community by DoriDoro (@doridoro).</description>
    <link>https://dev.to/doridoro</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1139377%2Fb85d3b0d-837a-4168-a39c-f91309ea1d08.jpeg</url>
      <title>DEV Community: DoriDoro</title>
      <link>https://dev.to/doridoro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/doridoro"/>
    <language>en</language>
    <item>
      <title>Cheat Sheet for all Django `on_delete` options</title>
      <dc:creator>DoriDoro</dc:creator>
      <pubDate>Fri, 20 Jun 2025 08:22:55 +0000</pubDate>
      <link>https://dev.to/doridoro/cheat-sheet-for-all-django-ondelete-options-32a8</link>
      <guid>https://dev.to/doridoro/cheat-sheet-for-all-django-ondelete-options-32a8</guid>
      <description>&lt;h2&gt;
  
  
  Django &lt;code&gt;on_delete&lt;/code&gt; Cheat Sheet
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;What Happens When Referenced Object is Deleted?&lt;/th&gt;
&lt;th&gt;Use Case Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CASCADE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Also delete the object with the ForeignKey&lt;/td&gt;
&lt;td&gt;Delete all &lt;code&gt;Comment&lt;/code&gt;s when a &lt;code&gt;Post&lt;/code&gt; is deleted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PROTECT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Raises &lt;code&gt;ProtectedError&lt;/code&gt; and &lt;strong&gt;prevents deletion&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Prevent deleting a &lt;code&gt;User&lt;/code&gt; if they’re linked to existing &lt;code&gt;Orders&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SET_NULL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sets the ForeignKey field to &lt;code&gt;NULL&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Keep &lt;code&gt;Article&lt;/code&gt;, but set &lt;code&gt;author = NULL&lt;/code&gt; when &lt;code&gt;Author&lt;/code&gt; is deleted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SET_DEFAULT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sets the ForeignKey field to its default value&lt;/td&gt;
&lt;td&gt;If a &lt;code&gt;Product&lt;/code&gt; is deleted, fallback to a default &lt;code&gt;Category&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SET(...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sets the ForeignKey to a custom value or callable&lt;/td&gt;
&lt;td&gt;Set to an "archived" user when original &lt;code&gt;User&lt;/code&gt; is deleted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DO_NOTHING&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Does nothing; deletion might fail due to DB-level constraints&lt;/td&gt;
&lt;td&gt;Advanced use with manual control; &lt;strong&gt;avoid unless necessary&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;RESTRICT&lt;/code&gt; &lt;em&gt;(Django 3.1+)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;Raises error &lt;strong&gt;if there are any referencing objects&lt;/strong&gt; (like &lt;code&gt;PROTECT&lt;/code&gt;, but stricter in behavior visibility)&lt;/td&gt;
&lt;td&gt;Similar to &lt;code&gt;PROTECT&lt;/code&gt;, but enforces DB constraint at the SQL level&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  When to Use What?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Goal&lt;/th&gt;
&lt;th&gt;Recommended Option&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Automatically delete dependents&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CASCADE&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prevent deletion if used somewhere&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;PROTECT&lt;/code&gt; or &lt;code&gt;RESTRICT&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Allow deletion, but keep dependent object&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;SET_NULL&lt;/code&gt; or &lt;code&gt;SET(...)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Replace with default&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SET_DEFAULT&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full manual control&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DO_NOTHING&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Example Code Snippets
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.conf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AUTH_USER_MODEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SET_NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Comment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AUTH_USER_MODEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PROTECT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Category&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SET_DEFAULT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;  &lt;span class="c1"&gt;# assuming category with id=1 is 'Uncategorized'
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Using JWT with Django REST Framework and Vue.js</title>
      <dc:creator>DoriDoro</dc:creator>
      <pubDate>Fri, 14 Mar 2025 11:25:45 +0000</pubDate>
      <link>https://dev.to/doridoro/using-jwt-with-django-rest-framework-and-vuejs-487l</link>
      <guid>https://dev.to/doridoro/using-jwt-with-django-rest-framework-and-vuejs-487l</guid>
      <description>&lt;p&gt;Here’s how JWT (JSON Web Token) works in Django DRF:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step-by-Step JWT Flow
&lt;/h3&gt;

&lt;p&gt;1️⃣ &lt;strong&gt;User Logs In&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontend sends &lt;code&gt;username&lt;/code&gt; &amp;amp; &lt;code&gt;password&lt;/code&gt; to &lt;code&gt;/api/token/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Django returns &lt;code&gt;access&lt;/code&gt; and &lt;code&gt;refresh&lt;/code&gt; tokens.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"access"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJhbGciOi... (valid for 60 minutes)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"refresh"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJhbGciOi... (valid for 7 days)"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2️⃣ &lt;strong&gt;Frontend Stores the Tokens&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The access token is stored in Vuex, Pinia, or LocalStorage.&lt;/li&gt;
&lt;li&gt;The refresh token is stored in HTTP-only cookies (for security).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3️⃣ &lt;strong&gt;Frontend Sends Access Token with Every API Request&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When making a request to Django, Vue.js &lt;strong&gt;adds the token to the &lt;code&gt;Authorization&lt;/code&gt; header&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/chats/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4️⃣ &lt;strong&gt;Backend Verifies the Token&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DRF checks if the &lt;code&gt;access&lt;/code&gt; token is valid.&lt;/li&gt;
&lt;li&gt;If valid → The request is processed.&lt;/li&gt;
&lt;li&gt;If expired → The backend rejects it (401 Unauthorized).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;5️⃣ &lt;strong&gt;Frontend Uses Refresh Token to Get a New Access Token&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the access token expires, Vue.js sends the &lt;code&gt;refresh&lt;/code&gt; token to &lt;code&gt;/api/token/refresh/&lt;/code&gt; to get a new one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Request to Refresh Token:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"refresh"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJhbGciOi... (old refresh token)"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Backend Response (New Access Token):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"access"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJhbGciOi... (new access token)"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;6️⃣ &lt;strong&gt;Frontend Stores the New Access Token and Continues&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The new &lt;code&gt;access&lt;/code&gt; token replaces the old one and API requests continue normally.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp75it8l2p0v2rhwa1bhx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp75it8l2p0v2rhwa1bhx.png" alt="Image description" width="800" height="241"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Vue.js Example: Sending JWT Token&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the frontend sends a request to create a chat, it includes the JWT token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendChat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;personas&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;accessToken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/chats/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;personas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;personas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;personas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;persona&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;response_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Simulated AI response&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Access token expired. Refreshing...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sendChat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;personas&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>What is `ContentFile` in Django?</title>
      <dc:creator>DoriDoro</dc:creator>
      <pubDate>Thu, 13 Mar 2025 18:12:02 +0000</pubDate>
      <link>https://dev.to/doridoro/what-is-contentfile-in-django-6nm</link>
      <guid>https://dev.to/doridoro/what-is-contentfile-in-django-6nm</guid>
      <description>&lt;p&gt;&lt;code&gt;ContentFile&lt;/code&gt; is a Django utility class that allows you to &lt;strong&gt;create a file-like object from raw data (such as a string or binary data)&lt;/strong&gt;. It is particularly useful when you want to &lt;strong&gt;save an image or other file content directly into a Django &lt;code&gt;FileField&lt;/code&gt; or &lt;code&gt;ImageField&lt;/code&gt; without needing an actual file on disk&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Why is &lt;code&gt;ContentFile&lt;/code&gt; Needed?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Normally, when you assign a file to a Django &lt;code&gt;ImageField&lt;/code&gt;, Django expects a &lt;strong&gt;physical file&lt;/strong&gt;. However, in cases where you generate or modify an image &lt;strong&gt;in memory&lt;/strong&gt; (e.g., resizing it with Pillow), you don’t have a physical file yet. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is where &lt;code&gt;ContentFile&lt;/code&gt; comes in&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
It allows you to take &lt;strong&gt;binary data&lt;/strong&gt; (like an image stored in memory with &lt;code&gt;BytesIO()&lt;/code&gt;) and treat it as if it were a normal file, so it can be saved into a model's &lt;code&gt;ImageField&lt;/code&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;How Does &lt;code&gt;ContentFile&lt;/code&gt; Work?&lt;/strong&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.core.files.base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ContentFile&lt;/span&gt;

&lt;span class="c1"&gt;# Example: Creating a file-like object from raw data
&lt;/span&gt;&lt;span class="n"&gt;raw_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, this is some binary data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;file_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ContentFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, &lt;code&gt;file_obj&lt;/code&gt; behaves like a Django &lt;strong&gt;File object&lt;/strong&gt;, even though it's just binary data stored in memory.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;Why Is It Used in Your Code?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In your &lt;strong&gt;profile image resizing function&lt;/strong&gt;, we &lt;strong&gt;don’t want to save the resized image to disk first&lt;/strong&gt; before saving it into &lt;code&gt;self.photo&lt;/code&gt;. Instead, we process it &lt;strong&gt;in memory&lt;/strong&gt; and then directly store it into Django’s &lt;code&gt;ImageField&lt;/code&gt; using &lt;code&gt;ContentFile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the key part of your function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Save the resized image to memory
&lt;/span&gt;&lt;span class="nb"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BytesIO&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Use ContentFile to store the in-memory image into the ImageField
&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_image_filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ContentFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getvalue&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt; &lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Breakdown of What Happens Here&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The image is processed and resized using &lt;code&gt;Pillow&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The resized image is written into a &lt;strong&gt;BytesIO buffer&lt;/strong&gt; (not saved to disk).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;buffer.getvalue()&lt;/code&gt; extracts the binary image data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ContentFile(buffer.getvalue())&lt;/code&gt; creates a &lt;strong&gt;file-like object&lt;/strong&gt; from the binary data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;self.photo.save(new_image_filename, ContentFile(buffer.getvalue()), save=False)&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Assigns the resized image &lt;strong&gt;directly&lt;/strong&gt; to the &lt;code&gt;photo&lt;/code&gt; field, without needing to write a file to disk first.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;save=False&lt;/code&gt; ensures we don’t accidentally call &lt;code&gt;save()&lt;/code&gt; on the whole model multiple times.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;What Would Happen Without &lt;code&gt;ContentFile&lt;/code&gt;?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If we didn’t use &lt;code&gt;ContentFile&lt;/code&gt;, we would have to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Save the resized image &lt;strong&gt;to disk&lt;/strong&gt; first.&lt;/li&gt;
&lt;li&gt;Open the saved file and assign it to &lt;code&gt;photo&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Delete the intermediate file after assigning.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That would be &lt;strong&gt;slow and inefficient&lt;/strong&gt;. &lt;code&gt;ContentFile&lt;/code&gt; lets us &lt;strong&gt;skip saving an unnecessary temporary file to disk&lt;/strong&gt;, making the process faster and cleaner.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Final Takeaways&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ContentFile&lt;/code&gt; is needed when saving files directly from memory into Django models.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It allows us to store an image in an &lt;code&gt;ImageField&lt;/code&gt; without writing to disk first.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It works perfectly with Pillow (&lt;code&gt;PIL.Image&lt;/code&gt;) and Django's file handling system.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It makes image processing more efficient and avoids unnecessary I/O operations.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;When Should You Use &lt;code&gt;ContentFile&lt;/code&gt;?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When working with &lt;strong&gt;images processed in memory&lt;/strong&gt; (like resized thumbnails).&lt;/li&gt;
&lt;li&gt;When creating &lt;strong&gt;dynamic files&lt;/strong&gt; (e.g., a PDF or CSV generated on-the-fly).&lt;/li&gt;
&lt;li&gt;When handling &lt;strong&gt;uploads via API where the file is received as raw data&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>django</category>
    </item>
    <item>
      <title>Understanding creating an Authentication Backend in a Django project</title>
      <dc:creator>DoriDoro</dc:creator>
      <pubDate>Sun, 02 Mar 2025 08:17:00 +0000</pubDate>
      <link>https://dev.to/doridoro/understanding-creating-an-authentication-backend-in-a-django-project-14po</link>
      <guid>https://dev.to/doridoro/understanding-creating-an-authentication-backend-in-a-django-project-14po</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;An &lt;strong&gt;authentication backend&lt;/strong&gt; in Django is a class that &lt;strong&gt;determines how users are authenticated (logged in)&lt;/strong&gt;. By default, Django uses &lt;code&gt;ModelBackend&lt;/code&gt;, which authenticates users based on their &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt;. However, Django allows developers to define &lt;strong&gt;custom authentication backends&lt;/strong&gt; to modify or extend authentication behavior or authenticate users against different sources (internal or external sources). An external authentication systems like &lt;strong&gt;Lightweight directory Access Protocol (LDAP)&lt;/strong&gt; server or even third-party providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use an Authentication Backend?
&lt;/h2&gt;

&lt;p&gt;Authentication backends are used when you want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Authenticate users in different ways&lt;/strong&gt;, such as logging in with an email as a username.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support multiple authentication methods&lt;/strong&gt;, like social logins (Google, Facebook) or external APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement custom user verification logic&lt;/strong&gt;, such as checking user roles, permissions, or account status.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Does It Work?
&lt;/h2&gt;

&lt;p&gt;Django uses authentication backends in the following way:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When a user tries to log in, Django iterates through the backends listed in &lt;code&gt;AUTHENTICATION_BACKENDS&lt;/code&gt; in &lt;code&gt;settings.py&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Each backend’s &lt;code&gt;authenticate()&lt;/code&gt; method is called. If a backend returns a user, authentication is successful.&lt;/li&gt;
&lt;li&gt;If no backend authenticates the user, login fails.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Example: Custom Email Authentication Backend&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here’s a simple authentication backend that allows users to log in with their &lt;strong&gt;email and password&lt;/strong&gt; instead of a username:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/authentication.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_user_model&lt;/span&gt;

&lt;span class="n"&gt;UserModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_user_model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailAuthBackend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Authenticate users using their email address instead of a username.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;UserModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DoesNotExist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Retrieve a user by their ID.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;UserModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;UserModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DoesNotExist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuring Authentication Backends in Django
&lt;/h2&gt;

&lt;p&gt;To enable a custom authentication backend, update &lt;code&gt;settings.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# project/settings.py
&lt;/span&gt;
&lt;span class="c1"&gt;# Authentication backends configuration
&lt;/span&gt;&lt;span class="n"&gt;AUTHENTICATION_BACKENDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;path.to.EmailAuthBackend&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Allow email login
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth.backends.ModelBackend&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Default username login
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;When you add a &lt;strong&gt;custom authentication backend&lt;/strong&gt; like above you should consider some important changes in your application. &lt;/p&gt;

&lt;p&gt;By default Django User model does not enforce unique email address. To ensure that the email address of each User instance is unique, it is better practice to set the &lt;code&gt;email&lt;/code&gt; attribute inside of your User model to &lt;code&gt;unique=True&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# accounts/models.py
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AbstractUser&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Default User model does not enforce unique emails!&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;EmailField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now Django automatically enforces uniqueness at the &lt;strong&gt;database level&lt;/strong&gt;, meaning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If someone tries to register with an existing email, the database will raise an &lt;code&gt;IntegrityError&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;However, Django’s form validation &lt;strong&gt;does not check this before submitting&lt;/strong&gt; unless you explicitly add it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Changing the email address to be unique requires additional changes. If a user registers or changes their email address within your application and the uniqueness of the email is not verified in the registration view, this will result in a &lt;strong&gt;500 server error&lt;/strong&gt;. And to have a more user friendly message instead of an error 500, you need to add additional logic to the registration form.&lt;/p&gt;

&lt;p&gt;Add a &lt;code&gt;clean_email()&lt;/code&gt; method to the registration form.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# accounts/forms.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;forms&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth.forms&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UserCreationForm&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_user_model&lt;/span&gt;

&lt;span class="n"&gt;UserModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_user_model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RegistrationForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserCreationForm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Register form for new User instances&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserModel&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;first_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;password1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;password2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;clean_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Ensure email is unique before saving.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cleaned_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;UserModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ValidationError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Email already exists. Please use a different one.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;With this setup:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Registration&lt;/strong&gt; → Users provide a &lt;strong&gt;username, email, and password&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Login&lt;/strong&gt; → Users can log in using &lt;strong&gt;either&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Username + Password&lt;/strong&gt; (handled by &lt;code&gt;ModelBackend&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email + Password&lt;/strong&gt; (handled by &lt;code&gt;EmailAuthBackend&lt;/code&gt;)
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This gives users &lt;strong&gt;flexibility&lt;/strong&gt; while still keeping the registration process structured. It’s a great balance between user convenience and maintaining Django’s built-in authentication system.  &lt;/p&gt;

</description>
      <category>django</category>
    </item>
    <item>
      <title>Fixing Docker 'Permission Denied' Error on Ubuntu 24.04: A Step-by-Step Guide</title>
      <dc:creator>DoriDoro</dc:creator>
      <pubDate>Sat, 01 Mar 2025 09:03:06 +0000</pubDate>
      <link>https://dev.to/doridoro/fixing-docker-permission-denied-error-on-ubuntu-2404-a-step-by-step-guide-1562</link>
      <guid>https://dev.to/doridoro/fixing-docker-permission-denied-error-on-ubuntu-2404-a-step-by-step-guide-1562</guid>
      <description>&lt;h2&gt;
  
  
  Intrduction
&lt;/h2&gt;

&lt;p&gt;When setting up Docker on Ubuntu 24.04, you might encounter a &lt;strong&gt;"permission denied"&lt;/strong&gt; error when running Docker commands without &lt;code&gt;sudo&lt;/code&gt;. This issue typically occurs because the user does not have the correct permissions to access the Docker daemon. Even after adding the user to the &lt;code&gt;docker&lt;/code&gt; group, the changes may not take effect immediately, leading to frustration when trying to run &lt;code&gt;docker images&lt;/code&gt; or other commands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Remove Old Docker Versions (If Any):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt remove &lt;span class="nt"&gt;-y&lt;/span&gt; docker docker-engine docker.io containerd runc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Update Package Lists:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Add Docker's Official GPG Key:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo install&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; 0755 &lt;span class="nt"&gt;-d&lt;/span&gt; /etc/apt/keyrings
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://download.docker.com/linux/ubuntu/gpg | &lt;span class="nb"&gt;sudo &lt;/span&gt;gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /etc/apt/keyrings/docker.gpg
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;a+r /etc/apt/keyrings/docker.gpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Verify Your Ubuntu Version:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lsb_release &lt;span class="nt"&gt;-cs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should return &lt;code&gt;noble&lt;/code&gt; (for Ubuntu 24.04). If not, check your installation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Set Up Docker's Stable Repository:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [arch=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;dpkg &lt;span class="nt"&gt;--print-architecture&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu noble stable"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/docker.list &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Update Package Index Again:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;6. Install Docker Engine and Related Components:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;7. Verify Docker Installation:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the Service is working, the terminal should show:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker.service - Docker Application Container Engine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and further information&lt;/p&gt;

&lt;p&gt;End the running Service with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;q
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;8. Test Docker with a Sample Container:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker run hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These steps install Docker on your machine.&lt;/p&gt;




&lt;p&gt;When I installed Docker on my machine, there was still a message when trying to access all docker images (&lt;code&gt;docker images&lt;/code&gt;) on my machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;permission denied &lt;span class="k"&gt;while &lt;/span&gt;trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Head &lt;span class="s2"&gt;"http://%2Fvar%2Frun%2Fdocker.sock/_ping"&lt;/span&gt;: dial unix /var/run/docker.sock: connect: permission denied
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this message appears when you want to access docker images without &lt;code&gt;sudo&lt;/code&gt; permission on your machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution: Add Your User to the docker Group&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;1. Check if the &lt;code&gt;docker&lt;/code&gt; group exists:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;getent group docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If nothing is returned, create the group manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;groupadd docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Add Your User to the &lt;code&gt;docker&lt;/code&gt; Group:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker &lt;span class="nv"&gt;$USER&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Apply the Changes:&lt;/strong&gt; Log out and log back in, or restart your machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;newgrp docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Test Running Docker without &lt;code&gt;sudo&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you want to access the &lt;code&gt;docker&lt;/code&gt; system without any &lt;code&gt;sudo&lt;/code&gt; commands, restart your machine and it is done.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;"permission denied"&lt;/strong&gt; error is usually resolved by ensuring the user is correctly added to the &lt;code&gt;docker&lt;/code&gt; group and restarting the system to apply the changes. If the issue persists, checking and adjusting the permissions of the Docker socket can help. After completing these steps, you should be able to run Docker commands without &lt;code&gt;sudo&lt;/code&gt; and manage containers smoothly. &lt;/p&gt;

</description>
      <category>docker</category>
    </item>
    <item>
      <title>What is the difference between INNER JOIN, LEFT JOIN and RIGHT JOIN in SQL?</title>
      <dc:creator>DoriDoro</dc:creator>
      <pubDate>Wed, 19 Feb 2025 19:50:44 +0000</pubDate>
      <link>https://dev.to/doridoro/what-is-the-difference-between-inner-join-left-join-and-right-join-in-sql-2nf3</link>
      <guid>https://dev.to/doridoro/what-is-the-difference-between-inner-join-left-join-and-right-join-in-sql-2nf3</guid>
      <description>&lt;p&gt;Once I came across the question: "what is a right table and what is a left table in SQL?"&lt;/p&gt;

&lt;p&gt;In SQL, the terms &lt;strong&gt;"left table"&lt;/strong&gt; and &lt;strong&gt;"right table"&lt;/strong&gt; refer to the order in which tables are listed in a &lt;code&gt;JOIN&lt;/code&gt; clause. His order determines how the join operates, especially in &lt;code&gt;LEFT JOIN&lt;/code&gt; and &lt;code&gt;RIGHT JOIN&lt;/code&gt; scenarios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Determining the Left and Right Tables:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Left Table&lt;/strong&gt;: The table that appears first in the &lt;code&gt;JOIN&lt;/code&gt; clause.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Right Table&lt;/strong&gt;: The table that appears second in the &lt;code&gt;JOIN&lt;/code&gt; clause.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;ELECT&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;table1&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;table2&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;table1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this above query:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;table1&lt;/code&gt;&lt;/strong&gt; is the &lt;strong&gt;left table&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;table2&lt;/code&gt;&lt;/strong&gt; is the &lt;strong&gt;right table&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Understanding &lt;code&gt;LEFT JOIN&lt;/code&gt; and &lt;code&gt;RIGHT JOIN&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;LEFT JOIN&lt;/code&gt;: Returns all records from the &lt;strong&gt;left table&lt;/strong&gt; and the matched records from the right table. If there's no match, the result is &lt;code&gt;NULL&lt;/code&gt; on the side of the right table.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RIGHT JOIN&lt;/code&gt;: Returns all records from the &lt;strong&gt;right table&lt;/strong&gt; and the matched records from the left table. If there's no match, the result is &lt;code&gt;NULL&lt;/code&gt; on the side of the left table.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The designation of "left" and "right" is purely based on the order of tables in your SQL statement. By rearranging the order of tables and switching between &lt;code&gt;LEFT JOIN&lt;/code&gt; and &lt;code&gt;RIGHT JOIN&lt;/code&gt;, you can achieve the same results. However, &lt;code&gt;LEFT JOIN&lt;/code&gt; is more commonly used in practice.&lt;/p&gt;




&lt;h2&gt;
  
  
  Now, what is the difference between &lt;code&gt;JOIN&lt;/code&gt;, &lt;code&gt;LEFT JOIN&lt;/code&gt; and &lt;code&gt;RIGHT JOIN&lt;/code&gt; in SQL?
&lt;/h2&gt;

&lt;p&gt;In SQL, joins are used to combine rows from two or more tables based on related columns. The primary types of joins are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;INNER JOIN&lt;/code&gt;&lt;/strong&gt;: Returns only the rows where there is a match in &lt;strong&gt;both tables&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;LEFT JOIN&lt;/code&gt; (&lt;code&gt;LEFT OUTER JOIN&lt;/code&gt;)&lt;/strong&gt;: Returns all rows from the &lt;strong&gt;left table&lt;/strong&gt; and the matched rows from the right table. If there's no match, the result is &lt;code&gt;NUL&lt;/code&gt;L on the side of the right table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;RIGHT JOIN&lt;/code&gt; (&lt;code&gt;RIGHT OUTER JOIN&lt;/code&gt;)&lt;/strong&gt;: Returns all rows from the &lt;strong&gt;right table&lt;/strong&gt; and the matched rows from the left table. If there's no match, the result is &lt;code&gt;NULL&lt;/code&gt; on the side of the left table.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Syntax examples:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;  &lt;span class="n"&gt;ELECT&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;table1&lt;/span&gt;
  &lt;span class="k"&gt;INNER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;table2&lt;/span&gt;
  &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;table1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;common_column&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;common_column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;  &lt;span class="n"&gt;ELECT&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;table1&lt;/span&gt;
  &lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;table2&lt;/span&gt;
  &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;table1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;common_column&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;common_column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;  &lt;span class="n"&gt;ELECT&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;table1&lt;/span&gt;
  &lt;span class="k"&gt;RIGHT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;table2&lt;/span&gt;
  &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;table1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;common_column&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;common_column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Integrate Sentry into your Django project</title>
      <dc:creator>DoriDoro</dc:creator>
      <pubDate>Thu, 02 Jan 2025 14:28:12 +0000</pubDate>
      <link>https://dev.to/doridoro/integrate-sentry-into-your-django-project-4j1d</link>
      <guid>https://dev.to/doridoro/integrate-sentry-into-your-django-project-4j1d</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When your project is ready to go live, it is a good time to integrate Sentry services to monitor your failures. It enables automatic reporting of defects and exceptions, as well as traceability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Install Sentry in your project&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; &lt;span class="s1"&gt;'sentry-sdk[django]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have a Django project and want to use the &lt;code&gt;DjangoIntegration&lt;/code&gt; option, you will only need this Django extension. And add &lt;code&gt;sentry-sdk&lt;/code&gt; to &lt;code&gt;requirements.txt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Create a project on Sentry website&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Log in to your account or sign up for a new free account from the &lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry home page&lt;/a&gt;. You will be taken to the main account dashboard after logging in or completing the Sentry sign-up process.&lt;/p&gt;

&lt;p&gt;Click on 'Projects' in the left sidebar to go to the Projects page and create a new Sentry Project just for this application. Click on the 'Create Project' button at the top right of the page.&lt;/p&gt;

&lt;p&gt;You choose 'Django' as platform. The next step is to give your new project a name and then press the 'Create Project' button. We can now integrate our Python code into our new project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Set up your Django project&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your newly created Sentry project, you will find the documentation you need to continue to integrate the &lt;code&gt;sentry-sdk&lt;/code&gt; into your project.&lt;/p&gt;

&lt;p&gt;First, import the &lt;code&gt;sentry-sdk&lt;/code&gt; at the top of your file and add the &lt;code&gt;sentry-sdk&lt;/code&gt; to the end of your &lt;code&gt;settings.py&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# blog_project/settings.py
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sentry_sdk&lt;/span&gt;


&lt;span class="n"&gt;sentry_sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;dsn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://yourkeygoeshere.ingest.sentry.io/project-number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;traces_sample_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;_experiments&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;continuous_profiling_auto_start&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is to add a URL to your project to trigger your first error, which will be reported in your Sentry dashboard. Personally, in order to be able to check the functionality of the Sentry integration later in production, I do not remove this URL and the ability to trigger an error in your project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# core/urls.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;

&lt;span class="n"&gt;app_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;core&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;trigger_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;division_by_zero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;


&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sentry-debug/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trigger_error&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Check the functionality&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Start your development server with &lt;code&gt;python manage.py runserver&lt;/code&gt;. Navigate to your URL pattern: &lt;code&gt;http://127.0.0.1:8000/sentry-debug/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This URL will cause a zero revision error in your project. Wait a minute or two and refresh the Sentry dashboard to see if the &lt;code&gt;sentry-sdk&lt;/code&gt; integration was successful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Additional informations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DjangoIntegration&lt;/code&gt; makes it much easier to debug and monitor a Django application with Sentry. It's highly recommended to include it when using Sentry in a Django project.&lt;/p&gt;

&lt;p&gt;In order to integrate the &lt;code&gt;DjangoIntegration&lt;/code&gt; option, you need to import &lt;code&gt;DjangoIntegration&lt;/code&gt; at the top of the &lt;code&gt;settings.py&lt;/code&gt; file and update the part from 'integrations' onwards.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# blog_project/settings.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sentry_sdk.integrations.django&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DjangoIntegration&lt;/span&gt;

&lt;span class="n"&gt;sentry_sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;dsn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-sentry-dsn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;integrations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nc"&gt;DjangoIntegration&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;traces_sample_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Enables performance monitoring
&lt;/span&gt;    &lt;span class="n"&gt;send_default_pii&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# Sends Personally Identifiable Information (PII), like user details
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Django integration has more features. But for a simple Django project these settings are sufficient.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sentry documentation &lt;a href="https://docs.sentry.io/platforms/python/integrations/django/" rel="noopener noreferrer"&gt;Django section&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>django</category>
      <category>sentry</category>
    </item>
    <item>
      <title>Django built-in authentication system</title>
      <dc:creator>DoriDoro</dc:creator>
      <pubDate>Fri, 27 Dec 2024 22:40:46 +0000</pubDate>
      <link>https://dev.to/doridoro/django-built-in-authentication-1j93</link>
      <guid>https://dev.to/doridoro/django-built-in-authentication-1j93</guid>
      <description>&lt;h2&gt;
  
  
  Introduction:
&lt;/h2&gt;

&lt;p&gt;In this article I will explain to you how to create a simple Django project with the basic login and logout authentication process. Django has built-in authentication systems and built-in views that you can use to quickly and easily create a user authentication using your own templates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create the Django project:
&lt;/h3&gt;

&lt;p&gt;Create a new project in your IDE or Terminal and go to the folder you have created. Create a virtual environment.&lt;/p&gt;

&lt;p&gt;Now install the dependencies inside your virtual environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;django python-decouple ipyhton
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can chain multiple dependencies together. You install Django for your project. &lt;code&gt;python-decouple&lt;/code&gt; is for the &lt;code&gt;.env&lt;/code&gt; file where you put all your secret environment variables, like the &lt;code&gt;SECRET_KEY&lt;/code&gt; or all email configurations, etc. And &lt;code&gt;ipython&lt;/code&gt; is a nice tool for the shell.&lt;/p&gt;

&lt;p&gt;After you have successfully installed your dependencies, store them in a file in the root directory with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip freeze &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;pip freeze&lt;/code&gt; lists all dependencies in terminal&lt;br&gt;
&lt;code&gt;&amp;gt; requirements.txt&lt;/code&gt; this will save all installed dependencies in a  the file called &lt;code&gt;requirements.txt&lt;/code&gt; or create the file.&lt;/p&gt;

&lt;p&gt;Now build your Django project inside the virtual environment using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;django-admin startproject authentication &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;.&lt;/code&gt; after the name of your project is to create the Django project directory inside the root directory.&lt;/p&gt;

&lt;p&gt;After you have created your first application inside the Django project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python manage.py startapp accounts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application has to be added into to the &lt;code&gt;INSTALLED_APPS&lt;/code&gt; in the &lt;code&gt;settings.py&lt;/code&gt; file inside the &lt;code&gt;authentication&lt;/code&gt; project directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# authentication/settings.py
&lt;/span&gt;
&lt;span class="c1"&gt;# Application definition
&lt;/span&gt;&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accounts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.contenttypes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.sessions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.staticfiles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to create your own custom authentication templates, you need to make sure that your created application &lt;code&gt;accounts&lt;/code&gt; is placed before the &lt;code&gt;"django.contrib.admin"&lt;/code&gt; application.&lt;/p&gt;




&lt;h3&gt;
  
  
  Ensure security of your project:
&lt;/h3&gt;

&lt;p&gt;To ensure the security of your project, you should store the &lt;code&gt;SECRET_KEY&lt;/code&gt;, &lt;code&gt;DEBUG&lt;/code&gt;, &lt;code&gt;ALLOWED_HOSTS&lt;/code&gt;, etc. in a locally stored &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Enter the above command in your terminal to create a secure &lt;code&gt;SECRET_KEY&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python manage.py shell &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'from django.core.management import utils; print(utils.get_random_secret_key())'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an &lt;code&gt;.env&lt;/code&gt; file in the root directory and add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# general project variables:
SECRET_KEY="r^=cy=8w8$^p)!gd6#%*c)s-u4h!ua9r6!i317qt^6l47)94t^"
DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be able to start your development server, you need to have access to the project variables such as the &lt;code&gt;SECRET_KEY&lt;/code&gt;. You need to make sure that your &lt;code&gt;settings.py&lt;/code&gt; file has access to the environment variables stored in the &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;The first step is already done by installing &lt;code&gt;python-decouple&lt;/code&gt;. Now update the &lt;code&gt;settings.py&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# authentication/settings.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;decouple&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;


&lt;span class="c1"&gt;# SECURITY WARNING: keep the secret key used in production secret!
&lt;/span&gt;&lt;span class="n"&gt;SECRET_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SECRET_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# SECURITY WARNING: don't run with debug turned on in production!
&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DEBUG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ALLOWED_HOSTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ALLOWED_HOSTS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ALLOWED_HOSTS&lt;/code&gt; should be a list. We have stored the value as a comma separated string in the &lt;code&gt;.env&lt;/code&gt; file. Within the &lt;code&gt;settings.py&lt;/code&gt; file, we split the comma-separated strings at the &lt;code&gt;,&lt;/code&gt; and create a list from them.&lt;/p&gt;

&lt;p&gt;The next file you need to create is the &lt;code&gt;.gitignore&lt;/code&gt; file, to avoid sending your environment variables to GitHub or GitLab.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# Django stuff:
*.log
*.pot
*.pyc

# virtual environment
.venv

# IDE
.idea

# Local configuration
.env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;.gitignore&lt;/code&gt; file is just an example, yours may look different depending on your IDE.&lt;/p&gt;




&lt;h3&gt;
  
  
  Creating a User model:
&lt;/h3&gt;

&lt;p&gt;It is good practice to use the &lt;code&gt;AbstractUser&lt;/code&gt; to create your own user model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# accounts/models.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AbstractUser&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AbstractUser&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If necessary, you can add additional attributes within the &lt;code&gt;User&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;The next step is to add the &lt;code&gt;User&lt;/code&gt; model to the Admin Panel. This way you can easily create &lt;code&gt;User&lt;/code&gt; instances from the admin panel. You can also create &lt;code&gt;User&lt;/code&gt; instances in the Python shell.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# accounts/models.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_user_model&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth.admin&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UserAdmin&lt;/span&gt;

&lt;span class="n"&gt;UserModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_user_model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UserAdmin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;settings.py&lt;/code&gt; file, we need to set the &lt;code&gt;User&lt;/code&gt; we created to tell the project that we want to use our custom &lt;code&gt;User&lt;/code&gt; model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# authentication/settings.py
&lt;/span&gt;
&lt;span class="c1"&gt;# template settings
&lt;/span&gt;&lt;span class="n"&gt;TEMPLATES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;BACKEND&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.template.backends.django.DjangoTemplates&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DIRS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;BASE_DIR&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;templates&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  &lt;span class="c1"&gt;# Make sure this is set correctly
&lt;/span&gt;        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;APP_DIRS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;OPTIONS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;context_processors&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.template.context_processors.debug&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.template.context_processors.request&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth.context_processors.auth&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.messages.context_processors.messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="c1"&gt;# set the User
&lt;/span&gt;&lt;span class="n"&gt;AUTH_USER_MODEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accounts.User&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next commands create the migration file inside the &lt;code&gt;accounts&lt;/code&gt; application and create the database tables inside the SQLite database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python manage.py makemigrations
python manage.py migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, it is time to create an admin user in terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python manage.py createsuperuser

Username: Admin
Email address: admin@mail.com
Password: 
Password &lt;span class="o"&gt;(&lt;/span&gt;again&lt;span class="o"&gt;)&lt;/span&gt;: 
Superuser created successfully.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember or save these authentication details for future use.&lt;/p&gt;




&lt;p&gt;Django provides a set of built-in authentication views for login, logout, password reset, etc. However, you do need to create templates for the different pages in folder: &lt;code&gt;accounts/templates/registration&lt;/code&gt;. And add for every view a template, like: &lt;code&gt;registration/login.html&lt;/code&gt; for the &lt;code&gt;LoginView&lt;/code&gt; because Django’s built-in authentication system does not provide its own templates — it only provides the views.&lt;/p&gt;




&lt;h3&gt;
  
  
  Setting the authentication URLs and creating custom authentication templates:
&lt;/h3&gt;

&lt;p&gt;The new application was already added to the project when we added the &lt;code&gt;accounts&lt;/code&gt; name to the &lt;code&gt;INSTALLED_APPS&lt;/code&gt; list in &lt;code&gt;settings.py&lt;/code&gt;, but we need to integrate all future url patterns from the &lt;code&gt;accounts&lt;/code&gt; application into the project URL file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# authentication/urls.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;include&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accounts/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accounts.urls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accounts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will include all url patterns of the &lt;code&gt;accounts&lt;/code&gt; application, which will be under the &lt;code&gt;accounts&lt;/code&gt; namespace.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;accounts&lt;/code&gt; application, create a new file called &lt;code&gt;urls.py&lt;/code&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# accounts/urls.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;include&lt;/span&gt;


&lt;span class="n"&gt;app_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accounts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth.urls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;app_name&lt;/code&gt; should be the same as the &lt;code&gt;namespace&lt;/code&gt; attribute inside the &lt;code&gt;path()&lt;/code&gt; function in the authentication &lt;code&gt;urls.py&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;If you start the development server with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python manage.py runserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and navigate to the URL: &lt;code&gt;http://127.0.0.1:8000/accounts/&lt;/code&gt; you will have access to the following URL patterns:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;admin/
accounts/ login/ [name='login']
accounts/ logout/ [name='logout']
accounts/ password_change/ [name='password_change']
accounts/ password_change/done/ [name='password_change_done']
accounts/ password_reset/ [name='password_reset']
accounts/ password_reset/done/ [name='password_reset_done']
accounts/ reset/&amp;lt;uidb64&amp;gt;/&amp;lt;token&amp;gt;/ [name='password_reset_confirm']
accounts/ reset/done/ [name='password_reset_complete']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let's create a test user and navigate to &lt;code&gt;http://127.0.0.1:8000/admin/&lt;/code&gt;. Enter the &lt;code&gt;username&lt;/code&gt; in my example: Admin and the &lt;code&gt;password&lt;/code&gt; you set with the &lt;code&gt;python manage.py createsuperuser&lt;/code&gt; command. &lt;/p&gt;

&lt;p&gt;Under the heading &lt;code&gt;ACCOUNTS&lt;/code&gt; you can add a new &lt;code&gt;user&lt;/code&gt;. You enter the username, twice the password and save it. Then you have to enter additional information such as first and last name and email address and save again. &lt;/p&gt;




&lt;h3&gt;
  
  
  Login and Logout view:
&lt;/h3&gt;

&lt;p&gt;The first template we will create is the &lt;code&gt;base.html&lt;/code&gt; template in the &lt;code&gt;accounts&lt;/code&gt; application. First create a directory inside the &lt;code&gt;accounts&lt;/code&gt; application called: &lt;code&gt;templates&lt;/code&gt; and inside the &lt;code&gt;templates&lt;/code&gt; directory create a file called &lt;code&gt;base.html&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- accounts/templates/base.html --&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;{% block title %}{% endblock %}&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"logo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Authentication&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      {% if request.user.is_authenticated %}
        &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="err"&gt;{%&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="na"&gt;section =&lt;/span&gt;&lt;span class="s"&gt;=&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;dashboard&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt; &lt;span class="err"&gt;%}&lt;/span&gt;&lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"selected"&lt;/span&gt;&lt;span class="err"&gt;{%&lt;/span&gt; &lt;span class="na"&gt;endif&lt;/span&gt; &lt;span class="err"&gt;%}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% url 'accounts:dashboard' %}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;My dashboard&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
      {% endif %}
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      {% if request.user.is_authenticated %}
        Hello {{ request.user.first_name|default:request.user.username }},
        &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"{% url 'accounts:logout' %}"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Logout&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
          {% csrf_token %}
        &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
      {% else %}
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% url 'accounts:login' %}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Log-in&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
      {% endif %}
    &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    {% block content %}
    {% endblock %}
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The URL syntax in my case always has the application name &lt;code&gt;accounts&lt;/code&gt; before the URL name, otherwise the URL name will not be found. If the authentication URL is in a namespace, the application name must be added.&lt;/p&gt;

&lt;p&gt;We will create three additional templates, a login template, a logged_out template and a template after the user has successfully logged in, a dashboard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- accounts/templates/registration/login.html --&amp;gt;&lt;/span&gt;

{% extends "base.html" %}

{% block title %}Log-in{% endblock %}

{% block content %}
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Log-in&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  {% if form.errors %}
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
      Your username and password didn't match.
      Please try again.
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  {% else %}
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
      Please, use the following form to log-in.

    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  {% endif %}
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"login-form"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      {{ form.as_p }}
      {% csrf_token %}
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"next"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"{{ next }}"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Log-in"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
{% endblock %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- accounts/templates/registration/logged_out.html --&amp;gt;&lt;/span&gt;

{% extends "base.html" %}

{% block title %}Logged out{% endblock %}

{% block content %}
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Logged out&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    You have been successfully logged out.
    You can &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% url 'accounts:login' %}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;log-in again&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;.
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{% endblock %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure you use the template name: &lt;code&gt;logged_out&lt;/code&gt; otherwise this template will be ignored.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- accounts/templates/dashboard.html --&amp;gt;&lt;/span&gt;

{% extends "base.html" %}

{% block title %}Dashboard{% endblock %}

{% block content %}
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Dashboard&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Welcome to your dashboard.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{% endblock %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is not done yet. We need to create the view and an URL for the dashboard and set some variables in the &lt;code&gt;settings.py&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# accounts/views.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth.decorators&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;login_required&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.shortcuts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;


&lt;span class="nd"&gt;@login_required&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dashboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dashboard.html&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;section&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dashboard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only an authenticated user has access to this view, we ensure this with the &lt;code&gt;login_required&lt;/code&gt; decorator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# accounts/urls.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;include&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;accounts.views&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dashboard&lt;/span&gt;

&lt;span class="n"&gt;app_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accounts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth.urls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dashboard&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dashboard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;settings.py&lt;/code&gt; file we have to set some variable to ensure the redirection after the login to our dashboard URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# authentication/settings.py
&lt;/span&gt;
&lt;span class="n"&gt;LOGIN_REDIRECT_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accounts:dashboard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;LOGIN_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;login&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;LOGOUT_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;logout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;LOGIN_REDIRECT_URL&lt;/code&gt; leads the way to the dashboard URL pattern inside the &lt;code&gt;accounts&lt;/code&gt; application.&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Django documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.djangoproject.com/en/5.1/topics/auth/default/" rel="noopener noreferrer"&gt;Django authentication system&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.djangoproject.com/en/5.1/topics/auth/default/#module-django.contrib.auth.views" rel="noopener noreferrer"&gt;Authentication Views&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;GitHub repository:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/django/django/blob/main/django/contrib/auth/urls.py" rel="noopener noreferrer"&gt;URL patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/django/django/blob/main/django/contrib/auth/views.py" rel="noopener noreferrer"&gt;views&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>django</category>
      <category>authentication</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to create a simple Flask application</title>
      <dc:creator>DoriDoro</dc:creator>
      <pubDate>Tue, 03 Dec 2024 10:29:20 +0000</pubDate>
      <link>https://dev.to/doridoro/how-to-create-a-simple-flask-application-3ne6</link>
      <guid>https://dev.to/doridoro/how-to-create-a-simple-flask-application-3ne6</guid>
      <description>&lt;h2&gt;
  
  
  Introduction:
&lt;/h2&gt;

&lt;p&gt;For this article, I wanted to create a guide to building a simple Flask app from scratch. This guide is just to get you through the first steps of creating a Flask application.&lt;/p&gt;

&lt;h3&gt;
  
  
  creating a simple Flask app
&lt;/h3&gt;

&lt;p&gt;My favourite IDE is PyCharm. To create a simple Flask application, I have created a new project within PyCharm. The advantage of doing that in PyCharm is, that my IDE creates immediately a virtual environment.&lt;/p&gt;

&lt;p&gt;You have to install Flask in your virtual environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;Flask
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the dependencies in a file (requirements.txt) in root directory with command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip freeze &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Legend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pip freeze&lt;/code&gt;: This command creates a list of all your installed packages in the virtual environment, along with their versions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;gt; requirements.txt&lt;/code&gt;: This part of the command saves all the installed packages and their versions into a file called: &lt;code&gt;requirements.txt&lt;/code&gt;. When this file doesn't exist that command creates this file in root directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To create a simple Flask application, you have to create in your root directory a file named: 'server.py' (you can name it whatever you like but AVOID to name it 'flask.py') and add this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# server.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello_world&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;p&amp;gt;Hello, World!&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Legend:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We import the Flask class at the beginning of our file. An instance of this class will be our WSGI application.&lt;/li&gt;
&lt;li&gt;Next we create an instance of the Flask class.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;route()&lt;/code&gt; decorator tells Flask which URL triggers our function.&lt;/li&gt;
&lt;li&gt;In this simple example, the function returns a paragraph with the content of "Hello World!".&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The next step is to start the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flask &lt;span class="nt"&gt;--app&lt;/span&gt; server run &lt;span class="nt"&gt;--debug&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Legend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;flask&lt;/code&gt;: Is the Flask CLI tool to manage the application.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--app server&lt;/code&gt;: This part specifies that the Flask application is defined in the &lt;code&gt;server.py&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;run&lt;/code&gt;: This command starts the Flask development server and serves the application locally.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--debug&lt;/code&gt;: This part enables the debug mode of the Flask application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that is it, you can go to your browser and enter: &lt;code&gt;http://127.0.0.1:5000&lt;/code&gt; and you should see "Hello World!" displayed on your browser screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://flask.palletsprojects.com/" rel="noopener noreferrer"&gt;Flask documentation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flask</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Django migration operations</title>
      <dc:creator>DoriDoro</dc:creator>
      <pubDate>Tue, 05 Nov 2024 16:51:15 +0000</pubDate>
      <link>https://dev.to/doridoro/django-migration-operations-2c65</link>
      <guid>https://dev.to/doridoro/django-migration-operations-2c65</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# migrations/0002_auto_20240311_1546.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;migrations&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;oc_lettings_site&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0001_initial&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;operations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SeparateDatabaseAndState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;state_operations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RemoveField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;letting&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;database_operations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SeparateDatabaseAndState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;state_operations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RemoveField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;profile&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;database_operations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SeparateDatabaseAndState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;state_operations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DeleteModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;database_operations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AlterModelTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lettings_address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SeparateDatabaseAndState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;state_operations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DeleteModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Letting&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;database_operations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AlterModelTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Letting&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lettings_letting&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SeparateDatabaseAndState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;state_operations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DeleteModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Profile&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;database_operations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AlterModelTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Profile&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;profiles_profile&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Django, migrations are used to alter the database schema and structure when the models in the application change. In your code, the &lt;code&gt;migrations.SeparateDatabaseAndState&lt;/code&gt; method is used to handle scenarios where the in-memory model state operations (&lt;code&gt;state_operations&lt;/code&gt;) need to be decoupled from the actual database schema operations (&lt;code&gt;database_operations&lt;/code&gt;). Here’s a breakdown of what each operation in your migration file is doing:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;migrations.RemoveField&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RemoveField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;letting&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: This operation removes a field named &lt;code&gt;address&lt;/code&gt; from the &lt;code&gt;Letting&lt;/code&gt; model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Effect&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;In terms of the model: After this operation, the &lt;code&gt;Letting&lt;/code&gt; model in Django’s internal state will no longer have the &lt;code&gt;address&lt;/code&gt; field.&lt;/li&gt;
&lt;li&gt;In terms of the database: If executed as a direct migration, this would typically drop the corresponding column (&lt;code&gt;address_id&lt;/code&gt;) in the &lt;code&gt;letting&lt;/code&gt; table. However, here it's specified within &lt;code&gt;state_operations&lt;/code&gt;, so it affects the in-memory model state but not the database schema directly.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;code&gt;migrations.DeleteModel&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DeleteModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: This operation deletes the &lt;code&gt;Address&lt;/code&gt; model entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Effect&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;In terms of the model: The &lt;code&gt;Address&lt;/code&gt; model is removed from Django’s internal state, meaning you can no longer query it or use it in your code.&lt;/li&gt;
&lt;li&gt;In terms of the database: The corresponding table (&lt;code&gt;lettings_address&lt;/code&gt;) would usually be dropped from the database, but in this case, it's handled separately using &lt;code&gt;database_operations&lt;/code&gt; to prevent this drop.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;code&gt;migrations.AlterModelTable&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AlterModelTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lettings_address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: This operation changes the table name for the &lt;code&gt;Address&lt;/code&gt; model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Effect&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;In terms of the database: It renames the existing database table to &lt;code&gt;lettings_address&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;This is included in the &lt;code&gt;database_operations&lt;/code&gt; section because it deals directly with the database schema rather than altering the model's in-memory state.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Summary of the Migration
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;migrations.RemoveField&lt;/code&gt;:&lt;/strong&gt; Removes the &lt;code&gt;address&lt;/code&gt; field from the &lt;code&gt;Letting&lt;/code&gt; model (model state change).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;migrations.DeleteModel&lt;/code&gt;:&lt;/strong&gt; Deletes the &lt;code&gt;Address&lt;/code&gt; model from the internal Django state (model state change), but since &lt;code&gt;database_operations&lt;/code&gt; are defined, the table will not be dropped.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;migrations.AlterModelTable&lt;/code&gt;:&lt;/strong&gt; Changes the table name of the &lt;code&gt;Address&lt;/code&gt; model to &lt;code&gt;lettings_address&lt;/code&gt; (database schema change).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach is useful when you want to change the Django model state but preserve some aspects of the database schema manually. In this case, you are deleting the model &lt;code&gt;Address&lt;/code&gt; from Django but keeping the corresponding table in the database, which is why you explicitly use &lt;code&gt;AlterModelTable&lt;/code&gt; to rename it.&lt;/p&gt;




&lt;p&gt;When dealing with Django migrations, it's common to encounter scenarios where you need to align Django's internal model state with the underlying database schema. In your example, the goal appears to be connecting a new or refactored model to an existing database table while ensuring consistency between the model's representation and the actual database schema.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Remove Fields and Delete the Model?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Django Tracks the Internal State of Models:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Django maintains a representation of your models through its internal migration state. Any changes to your models (e.g., fields, models, or related tables) need to be reflected in this state so that Django knows what the "current" structure should be.&lt;/li&gt;
&lt;li&gt;If you have an &lt;code&gt;Address&lt;/code&gt; model with fields, removing it in Django’s codebase will make Django expect that the model (and its fields) are no longer in use. This expectation needs to be formally expressed through migrations so that the model’s absence is understood.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Separating In-Memory State Changes from Database Schema Changes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By using &lt;code&gt;SeparateDatabaseAndState&lt;/code&gt;, you can alter the &lt;strong&gt;in-memory state&lt;/strong&gt; separately from the &lt;strong&gt;database schema&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Removing fields and deleting the model in the &lt;strong&gt;state_operations&lt;/strong&gt; ensures that Django’s migration system reflects the fact that this model and its fields no longer exist &lt;strong&gt;in your Python code&lt;/strong&gt;. But this does not impact the actual database tables until you apply changes via &lt;strong&gt;database_operations&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Avoiding Conflicts and Data Loss:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Without &lt;code&gt;RemoveField&lt;/code&gt; and &lt;code&gt;DeleteModel&lt;/code&gt;, Django would still have references to the old model (&lt;code&gt;Address&lt;/code&gt;) and its fields. This can lead to schema conflicts when trying to connect a new model to the old database table.&lt;/li&gt;
&lt;li&gt;If you simply renamed the table and tried to associate it with a "new" model without removing the old one, Django’s migration system might get confused and create duplicate tables or fail with errors about field or table name conflicts.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Connecting the 'Old' Database Table to a 'New' Model
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If your end goal is to connect an existing table to a new model, Django needs to see that you’ve removed the old model and are explicitly associating the new one.&lt;/li&gt;
&lt;li&gt;By removing fields and deleting the old model, you’re effectively telling Django:

&lt;ol&gt;
&lt;li&gt;This old model and its fields should no longer be tracked.&lt;/li&gt;
&lt;li&gt;I want to connect a new (or refactored) model to the same table using the &lt;code&gt;AlterModelTable&lt;/code&gt; operation.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Migration Sequence Explanation
&lt;/h3&gt;

&lt;p&gt;Here’s how it breaks down in your specific migration:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Remove the &lt;code&gt;address&lt;/code&gt; field&lt;/strong&gt; from &lt;code&gt;Letting&lt;/code&gt; so that &lt;code&gt;Letting&lt;/code&gt; is no longer linked to the &lt;code&gt;Address&lt;/code&gt; model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delete the &lt;code&gt;Address&lt;/code&gt; model&lt;/strong&gt; in Django’s in-memory state, indicating it’s not used anymore in your application code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rename the table&lt;/strong&gt; (using &lt;code&gt;AlterModelTable&lt;/code&gt;) to keep the database content but update its association.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This pattern ensures that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Django no longer tracks the old &lt;code&gt;Address&lt;/code&gt; model or its fields.&lt;/li&gt;
&lt;li&gt;The table remains in the database under the new name, ready to be re-associated with a different model.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What Happens Without This Sequence?
&lt;/h3&gt;

&lt;p&gt;If you skip the &lt;code&gt;RemoveField&lt;/code&gt; and &lt;code&gt;DeleteModel&lt;/code&gt; operations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Django would still consider the &lt;code&gt;Address&lt;/code&gt; model and its fields part of your project, causing confusion when trying to associate a new model with the same table.&lt;/li&gt;
&lt;li&gt;Schema conflicts can occur when two models (the old &lt;code&gt;Address&lt;/code&gt; and a new one) try to interact with the same table.&lt;/li&gt;
&lt;li&gt;Your database content might get corrupted or cause runtime errors if Django tries to apply changes based on the outdated model state.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Key Takeaway
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;RemoveField&lt;/code&gt; and &lt;code&gt;DeleteModel&lt;/code&gt; are necessary to "clean up" Django’s internal state so it correctly understands the structure you’re aiming for.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;AlterModelTable&lt;/code&gt; then safely renames the table and prepares it for use with the new model, ensuring no data loss.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach ensures a smooth transition of database content to a new model without disrupting Django’s tracking of your application’s schema.&lt;/p&gt;

</description>
      <category>django</category>
    </item>
    <item>
      <title>Django REST Framework (DRF) - permissions</title>
      <dc:creator>DoriDoro</dc:creator>
      <pubDate>Mon, 28 Oct 2024 10:37:23 +0000</pubDate>
      <link>https://dev.to/doridoro/django-rest-framework-drf-permissions-hgk</link>
      <guid>https://dev.to/doridoro/django-rest-framework-drf-permissions-hgk</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In Django REST Framework, permissions are a crucial part of the authentication and authorization mechanism. They determine the level of access that users have to various resources in your API, ensuring that sensitive information is protected and only accessible to authorized users.&lt;/p&gt;

&lt;p&gt;Permissions can be applied at the view level, allowing you to specify who can list, retrieve, create, update, or delete resources. This fine-grained control is essential for building secure applications, as it restricts actions based on user roles, authentication status, or other custom rules.&lt;/p&gt;

&lt;p&gt;DRF provides a set of built-in permission classes that cover common use cases, such as granting access to authenticated users or allowing only admin users to perform certain actions. You can apply these permission classes to individual views or viewsets using the permission_classes attribute.&lt;/p&gt;

&lt;p&gt;For more complex scenarios, DRF's flexibility allows you to define custom permission classes by extending the BasePermission class. By leveraging permissions effectively, you can build robust APIs that cater to different user roles while maintaining data integrity and security.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Setting the permission policy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can choose not to set a general restriction for your project. By doing so, the default settings of the Djnago REST framework will allow unrestricted access.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;DEFAULT_PERMISSION_CLASSES&lt;/code&gt; is set to the permission &lt;code&gt;AllowAny&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DEFAULT_PERMISSION_CLASSES&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
   &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rest_framework.permissions.AllowAny&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your settings.py file you can set a general restriction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;REST_FRAMEWORK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DEFAULT_PERMISSION_CLASSES&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rest_framework.permissions.IsAuthenticated&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The restriction allows only authenticated users to access your entire project.&lt;/p&gt;

&lt;p&gt;You can also set permissions in your view. You can set a general permission in your &lt;code&gt;settings.py&lt;/code&gt; and override the &lt;code&gt;permission_classes&lt;/code&gt; in your view. Or you can set your permissions in your view only.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to apply a permission to a view?&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AccountViewSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewsets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelViewSet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AccountSerializer&lt;/span&gt;
    &lt;span class="n"&gt;permission_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;IsAccountAdminOrReadOnly&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You add the permission into the &lt;code&gt;permission_classed&lt;/code&gt; list in your view.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does the system work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is a difference between the &lt;code&gt;APIView&lt;/code&gt; and the &lt;code&gt;ViewSet&lt;/code&gt; and &lt;code&gt;GenericViewSet&lt;/code&gt;. The &lt;code&gt;APIView&lt;/code&gt; provides a very basic view that you can extend. It doesn't come with automatic permission behavior, so you need to &lt;code&gt;call check_object_permission&lt;/code&gt; manually. On the other hand, ViewSets and Generic Views are built on top of &lt;code&gt;APIView&lt;/code&gt; and come with more built-in functionality. They come pre-equipped with mechanisms to handle permissions for detail routes. Essentially, inside ViewSets and Generic Views, there's logic that automatically handles permission checks when it accesses an object. This is done through the use of mixins and generic classes, making it unnecessary for you to manually invoke &lt;code&gt;check_object_permission&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;ViewSet&lt;/code&gt; and &lt;code&gt;GenericView&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
You don't have to worry about the permissions system, you just have to implement the permissions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;APIView&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
If you are using an &lt;code&gt;APIView&lt;/code&gt; within your method where you get the object, call &lt;code&gt;self.check_object_permissions(self.request, obj)&lt;/code&gt; immediately after you get the object and before you perform any further actions. This will ensure that the permissions checks are properly enforced before any further operations are performed on the object.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With an &lt;code&gt;APIView&lt;/code&gt;, you must explicitly call &lt;code&gt;check_object_permission&lt;/code&gt; to execute &lt;code&gt;has_object_permission&lt;/code&gt; for all permission classes.&lt;/li&gt;
&lt;li&gt;With ViewSets (like &lt;code&gt;ModelViewSet&lt;/code&gt;) or Generic Views (like &lt;code&gt;RetrieveAPIView&lt;/code&gt;), &lt;code&gt;has_object_permission&lt;/code&gt; is executed via &lt;code&gt;check_object_permission&lt;/code&gt; inside a &lt;code&gt;get_object&lt;/code&gt; method out of the box.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;has_object_permission&lt;/code&gt; is never executed for list views (regardless of the view you're extending from) or when the request method is &lt;code&gt;POST&lt;/code&gt; (since the object doesn't exist yet).&lt;/li&gt;
&lt;li&gt;When any &lt;code&gt;has_permission&lt;/code&gt; returns &lt;code&gt;False&lt;/code&gt;, the &lt;code&gt;has_object_permission&lt;/code&gt; doesn't get checked. The request is immediately rejected.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;1. Built-in permissions:&lt;/strong&gt;&lt;br&gt;
Django REST Framework are several built-in permissions that you can use for controlling access to your API views. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here are the main ones:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;AllowAny&lt;/code&gt;&lt;/strong&gt;: This permission class allows unrestricted access, i. e., any user can perform any operation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;IsAuthenticated&lt;/code&gt;&lt;/strong&gt;: This permission only allows access to authenticated users. Anonymous users will be denied access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;IsAdminUser&lt;/code&gt;&lt;/strong&gt;: Grants access only to users with the &lt;code&gt;is_staff&lt;/code&gt; attribute set to &lt;code&gt;True&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;IsAuthenticatedOrReadOnly&lt;/code&gt;&lt;/strong&gt;: Allow read-only access to anonymous users and full access to authenticated users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;DjangoModelPermissions&lt;/code&gt;&lt;/strong&gt;: This permission ties the access level to the model-level permissions set in Django admin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;DjangoModelPermissionsOrAnonReadOnly&lt;/code&gt;&lt;/strong&gt;: Similar to &lt;code&gt;DjangoModelPermissions&lt;/code&gt;, but allows read-only access to anonymous users.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These permissions can be applied to DRF's views and viewsets by setting the &lt;code&gt;permission_classes&lt;/code&gt; attribute. For custom behaviour, you can also create your own permission classes by extending &lt;code&gt;BasePermission&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Custom permissions:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you need a custom permission, you will need to override one of the two &lt;code&gt;BasePermission&lt;/code&gt; methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.has_permission(self, request, view)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.has_object_permission(self, request, view, obj)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;has_permission()&lt;/code&gt;&lt;/strong&gt; method checks whether a user has the permission to perform a certain action on the API resource (view) or endpoint.&lt;/p&gt;

&lt;p&gt;And the &lt;strong&gt;&lt;code&gt;has_object_permission()&lt;/code&gt;&lt;/strong&gt; method checks the permissions on a specific instance or object level. &lt;strong&gt;It is important to note that the &lt;code&gt;has_object_permission()&lt;/code&gt; method is only called if the &lt;code&gt;has_permission()&lt;/code&gt; method has granted access.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The method should return &lt;code&gt;True&lt;/code&gt; to give access. By returning &lt;code&gt;False&lt;/code&gt; a &lt;code&gt;PermissionDenied&lt;/code&gt; exception will be raised.&lt;/p&gt;

&lt;p&gt;To customise the error message that is raised when the permission is denied, you can implement a message attribute in your permission class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;permissions&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomerAccessPermission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BasePermission&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Adding customers not allowed.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_permission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
         &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In general, you will want to create permissions for read or write operations. &lt;/p&gt;

&lt;p&gt;Read operations are actions that retrieve data without modifying it. Methods such as &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;OPTIONS&lt;/code&gt; and &lt;code&gt;HEAD&lt;/code&gt; are considered safe or read operations. These read operations (&lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;OPTIONS&lt;/code&gt; and &lt;code&gt;HEAD&lt;/code&gt;) can be checked using the &lt;code&gt;SAFE_METHODS&lt;/code&gt; constant.&lt;/p&gt;

&lt;p&gt;On the other hand, write operations are actions that change the state on the server by creating, updating or deleting data. Methods such as &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;PUT&lt;/code&gt;, &lt;code&gt;PATCH&lt;/code&gt; and &lt;code&gt;DELETE&lt;/code&gt; fall into this category.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SAFE_METHODS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Check permissions for read-only request
&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Check permissions for write request
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Here are some examples:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IsAuthor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BasePermission&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You have to be the author to update or delete.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_object_permission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;SAFE_METHODS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, I have not overridden the &lt;code&gt;has_permission&lt;/code&gt; method. So the general permission or the view implemented permission is evaluated for access to the view. On the other hand, I want to make sure that only the author of the object (a project, issue or comment) has the permission to update or delete this object. Read operations, for this object, are allowed for other users. If permission is denied, the message attribute is set to deliver a customised message to the user.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserPermission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BasePermission&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_object_permission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_authenticated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retrieve&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;update&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;partial_update&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the permission customisation is again at the object level. The first check is to see if the user is authenticated. If the user is an &lt;code&gt;AnonymousUser&lt;/code&gt; (not authenticated), the permission is denied. The next check allows the user to retrieve, update or partial update their own data by verifying that specific view actions are met. All other view actions are denied.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;- Django REST Framework Links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.django-rest-framework.org/api-guide/permissions" rel="noopener noreferrer"&gt;Permissions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.django-rest-framework.org/api-guide/permissions/#setting-the-permission-policy" rel="noopener noreferrer"&gt;Setting the permission policy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.django-rest-framework.org/api-guide/permissions/#api-reference" rel="noopener noreferrer"&gt;Built-in permissions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.django-rest-framework.org/api-guide/permissions/#custom-permissions" rel="noopener noreferrer"&gt;Custom permissions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>django</category>
      <category>api</category>
    </item>
    <item>
      <title>Django REST Framework (DRF) - ModelViewSets</title>
      <dc:creator>DoriDoro</dc:creator>
      <pubDate>Thu, 24 Oct 2024 15:38:40 +0000</pubDate>
      <link>https://dev.to/doridoro/django-rest-framework-drf-modelviewsets-2ich</link>
      <guid>https://dev.to/doridoro/django-rest-framework-drf-modelviewsets-2ich</guid>
      <description>&lt;h2&gt;
  
  
  Introduction:
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;ModelViewSet&lt;/code&gt; in Django REST Framework (DRF) is a powerful view class that provides a set of common actions for working with models through an API. It combines the functionality of Django's generic views and viewsets, enabling you to quickly build CRUD (Create, Read, Update, Delete) APIs for your models without needing to manually define each individual action.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key features of ModelViewSet:
&lt;/h3&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pre-built CRUD actions:&lt;/strong&gt; It automatically provides the following actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;list&lt;/code&gt; - &lt;code&gt;GET&lt;/code&gt;: Retrieves multiple objects of model instances.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;retrieve&lt;/code&gt; - &lt;code&gt;GET&lt;/code&gt;: Retrieves a single model instance.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;create&lt;/code&gt; - &lt;code&gt;POST&lt;/code&gt;: Creates a new model instance.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;update&lt;/code&gt; - &lt;code&gt;PUT&lt;/code&gt;: Updates an existing model instance.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;partial_update&lt;/code&gt; - &lt;code&gt;PATCH&lt;/code&gt;: Partially updates an existing model instance.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;destroy&lt;/code&gt; - &lt;code&gt;DELETE&lt;/code&gt;: Deletes a model instance.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic routing:&lt;/strong&gt; When you use &lt;code&gt;ModelViewSet&lt;/code&gt; with DRF's routers, URL routes are automatically generated for these actions.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexibility:&lt;/strong&gt; You can easily customize or extend the default behavior by overriding methods or adding custom actions.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;queryset&lt;/code&gt; and &lt;code&gt;serializer_class&lt;/code&gt; attributes are essential for using a ModelViewSet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is a simple example of a &lt;code&gt;ModelViewSet&lt;/code&gt; from the DRF documentation:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/views.py
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AccountViewSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewsets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelViewSet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AccountSerializer&lt;/span&gt;
    &lt;span class="n"&gt;permission_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;IsAccountAdminOrReadOnly&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  How can you customize your &lt;code&gt;ModelViewSet&lt;/code&gt; and what do you need to be aware of?
&lt;/h3&gt;

&lt;p&gt;You can use any of the standard attributes or method overrides that are provided by the &lt;code&gt;GenericAPIView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is a list of some of the key ones:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;Standard Attributes:&lt;/em&gt;
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;queryset&lt;/strong&gt;: The queryset that should be used for returning objects from this view.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;serializer_class&lt;/strong&gt;: Specifies the serializer class to use for validating and deserializing input, and for serializing output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;lookup_field&lt;/strong&gt;: The model field that should be used to lookup objects. Defaults to 'pk'.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pagination_class&lt;/strong&gt;: Pagination class to be used to paginate the list of objects.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;Standard Methods:&lt;/em&gt;
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;get_queryset()&lt;/strong&gt;: Returns the queryset that will be used to retrieve objects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_serializer_class()&lt;/strong&gt;: Returns the class to use for the serializer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_serializer()&lt;/strong&gt;: Returns the serializer instance that should be used for validating and deserializing input.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_object()&lt;/strong&gt;: Returns the object that this view is displaying.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_serializer_context()&lt;/strong&gt;: Can be overridden to change the context dictionary passed to the serializer instance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;filter_queryset(queryset)&lt;/strong&gt;: Given a queryset, filter it based on the view’s filtering configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;paginate_queryset(queryset)&lt;/strong&gt;: Paginate the given queryset, and return a page object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_pagination_response(data)&lt;/strong&gt;: Return a paginated style response for the given output data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_view_name()&lt;/strong&gt;: Returns the view name that should be used as the title of the view.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_view_description()&lt;/strong&gt;: Returns the description to be used by browsable APIs and other descriptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_renderer_context()&lt;/strong&gt;: Creates a context dictionary for rendering.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;strong&gt;1.) The &lt;code&gt;get_queryset()&lt;/code&gt; method is overridden by the DRF documentation in this example.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/views.py
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AccountViewSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewsets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelViewSet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AccountSerializer&lt;/span&gt;
    &lt;span class="n"&gt;permission_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;IsAccountAdminOrReadOnly&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The DRF documentation shows this example because if you override the &lt;code&gt;get_queryset()&lt;/code&gt; method, you need to be aware that the &lt;code&gt;basename&lt;/code&gt; in the router registry has to be set to a value. Normally DRF will automatically create the &lt;code&gt;basename&lt;/code&gt; and set the value. It takes the values from the model name and creates the &lt;code&gt;basename&lt;/code&gt; with the model name in lower case. In this case, you must set the &lt;code&gt;basename&lt;/code&gt; to a value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# project/urls.py
&lt;/span&gt;
   &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;routers&lt;/span&gt;

   &lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;routers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SimpleRouter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;accounts&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AccountViewSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;basename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;account&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/views.py
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AccountViewSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewsets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelViewSet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AccountSerializer&lt;/span&gt;
    &lt;span class="n"&gt;permission_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;IsAccountAdminOrReadOnly&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the &lt;code&gt;basename&lt;/code&gt; is automatically set to &lt;code&gt;basename='account'&lt;/code&gt;. It takes the model name of the &lt;code&gt;queryset&lt;/code&gt; attribute &lt;code&gt;Account&lt;/code&gt; and create a lower case name.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;2.) Having multiple serializer classes:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using a mixin is one way of generating multiple serializer classes. Why do I want to create multiple serializers?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Separation of Concerns&lt;/strong&gt;: Different parts of an application may require different subsets of data. Multiple serializers allow you to fetch only the necessary data for each context, separating concerns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient Data Handling&lt;/strong&gt;: By defining serializers specifically tailored to different API endpoints or logic, you can optimize data serialization/deserialization, improving performance and efficiency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: Having different serializers lets you expose only the necessary fields to users who do not need full access to the data. This minimizes exposure to sensitive information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility&lt;/strong&gt;: Some API endpoints might need to validate data differently or handle it in a specific manner. Custom serializers provide the flexibility to add custom validation logic as needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: Breaking down complex functionalities into simpler, smaller serializers makes the codebase easier to maintain. Each serializer handles a well-defined responsibility.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The serializer mixin can look like this:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# mixins.py
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SerializerClassMixin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;serializer_create_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;serializer_detail_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;serializer_list_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_serializer_class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;create&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serializer_create_class&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retrieve&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serializer_detail_class&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;list&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serializer_list_class&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_serializer_class&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a Django REST framework project, the &lt;code&gt;self.action&lt;/code&gt; is an attribute that represents the current action being performed by a viewset. It is automatically set by Django REST framework based on the HTTP method of the request and the viewset's configuration.&lt;/p&gt;

&lt;p&gt;This Mixin is designed to allow different serializers to be used in different situations within a single viewset:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;serializer_create_class:&lt;/strong&gt; Used when the create action is being performed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;serializer_detail_class:&lt;/strong&gt; Used for the retrieve action, accessing a single instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;serializer_list_class:&lt;/strong&gt; Used when listing a collection of instances with the list action.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By using &lt;code&gt;self.action&lt;/code&gt;, the &lt;code&gt;get_serializer_class()&lt;/code&gt; method dynamically chooses which serializer class to use based on the current action. This can be very helpful in a scenario where you need different serializers for different operations on the same resource.&lt;/p&gt;

&lt;p&gt;Here is an example of a view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# views.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework.permissions&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;IsAuthenticated&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework.viewsets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ModelViewSet&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;api.models.project&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Project&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;api.permissions&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;IsAuthor&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;api.serializers.project&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ProjectCreateSerializer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ProjectListSerializer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ProjectDetailSerializer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;api.views.mixins&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SerializerClassMixin&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProjectViewSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SerializerClassMixin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ModelViewSet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ProjectCreateSerializer&lt;/span&gt;
    &lt;span class="n"&gt;serializer_create_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ProjectCreateSerializer&lt;/span&gt;
    &lt;span class="n"&gt;serializer_detail_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ProjectDetailSerializer&lt;/span&gt;
    &lt;span class="n"&gt;serializer_list_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ProjectListSerializer&lt;/span&gt;
    &lt;span class="n"&gt;permission_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;IsAuthor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IsAuthenticated&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;_project&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="nd"&gt;@property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;project&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_project&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_project&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contributors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_project&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_queryset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# use order_by to avoid the warning for the pagination
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;order_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created_time&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# save the author as author and as contributor (request.user)
&lt;/span&gt;        &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contributors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;ProjectViewSet&lt;/code&gt; we integrate the serializer mixin (&lt;code&gt;SerializerClassMixin&lt;/code&gt;) to be able to use all the different serializers to list, create and display a detailed serializer. &lt;/p&gt;

&lt;p&gt;We need to specify the &lt;code&gt;basename&lt;/code&gt; in the URL pattern because we have overridden the &lt;code&gt;get_queryset()&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# urls.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework_nested&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;routers&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;api.views.project&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ProjectViewSet&lt;/span&gt;

&lt;span class="n"&gt;app_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;routers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DefaultRouter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;projects&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ProjectViewSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;basename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;project&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Finally, there are the different serializers:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# serializers.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;api.models.project&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Project&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProjectCreateSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelSerializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Project&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;project_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;view&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;project_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;project_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ValidationError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Attention! This project exists already.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProjectListSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelSerializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Project&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;author&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contributors&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProjectDetailSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelSerializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Project&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created_time&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;project_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;author&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contributors&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Link:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.django-rest-framework.org/api-guide/viewsets/#modelviewset" rel="noopener noreferrer"&gt;ModelViewSets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.django-rest-framework.org/api-guide/viewsets/#genericviewset" rel="noopener noreferrer"&gt;GenericViewSet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/DoriDoro/SoftDesk_api" rel="noopener noreferrer"&gt;GitHub repository: SoftDesk&lt;/a&gt; (Project 10 OpenClassrooms Path - SoftDesk -- create a secure RESTful API using Django REST framework)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
