<?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: Serhat Teker</title>
    <description>The latest articles on DEV Community by Serhat Teker (@serhatteker).</description>
    <link>https://dev.to/serhatteker</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%2F188904%2Fc0e1e060-5f43-474d-b5f0-ee4a621b4547.jpg</url>
      <title>DEV Community: Serhat Teker</title>
      <link>https://dev.to/serhatteker</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/serhatteker"/>
    <language>en</language>
    <item>
      <title>Automate Python Virtual Environment with a Script</title>
      <dc:creator>Serhat Teker</dc:creator>
      <pubDate>Fri, 01 Apr 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/serhatteker/automate-python-virtual-environment-with-a-script-2748</link>
      <guid>https://dev.to/serhatteker/automate-python-virtual-environment-with-a-script-2748</guid>
      <description>&lt;h2&gt;
  
  
  Issue
&lt;/h2&gt;

&lt;p&gt;There are 2 things that annoy me every time when I create a python virtual environment.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;/p&gt;

&lt;p&gt;Below instructions are related to the python's default &lt;strong&gt;venv&lt;/strong&gt;  module.&lt;/p&gt;

&lt;p&gt;If you are using any other version/virtual environment management tools,&lt;br&gt;
like &lt;strong&gt;Conda&lt;/strong&gt;, &lt;strong&gt;Poetry&lt;/strong&gt;, &lt;strong&gt;Pyenv&lt;/strong&gt;, below doesn't apply.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first one is that I have to type every time:&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="nv"&gt;$ &lt;/span&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv ./.venv
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; ./.venv/bin/activate
&lt;span class="c"&gt;# or&lt;/span&gt;
&lt;span class="c"&gt;# $ source ./.venv/bin/activate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second thing is that after installing any &lt;em&gt;package&lt;/em&gt; I'm getting below &lt;code&gt;pip&lt;/code&gt;&lt;br&gt;
version &lt;em&gt;WARNING&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;WARNING: You are using pip version 21.1.1&lt;span class="p"&gt;;&lt;/span&gt; however, version 22.0.4 is available. You should consider upgrading via the &lt;span class="s1"&gt;'/path/to/project/.venv/bin/python3.8 -m pip install --upgrade pip'&lt;/span&gt; command.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is an expected behavior, 'cause &lt;code&gt;python -m venv&lt;/code&gt; calls &lt;code&gt;python -m ensurepip&lt;/code&gt; to install &lt;code&gt;pip&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And there is no way to globally upgrade since &lt;code&gt;pip&lt;/code&gt; is installed with &lt;em&gt;bundled&lt;/em&gt; version which is almost out of date. You can check it like below:&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="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;ensurepip&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ensurepip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="s"&gt;'21.1.1'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though you can't upgrade to the latest version with below commands as mentioned in &lt;a href="https://docs.python.org/3/library/ensurepip.html#module-ensurepip"&gt;ensurepip&lt;/a&gt; doc:&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="nv"&gt;$ &lt;/span&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; ensurepip &lt;span class="nt"&gt;--upgrade&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because &lt;code&gt;ensurepip&lt;/code&gt; will only install the &lt;em&gt;bundled&lt;/em&gt; version even with the &lt;code&gt;--upgrade&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;There is no official option to update the &lt;em&gt;bundled&lt;/em&gt; &lt;code&gt;pip&lt;/code&gt; and &lt;code&gt;setuptools&lt;/code&gt;, yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;Okay, since we are developers, we always find our ways and produce our solutions that suits our needs.&lt;/p&gt;

&lt;p&gt;My solution comes from a shell script. You can put it in your shell configuration file, like &lt;code&gt;.zshrc&lt;/code&gt;, &lt;code&gt;.bashrc&lt;/code&gt;, &lt;code&gt;config.fish&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With below function, when I enter &lt;code&gt;ve&lt;/code&gt; command, it will create my virtual environment — if it doesn't exist, activate it and upgrade to the latest &lt;code&gt;pip&lt;/code&gt; version.&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="c"&gt;# 0. If not already in virtualenv:&lt;/span&gt;
&lt;span class="c"&gt;# 0.1. If virtualenv already exists activate it,&lt;/span&gt;
&lt;span class="c"&gt;# 0.2. If not create it with global packages, update pip then activate it&lt;/span&gt;
&lt;span class="c"&gt;# 1. If already in virtualenv: just give info&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Usage:&lt;/span&gt;
&lt;span class="c"&gt;# $ ve&lt;/span&gt;
&lt;span class="c"&gt;# or&lt;/span&gt;
&lt;span class="c"&gt;# $ ve python3.9&lt;/span&gt;
&lt;span class="c"&gt;# or&lt;/span&gt;
&lt;span class="c"&gt;# $ ve python3.9 ./.venv-diff&lt;/span&gt;
ve&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;py&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;python3&lt;/span&gt;&lt;span class="p"&gt;.8&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;venv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;./.venv&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;venv&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/bin/activate"&lt;/span&gt;

    &lt;span class="c"&gt;# If not already in virtualenv&lt;/span&gt;
    &lt;span class="c"&gt;# $VIRTUAL_ENV is being set from $venv/bin/activate script&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VIRTUAL_ENV&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;venv&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Creating and activating virtual environment &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;venv&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
            &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;py&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; venv &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;venv&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--system-site-package&lt;/span&gt;
            &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"export PYTHON=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;py&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;bin&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;    &lt;span class="c"&gt;# overwrite ${python} on .zshenv&lt;/span&gt;
            &lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;bin&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
            &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Upgrading pip"&lt;/span&gt;
            &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;py&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; pip
        &lt;span class="k"&gt;else
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Virtual environment  &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;venv&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; already exists, activating..."&lt;/span&gt;
            &lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;bin&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;fi
    else
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Already in a virtual environment!"&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function may seem complex, so let me walk through it line by line.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$1&lt;/code&gt; is the first argument, the desired python version, &lt;code&gt;$2&lt;/code&gt; is the second argument which is virtual environment's name/directory, provided to the function &lt;code&gt;ve()&lt;/code&gt;. If no arguments provided function will use default values: &lt;code&gt;python3.8&lt;/code&gt; and &lt;code&gt;.venv&lt;/code&gt;. You can these default values according to your needs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ve&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;py&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;python3&lt;/span&gt;&lt;span class="p"&gt;.8&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;venv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;./.venv&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;venv&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/bin/activate"&lt;/span&gt;
    ...
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can provide positional arguments like:&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="nv"&gt;$ &lt;/span&gt;ve python3.9 .venv2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After creating local &lt;code&gt;variables&lt;/code&gt;, if we are already in a &lt;em&gt;virtual environment&lt;/em&gt;, it just gives "already in a virtual environment" message. It decides this whether we're in a &lt;em&gt;virtual environment&lt;/em&gt; by checking if there is a &lt;strong&gt;environment variable&lt;/strong&gt; called &lt;code&gt;$VIRTUAL_ENV&lt;/code&gt; exported from &lt;code&gt;activate&lt;/code&gt; — &lt;code&gt;.venv/bin/activate&lt;/code&gt;, script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ve&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    ...

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VIRTUAL_ENV&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        ...
    &lt;span class="k"&gt;else
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Already in a virtual environment!"&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we're not in a &lt;em&gt;virtual environment&lt;/em&gt;, it will control if &lt;code&gt;.venv&lt;/code&gt; directory exists. If the directory exists, it will be activated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ve&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    ...

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VIRTUAL_ENV&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;venv&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
            ...
        &lt;span class="k"&gt;else
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Virtual environment  &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;venv&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; already exists, activating..."&lt;/span&gt;
            &lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;bin&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;fi

    else&lt;/span&gt;
        ...
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, if &lt;code&gt;.venv&lt;/code&gt; directory does not exist, it will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create virtual environment &lt;code&gt;.venv&lt;/code&gt; with global packages included (line 7),&lt;/li&gt;
&lt;li&gt;Add exporting desired python version environment variable into &lt;code&gt;activate&lt;/code&gt; script (line 8)&lt;/li&gt;
&lt;li&gt;Activate the virtual environment (line 9)&lt;/li&gt;
&lt;li&gt;Upgrade the current &lt;code&gt;pip&lt;/code&gt; version to the latest one (line 11)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ve&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    ...

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VIRTUAL_ENV&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;venv&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Creating and activating virtual environment &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;venv&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
            &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;py&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; venv &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;venv&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--system-site-package&lt;/span&gt;
            &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"export PYTHON=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;py&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;bin&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;    &lt;span class="c"&gt;# overwrite ${python} on .zshenv&lt;/span&gt;
            &lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;bin&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
            &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Upgrading pip"&lt;/span&gt;
            &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;py&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; pip
        &lt;span class="k"&gt;else&lt;/span&gt;
            ...
        &lt;span class="k"&gt;fi

    else&lt;/span&gt;
        ...
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You probably don't need &lt;em&gt;line 8&lt;/em&gt;, I'm adding this, because using this environment variable in my other &lt;code&gt;aliases&lt;/code&gt;/&lt;code&gt;functions&lt;/code&gt;/&lt;code&gt;binaries&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In the end, with this shell script we solved our annoying &lt;em&gt;bugs&lt;/em&gt; and make us more productive again.&lt;/p&gt;

&lt;p&gt;You can find this script in this &lt;a href="https://gist.github.com/SerhatTeker/899461f3bcf7b82e115f3ff01a49b21d"&gt;gist&lt;/a&gt; or in &lt;a href="https://github.com/SerhatTeker/dotfiles/blob/cef51a994dda18935006d6bc3055bf7eb58fe43d/zsh/.functions#L327-L362"&gt;function&lt;/a&gt; from my &lt;a href="https://github.com/serhatteker/dotfiles"&gt;dotfiles&lt;/a&gt; repo.&lt;/p&gt;

&lt;p&gt;All done!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Changelog&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2022-05-10 : Added gist and dotfiles link references&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;surepip&lt;/p&gt;

</description>
      <category>python</category>
      <category>bash</category>
      <category>zsh</category>
    </item>
    <item>
      <title>Django REST Filtering Tutorial - Filter with Current User (Part II)</title>
      <dc:creator>Serhat Teker</dc:creator>
      <pubDate>Thu, 24 Mar 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/serhatteker/django-rest-filtering-tutorial-filter-with-current-user-part-ii-hb0</link>
      <guid>https://dev.to/serhatteker/django-rest-filtering-tutorial-filter-with-current-user-part-ii-hb0</guid>
      <description>&lt;h2&gt;
  
  
  Entrée
&lt;/h2&gt;

&lt;p&gt;We've seen in &lt;a href="https://tech.serhatteker.com/post/2022-03/django-rest-filtering-tutorial-part-1/"&gt;part I&lt;/a&gt; how to setup our &lt;a href="https://github.com/SerhatTeker/django-rest-filtering-tutorial"&gt;repo&lt;/a&gt;, sending HTTP requests and some fundamental concepts about &lt;a href="https://www.django-rest-framework.org/"&gt;Django REST&lt;/a&gt; &lt;strong&gt;filtering&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this second part we will limit our views/querysets/objects with &lt;code&gt;user&lt;/code&gt;, more precisely with current authenticated user.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;authors&lt;/em&gt; list endpoint — &lt;code&gt;/authors/&lt;/code&gt;, displays all items regardless of whether they belong to current user or not.&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="nv"&gt;$ &lt;/span&gt;http :8000/authors

&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"first_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name1"&lt;/span&gt;,
        &lt;span class="s2"&gt;"full_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name1 Surname1"&lt;/span&gt;,
        &lt;span class="s2"&gt;"id"&lt;/span&gt;: 1,
        &lt;span class="s2"&gt;"last_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Surname1"&lt;/span&gt;,
        &lt;span class="s2"&gt;"user"&lt;/span&gt;: 1
    &lt;span class="o"&gt;}&lt;/span&gt;,
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"first_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"full_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name2 Surname2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"id"&lt;/span&gt;: 2,
        &lt;span class="s2"&gt;"last_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Surname2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"user"&lt;/span&gt;: null
    &lt;span class="o"&gt;}&lt;/span&gt;,
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"first_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name3"&lt;/span&gt;,
        &lt;span class="s2"&gt;"full_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name3 Surname3"&lt;/span&gt;,
        &lt;span class="s2"&gt;"id"&lt;/span&gt;: 3,
        &lt;span class="s2"&gt;"last_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Surname3"&lt;/span&gt;,
        &lt;span class="s2"&gt;"user"&lt;/span&gt;: 3
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How can we change that behavior in order to return items only owned by current authenticated user?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;/p&gt;

&lt;p&gt;You can find the code we're working on this tutorial series in this repository: &lt;a href="https://github.com/SerhatTeker/django-rest-filtering-tutorial"&gt;django-rest-filtering-tutorial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You don't need to download and setup the repository in order to follow this series, however I'd like to encorauge to do so, since while you play you learn better as always.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Current User
&lt;/h2&gt;

&lt;p&gt;This is one common filter usage which is filtering the queryset to ensure only relevant results to the current authenticated user who makes the request are returned.&lt;/p&gt;

&lt;p&gt;For this purpose we will override default &lt;a href="https://github.com/encode/django-rest-framework/blob/0323d6f8955f987771269506ca5da461e2e7a248/rest_framework/generics.py#L48-L73"&gt;get_queryset&lt;/a&gt; as we've seen in &lt;a href="https://tech.serhatteker.com/post/2022-03/django-rest-filtering-tutorial-part-1/#default-filtering"&gt;default filtering&lt;/a&gt; in detail.&lt;/p&gt;

&lt;p&gt;Let's filter &lt;strong&gt;authors&lt;/strong&gt; list endpoint with the &lt;em&gt;current user&lt;/em&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="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;generics&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;src.authors.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;src.authors.serializers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AuthorSerializer&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthorListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListAPIView&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;AuthorSerializer&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="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="s"&gt;"""
        This view returns a list of all the authors for the currently
        authenticated user.

        Returns empyt list if user Anonymous
        """&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&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="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&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_anonymous&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;Author&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="nb"&gt;filter&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;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;Author&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="n"&gt;none&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;/p&gt;

&lt;p&gt;In our &lt;a href="https://github.com/SerhatTeker/django-rest-filtering-tutorial"&gt;repo&lt;/a&gt; we use &lt;code&gt;ModelViewSet&lt;/code&gt; for &lt;strong&gt;authors&lt;/strong&gt; endpoint. You can update it like above.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can look at related &lt;code&gt;AuthorSerializer&lt;/code&gt; and &lt;code&gt;Author&lt;/code&gt; model in the &lt;a href="https://github.com/SerhatTeker/django-rest-filtering-tutorial"&gt;repo&lt;/a&gt;, however for easy access I put them there as well. In order to examine them just expand the below section.&lt;/p&gt;

&lt;p&gt;
  AuthorSerializer and Author model
  &lt;p&gt;&lt;code&gt;AuthorSerializer&lt;/code&gt; from &lt;code&gt;src/authors/serializers.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;# src/authors/serializers.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&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="nn"&gt;src.authors.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthorSerializer&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;Author&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="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"last_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"full_name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;read_only_fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"full_name"&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;Author&lt;/code&gt; model from &lt;code&gt;src/authors/model.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;# src/authors/model.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&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="nn"&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="n"&gt;USER&lt;/span&gt; &lt;span class="o"&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Author&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="s"&gt;"""
    Author entity

    Provides first_name and last_name, since he/she can write unter a Pen Name
    """&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="n"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&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;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;DO_NOTHING&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="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;first_name&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;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;last_name&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;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;255&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;__str__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&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="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;

    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&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="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Now we can make a successful request by including the username and password of one of the users we created in &lt;code&gt;populate_db.py&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;&lt;span class="nv"&gt;$ &lt;/span&gt;http &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"User1:1234"&lt;/span&gt; &lt;span class="s2"&gt;":8000/authors/"&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"first_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name1"&lt;/span&gt;,
        &lt;span class="s2"&gt;"full_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name1 Surname1"&lt;/span&gt;,
        &lt;span class="s2"&gt;"id"&lt;/span&gt;: 1,
        &lt;span class="s2"&gt;"last_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Surname1"&lt;/span&gt;,
        &lt;span class="s2"&gt;"user"&lt;/span&gt;: 1
    &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can recognize now it returns only one object instead of three.&lt;/p&gt;

&lt;p&gt;And if you we make a request as &lt;strong&gt;anonymous&lt;/strong&gt; or unauthenticated user, we will get:&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="nv"&gt;$ &lt;/span&gt;http &lt;span class="s2"&gt;":8000/authors/"&lt;/span&gt;

&lt;span class="o"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  User Authentication and Permission
&lt;/h3&gt;

&lt;p&gt;It's usually better idea to separate &lt;code&gt;authentication&lt;/code&gt; and &lt;code&gt;permission&lt;/code&gt; layer/logic. For this goal you can use &lt;code&gt;authentication_classes&lt;/code&gt; and &lt;code&gt;permission_classes&lt;/code&gt; on per-view or per-viewset basis;&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="nn"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;generics&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rest_framework.authentication&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SessionAuthentication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BasicAuthentication&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&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="nn"&gt;src.authors.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;src.authors.serializers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AuthorSerializer&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthorListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListAPIView&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;AuthorSerializer&lt;/span&gt;
    &lt;span class="n"&gt;authentication_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;SessionAuthentication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BasicAuthentication&lt;/span&gt;&lt;span class="p"&gt;)&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;IsAuthenticated&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="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="s"&gt;"""
        This view returns a list of all the authors for the currently
        authenticated user.
        """&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Author&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="nb"&gt;filter&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;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another method is setting the default authentication globally, using the &lt;code&gt;DEFAULT_AUTHENTICATION_CLASSES&lt;/code&gt; setting:&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;# settings.py
&lt;/span&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="s"&gt;"DEFAULT_AUTHENTICATION_CLASSES"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s"&gt;"rest_framework.authentication.BasicAuthentication"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"rest_framework.authentication.SessionAuthentication"&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;blockquote&gt;
&lt;p&gt;INFO&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://github.com/SerhatTeker/django-rest-filtering-tutorial"&gt;repo&lt;/a&gt; these are disabled, you can set them globally if you comment out the related lines at the end of the &lt;strong&gt;setting.py&lt;/strong&gt; file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And now our view will look cleaner like 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;# src/authors/views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;generics&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;src.authors.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;src.authors.serializers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AuthorSerializer&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthorListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListAPIView&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;AuthorSerializer&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="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="s"&gt;"""
        This view returns a list of all the authors for the currently
        authenticated user.
        """&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Author&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="nb"&gt;filter&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="bp"&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;For more info about &lt;code&gt;authentication&lt;/code&gt; and &lt;code&gt;permissions&lt;/code&gt; you can look at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.django-rest-framework.org/api-guide/authentication/"&gt;drf authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.django-rest-framework.org/api-guide/permissions/"&gt;drf permissions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Custom FilterBackend
&lt;/h2&gt;

&lt;p&gt;There is another method which is that we can also provide our own generic filtering backend.&lt;/p&gt;

&lt;p&gt;To do so override &lt;code&gt;BaseFilterBackend&lt;/code&gt; class, and override the &lt;code&gt;.filter_queryset&lt;/code&gt; method. The method should return a new, filtered queryset.&lt;/p&gt;

&lt;p&gt;As well as allowing clients to perform searches and filtering, generic filter backends can be useful to restrict which objects should be visible to any given request or user.&lt;/p&gt;

&lt;p&gt;Let's write &lt;code&gt;IsOwnerFilterBackend&lt;/code&gt; for our current user logic:&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;# src/authors/filters.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django_filters&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;filters&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IsOwnerFilterBackend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseFilterBackend&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;"""
    Filter that only allows users to get their own objects
    """&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;filter_queryset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&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;queryset&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;queryset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;owner&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this filter to our &lt;code&gt;AuthorListView&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;# src/authors/views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;generics&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django_filters&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;rest_framework&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;filters&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;src.authors.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;src.authors.serializers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AuthorSerializer&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;src.authors.filters&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;IsOwnerFilterBackend&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthorListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListAPIView&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;AuthorSerializer&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;Author&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="nb"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;filter_backends&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IsOwnerFilterBackend&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
    &lt;span class="n"&gt;filterset_fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&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;Now if we send request we only receive related authors to the user.&lt;/p&gt;

&lt;p&gt;One side note to this method; as we've already seen above, we can achieve the same behavior by overriding &lt;code&gt;get_queryset()&lt;/code&gt; on the view, but using a filter backend allows us to more easily add this restriction to multiple views, or to apply it across the entire &lt;strong&gt;API&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We can also make this filter backend as our global default backend:&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;# settings.py
&lt;/span&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="s"&gt;"DEFAULT_FILTER_BACKENDS"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src.authors.filters.IsOwnerFilterBackend"&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial we learned how to filter the queryset to ensure only relevant results to the current authenticated user who makes the request are returned.&lt;/p&gt;

&lt;p&gt;See you in the next part of this tutorial series.&lt;/p&gt;

&lt;p&gt;All done!&lt;/p&gt;

</description>
      <category>django</category>
      <category>djangorestframework</category>
      <category>filter</category>
      <category>search</category>
    </item>
    <item>
      <title>Django REST Filtering Tutorial - Intro (Part I)</title>
      <dc:creator>Serhat Teker</dc:creator>
      <pubDate>Thu, 17 Mar 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/serhatteker/django-rest-filtering-tutorial-intro-part-i-2e2l</link>
      <guid>https://dev.to/serhatteker/django-rest-filtering-tutorial-intro-part-i-2e2l</guid>
      <description>&lt;h2&gt;
  
  
  Entrée
&lt;/h2&gt;

&lt;p&gt;In this tutorial I'd like to aim to collect some of &lt;strong&gt;Django REST&lt;/strong&gt; &lt;strong&gt;filtering&lt;/strong&gt; concepts and common examples that I use and teach usually. Some of them can be found in official Django REST documentation, however I'm going to walk by a sample repository.&lt;/p&gt;

&lt;p&gt;The repo consists as less code as possible which implies it's not designed according to best practices such as &lt;em&gt;api versioning&lt;/em&gt; (&lt;code&gt;api/v1&lt;/code&gt;), &lt;a href="https://12factor.net/"&gt;The Twelve Factor App&lt;/a&gt; etc.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;/p&gt;

&lt;p&gt;You can find the code we're working on this tutorial series in this repository: &lt;a href="https://github.com/SerhatTeker/django-rest-filtering-tutorial"&gt;django-rest-filtering-tutorial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You don't need to download and setup the repository in order to follow this series, however I'd like to encorauge to do so, since while you play you learn better as always.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Setup Repo
&lt;/h2&gt;

&lt;p&gt;As mentioned above you don't need to setup the repo however if you like to, —I suggest as well, run below commands:&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="c"&gt;# Create virtual environment named .venv&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv ./.venv
&lt;span class="c"&gt;# Activate the virtual environment&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ./.venv/bin/activate
&lt;span class="c"&gt;# Install python packages&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;span class="c"&gt;# Create db, make migrations and seed database with some dummy data&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;python populate_db.py
&lt;span class="c"&gt;# Run development server&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;python manage.py runserver 8000
&lt;span class="c"&gt;# or&lt;/span&gt;
&lt;span class="c"&gt;# ./manage.py runserver 8000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;INFO&lt;/p&gt;

&lt;p&gt;You don't need to give &lt;code&gt;8000&lt;/code&gt; port since it's &lt;strong&gt;8default port&lt;/strong&gt; but I always prefer &lt;strong&gt;verbosity&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also another option is that you can use &lt;a href="https://www.gnu.org/software/make/"&gt;gnu make&lt;/a&gt; and simply run:&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="nv"&gt;$ &lt;/span&gt;make start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;strong&gt;make&lt;/strong&gt; target will run all commands above together so it will setup the repository and run development server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending HTTP Requests
&lt;/h2&gt;

&lt;p&gt;I'm going to use &lt;a href="https://httpie.io/"&gt;httpie&lt;/a&gt; for &lt;strong&gt;HTTP&lt;/strong&gt; &lt;em&gt;requests&lt;/em&gt; since it's more human-usable —or let's say more dev-friendly; it provides colorful syntax highlighting (like pretty JSON outputs), persistent sessions, capability of downloading files etc. and it's written in &lt;strong&gt;Python&lt;/strong&gt; but you can use &lt;a href="https://curl.se/"&gt;curl&lt;/a&gt; as well:&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="nv"&gt;$ &lt;/span&gt;http GET http://localhost:8000/authors/
&lt;span class="c"&gt;# or with less keystroke, it's same as above&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;http :8000/authors/
&lt;span class="c"&gt;# curl equivalent&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;curl http://localhost:8000/authors/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more info you can look at &lt;a href="https://httpie.io/docs/cli"&gt;httpie doc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CeRZvje---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://raw.githubusercontent.com/httpie/httpie/master/docs/httpie-animation.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CeRZvje---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://raw.githubusercontent.com/httpie/httpie/master/docs/httpie-animation.gif" alt="httpie-demo" width="880" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's start with some basics and send http requests to endpoints.&lt;/p&gt;

&lt;p&gt;In order to get all &lt;em&gt;authors&lt;/em&gt;, run:&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="nv"&gt;$ &lt;/span&gt;http :8000/authors/

HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 165
Content-Type: application/json
Date: Fri, 17 Mar 2022 11:03:37 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.8.11
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"first_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name1"&lt;/span&gt;,
        &lt;span class="s2"&gt;"full_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name1 Surname1"&lt;/span&gt;,
        &lt;span class="s2"&gt;"id"&lt;/span&gt;: 1,
        &lt;span class="s2"&gt;"last_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Surname1"&lt;/span&gt;,
        &lt;span class="s2"&gt;"user"&lt;/span&gt;: null
    &lt;span class="o"&gt;}&lt;/span&gt;,
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"first_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"full_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name2 Surname2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"id"&lt;/span&gt;: 2,
        &lt;span class="s2"&gt;"last_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Surname2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"user"&lt;/span&gt;: null
    &lt;span class="o"&gt;}&lt;/span&gt;,
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"first_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"full_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name2 Surname2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"id"&lt;/span&gt;: 3,
        &lt;span class="s2"&gt;"last_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Surname2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"user"&lt;/span&gt;: 3
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mind the slash (&lt;code&gt;/&lt;/code&gt;) suffix after &lt;em&gt;authors&lt;/em&gt;; if you don't append it you will get:&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="nv"&gt;$ &lt;/span&gt;http :8000/authors

HTTP/1.1 301 Moved Permanently
Content-Length: 0
Content-Type: text/html&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;utf-8
Date: Fri, 17 Mar 2022 11:05:35 GMT
Location: /authors/
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.8.11
X-Content-Type-Options: nosniff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can change this behavior by adding &lt;code&gt;--follow&lt;/code&gt; argument as a flag or as a config in &lt;a href="https://httpie.io/"&gt;httpie&lt;/a&gt;'s config file which by default located in &lt;code&gt;~/.config/httpie/config.json&lt;/code&gt;.  As a command flag:&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="nv"&gt;$ &lt;/span&gt;http :8000/authors &lt;span class="nt"&gt;--follow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a config:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;~/.config/httpie/config.json&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;span class="nl"&gt;"__meta__"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"about"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HTTPie configuration file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://httpie.org/doc#config"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"httpie"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.3"&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;span class="nl"&gt;"default_options"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="s2"&gt;"--timeout=300"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"follow"&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;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;Django controls this behavior by &lt;strong&gt;&lt;a href="https://docs.djangoproject.com/en/4.0/ref/settings/#append-slash"&gt;APPEND_SLASH&lt;/a&gt;&lt;/strong&gt; setting:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;APPEND_SLASH&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Default: &lt;strong&gt;True&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When set to &lt;strong&gt;True&lt;/strong&gt;, if the request URL does not match any of the patterns in the URLconf and it doesn’t end in a slash, an HTTP redirect is issued to the same URL with a slash appended. Note that the redirect may cause any data submitted in a POST request to be lost.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;APPEND_SLASH&lt;/strong&gt; setting is only used if &lt;strong&gt;&lt;a href="https://docs.djangoproject.com/en/4.0/ref/middleware/#django.middleware.common.CommonMiddleware"&gt;CommonMiddleware&lt;/a&gt;&lt;/strong&gt; is installed (see &lt;a href="https://docs.djangoproject.com/en/4.0/topics/http/middleware/"&gt;Middleware&lt;/a&gt;). See also &lt;strong&gt;&lt;a href="https://docs.djangoproject.com/en/4.0/ref/settings/#std:setting-PREPEND_WWW"&gt;PREPEND_WWW&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also if you'd like to omit &lt;code&gt;header&lt;/code&gt; part of the response provide &lt;code&gt;--body&lt;/code&gt; flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  Default Filtering
&lt;/h2&gt;

&lt;p&gt;Default filter for &lt;a href="https://www.django-rest-framework.org/"&gt;Django REST&lt;/a&gt; is &lt;strong&gt;no filter&lt;/strong&gt;, meaning that it returns all &lt;em&gt;objects&lt;/em&gt; from the database.&lt;/p&gt;

&lt;p&gt;In other words if you try to filter the endpoint with some parameters it will return all objects together just like it did above:&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="nv"&gt;$ &lt;/span&gt;http &lt;span class="s2"&gt;":8000/authors/?id=1"&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"first_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name1"&lt;/span&gt;,
        &lt;span class="s2"&gt;"full_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name1 Surname1"&lt;/span&gt;,
        &lt;span class="s2"&gt;"id"&lt;/span&gt;: 1,
        &lt;span class="s2"&gt;"last_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Surname1"&lt;/span&gt;,
        &lt;span class="s2"&gt;"user"&lt;/span&gt;: null
    &lt;span class="o"&gt;}&lt;/span&gt;,
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"first_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"full_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name2 Surname2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"id"&lt;/span&gt;: 2,
        &lt;span class="s2"&gt;"last_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Surname2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"user"&lt;/span&gt;: null
    &lt;span class="o"&gt;}&lt;/span&gt;,
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"first_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"full_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Name2 Surname2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"id"&lt;/span&gt;: 3,
        &lt;span class="s2"&gt;"last_name"&lt;/span&gt;: &lt;span class="s2"&gt;"Surname2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"user"&lt;/span&gt;: 3
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For better understanding let's look at the responsible &lt;a href="https://github.com/encode/django-rest-framework/blob/0323d6f8955f987771269506ca5da461e2e7a248/rest_framework/generics.py#L48-L73"&gt;get_queryset&lt;/a&gt; method from the source code:&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;# rest_framework/generics.py
&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="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;"""
    Get the list of items for this view.
    This must be an iterable, and may be a queryset.
    Defaults to using `self.queryset`.

    This method should always be used rather than accessing `self.queryset`
    directly, as `self.queryset` gets evaluated only once, and those results
    are cached for all subsequent requests.

    You may want to override this if you need to provide different
    querysets depending on the incoming request.

    (Eg. return a list of items that is specific to the user)
    """&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"'%s' should either include a `queryset` attribute, "&lt;/span&gt;
        &lt;span class="s"&gt;"or override the `get_queryset()` method."&lt;/span&gt;
        &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__class__&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="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queryset&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queryset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QuerySet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Ensure queryset is re-evaluated on each request.
&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;queryset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;all&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;queryset&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, it just returns &lt;code&gt;queryset&lt;/code&gt; attribute from the related view which in our case is &lt;code&gt;Article.objects.all()&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;# src/articles/view.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;viewsets&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;src.articles.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;src.articles.serializers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ArticleSerializer&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticleViewSet&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;ArticleSerializer&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;Article&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="nb"&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;So as an example if you change &lt;code&gt;queryset&lt;/code&gt; attribute to &lt;code&gt;Article.objects.filter(content__icontains="3")&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;# src/articles/view.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rest_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;viewsets&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;src.articles.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;src.articles.serializers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ArticleSerializer&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticleViewSet&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;ArticleSerializer&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;Article&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="nb"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content__icontains&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it only will return &lt;strong&gt;Fake Article3&lt;/strong&gt; article:&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="nv"&gt;$ &lt;/span&gt;http &lt;span class="s2"&gt;":8000/authors/"&lt;/span&gt;
&lt;span class="c"&gt;# or&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;http &lt;span class="s2"&gt;":8000/authors/?id=1"&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"author"&lt;/span&gt;: 3,
        &lt;span class="s2"&gt;"content"&lt;/span&gt;: &lt;span class="s2"&gt;"Fake Content3"&lt;/span&gt;,
        &lt;span class="s2"&gt;"id"&lt;/span&gt;: 3,
        &lt;span class="s2"&gt;"regions"&lt;/span&gt;: &lt;span class="o"&gt;[]&lt;/span&gt;,
        &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"Fake Article3"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the same time you may realize you can directly change the &lt;code&gt;get_queryset&lt;/code&gt; method and throw the &lt;code&gt;queryset&lt;/code&gt; attribute:&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;# src/articles/views.py
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticleViewSet&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;ArticleSerializer&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="bp"&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;Article&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="nb"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content__icontains&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That's all for this part of the series. In the next parts you will explore more in depth example and cases.&lt;/p&gt;

&lt;p&gt;All done!&lt;/p&gt;

</description>
      <category>django</category>
      <category>djangorestframework</category>
      <category>filter</category>
      <category>search</category>
    </item>
    <item>
      <title>How to Install Deb Packages</title>
      <dc:creator>Serhat Teker</dc:creator>
      <pubDate>Thu, 10 Mar 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/serhatteker/how-to-install-deb-packages-1h4k</link>
      <guid>https://dev.to/serhatteker/how-to-install-deb-packages-1h4k</guid>
      <description>&lt;p&gt;&lt;code&gt;.deb&lt;/code&gt; is the installation package format used by all &lt;strong&gt;Debian&lt;/strong&gt; based distributions like &lt;strong&gt;Ubuntu&lt;/strong&gt;, &lt;strong&gt;Kali&lt;/strong&gt; , &lt;strong&gt;Linux Mint&lt;/strong&gt; , &lt;strong&gt;Pop!_OS&lt;/strong&gt; etc. and of course &lt;strong&gt;Debian&lt;/strong&gt; itself.&lt;/p&gt;

&lt;p&gt;In this post, I will explain how to install &lt;code&gt;.deb&lt;/code&gt; files on &lt;strong&gt;Ubuntu&lt;/strong&gt;. The same instructions apply for any other &lt;strong&gt;Debian&lt;/strong&gt; based distribution as mentioned above.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Ubuntu&lt;/strong&gt; repositories contain thousands of &lt;strong&gt;deb&lt;/strong&gt; packages that can be installed either from the &lt;strong&gt;Ubuntu&lt;/strong&gt; &lt;em&gt;Software Center&lt;/em&gt; or from the command line using the &lt;code&gt;apt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However many applications are not included in the &lt;strong&gt;Ubuntu&lt;/strong&gt; or any 3rd party repositories.  Another reason that you'd like to install a local &lt;strong&gt;deb&lt;/strong&gt; package would be their version on default package manager could be old and you'd like to get new version of them.&lt;/p&gt;

&lt;p&gt;Those &lt;em&gt;unofficial&lt;/em&gt; applications can be downloaded from the developer’s websites or git repositories and installed manually. But be careful when installing &lt;code&gt;.deb&lt;/code&gt; packages from unofficial sources especially if it's not open source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Downloading Deb Package
&lt;/h2&gt;

&lt;p&gt;For demonstration let's download &lt;a href="https://code.visualstudio.com/"&gt;Vscode&lt;/a&gt; &lt;em&gt;IDE&lt;/em&gt; via &lt;a href="https://www.gnu.org/software/wget/"&gt;wget&lt;/a&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="nv"&gt;$ &lt;/span&gt;wget &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="s1"&gt;'vscode-stable.deb'&lt;/span&gt; &lt;span class="s1"&gt;'https://code.visualstudio.com/sha/download?build=stable&amp;amp;os=linux-deb-x64'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you may guess from &lt;code&gt;query paramaters&lt;/code&gt; this command will download &lt;em&gt;64 bit&lt;/em&gt; architecture of &lt;a href="https://code.visualstudio.com/"&gt;Vscode&lt;/a&gt; &lt;strong&gt;deb&lt;/strong&gt; package from official &lt;a href="https://code.visualstudio.com/"&gt;Vscode&lt;/a&gt; repository as named &lt;strong&gt;vscode-stable.deb&lt;/strong&gt; in your current working directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Deb Package
&lt;/h2&gt;

&lt;p&gt;When it comes to installing &lt;strong&gt;deb&lt;/strong&gt; packages there are command-line or graphical user interface options.&lt;/p&gt;

&lt;p&gt;From the command line you have several tools at your disposal as well. In the following sections, I will show you how to use &lt;code&gt;apt&lt;/code&gt;, and &lt;code&gt;dpkg&lt;/code&gt; utilities to install deb packages.&lt;/p&gt;

&lt;h3&gt;
  
  
  dpkg
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;dpkg&lt;/code&gt; is a low-level package manager for Debian based systems. Use the &lt;code&gt;-i&lt;/code&gt; or &lt;code&gt;--install&lt;/code&gt; flag to install deb packages with &lt;code&gt;dpkg&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;&lt;span class="c"&gt;# First update package indices&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="c"&gt;# Install via dpkg&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;dpkg &lt;span class="nt"&gt;-i&lt;/span&gt; ./vscode-stable.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike &lt;code&gt;apt&lt;/code&gt;, &lt;code&gt;dpkg&lt;/code&gt; doesn’t resolve dependencies. If you get any dependency errors when installing &lt;strong&gt;deb&lt;/strong&gt; packages, you can use the following &lt;code&gt;apt&lt;/code&gt; command to resolve and install all package dependencies:&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="nv"&gt;$ &lt;/span&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;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  apt
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;apt&lt;/code&gt; is a command-line utility for installing, updating, removing, in short managing &lt;strong&gt;deb&lt;/strong&gt; packages on &lt;strong&gt;Ubuntu&lt;/strong&gt;, &lt;strong&gt;Debian&lt;/strong&gt;, and related Linux distributions. It was introduced in &lt;em&gt;Ubuntu 14.04&lt;/em&gt; and combines the most commonly used commands from &lt;code&gt;apt-get&lt;/code&gt; and &lt;code&gt;apt-cache&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;apt&lt;/code&gt; package manager will resolve and install all the package dependencies by itself, so it's better to use &lt;code&gt;apt&lt;/code&gt; instead of &lt;code&gt;dpkg&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To install local &lt;strong&gt;deb&lt;/strong&gt; packages with &lt;code&gt;apt&lt;/code&gt; you need to provide the full path to the &lt;strong&gt;deb&lt;/strong&gt; file. If the file is located in your current working directory instead of typing the absolute path, you should prepend &lt;code&gt;./&lt;/code&gt; before the package&lt;br&gt;
name.  Otherwise, &lt;code&gt;apt&lt;/code&gt; will try to retrieve and install the package from &lt;strong&gt;Ubuntu&lt;/strong&gt;’s repositories.&lt;/p&gt;

&lt;p&gt;Let's assume you are in the same directory after &lt;code&gt;wget&lt;/code&gt;ting &lt;a href="https://code.visualstudio.com/"&gt;Vscode&lt;/a&gt; &lt;strong&gt;deb&lt;/strong&gt; package, then just simply run:&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="c"&gt;# First update package indices&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="c"&gt;# Install via apt&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; ./vscode-stable.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We saw how to install local &lt;strong&gt;deb&lt;/strong&gt; packages on a &lt;strong&gt;Debian&lt;/strong&gt; based distribution —as an example Ubuntu. When installing &lt;strong&gt;deb&lt;/strong&gt; packages prefer using &lt;code&gt;apt&lt;/code&gt; since it resolves and install all the package dependencies.&lt;/p&gt;

&lt;p&gt;All done!&lt;/p&gt;

</description>
      <category>debian</category>
      <category>ubuntu</category>
      <category>linux</category>
      <category>os</category>
    </item>
    <item>
      <title>Python Interactive Shell Interfaces</title>
      <dc:creator>Serhat Teker</dc:creator>
      <pubDate>Thu, 03 Mar 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/serhatteker/python-interactive-shell-interfaces-45jd</link>
      <guid>https://dev.to/serhatteker/python-interactive-shell-interfaces-45jd</guid>
      <description>&lt;p&gt;The &lt;strong&gt;Python Interactive Shell&lt;/strong&gt; is an interactive interpreter that can execute &lt;strong&gt;Python&lt;/strong&gt; commands.&lt;/p&gt;

&lt;p&gt;You can invoke it from your default shell — &lt;code&gt;zsh&lt;/code&gt;, &lt;code&gt;bash&lt;/code&gt;, &lt;code&gt;fish&lt;/code&gt; etc.:&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="nv"&gt;$ &lt;/span&gt;python
&lt;span class="c"&gt;# or for a specific python version&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;python3.9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also you can run interactive shell with a module/file like below:&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="nv"&gt;$ &lt;/span&gt;python &lt;span class="nt"&gt;-i&lt;/span&gt; somefile.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Use Case
&lt;/h2&gt;

&lt;p&gt;Thanks python, however I can't say I enjoy your default shell. I need more &lt;em&gt;capable&lt;/em&gt;, &lt;em&gt;colorful&lt;/em&gt; interactive shell like &lt;strong&gt;&lt;a href="https://ipython.org"&gt;IPython&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://bpython-interpreter.org"&gt;bpython&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It's easy to achieve this in &lt;strong&gt;Django&lt;/strong&gt;. It's well documented in &lt;a href="https://docs.djangoproject.com/en/4.0/ref/django-admin/#shell"&gt;django-shell&lt;/a&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="c"&gt;# IPython&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;django-admin &lt;span class="nt"&gt;-i&lt;/span&gt; ipython
&lt;span class="c"&gt;# bpython&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;django-admin &lt;span class="nt"&gt;-i&lt;/span&gt; bpython
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, how can we achieve it in &lt;code&gt;Python&lt;/code&gt;?&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Python&lt;/strong&gt;'s way is kind of similar; you invoke it with some &lt;code&gt;module&lt;/code&gt; using &lt;code&gt;-m&lt;/code&gt; flag:&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;IPython&lt;/code&gt; run:&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="nv"&gt;$ &lt;/span&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; IPython &lt;span class="nt"&gt;-i&lt;/span&gt;
&lt;span class="c"&gt;# with module/file&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; IPython &lt;span class="nt"&gt;-i&lt;/span&gt; somefile.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For &lt;code&gt;bpython&lt;/code&gt; run:&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="nv"&gt;$ &lt;/span&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; bpython &lt;span class="nt"&gt;-i&lt;/span&gt;
&lt;span class="c"&gt;# with module/file&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; bpython &lt;span class="nt"&gt;-i&lt;/span&gt; somefile.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;br&gt;
In order to be able to use &lt;strong&gt;IPython&lt;/strong&gt; and/or &lt;strong&gt;bpython&lt;/strong&gt; first you have to install them:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install &lt;/span&gt;ipython
&lt;span class="nv"&gt;$ &lt;/span&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install &lt;/span&gt;bpython
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;Yes, it's that easy and now we can take advantage of amazing features like below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In-line syntax highlighting&lt;/li&gt;
&lt;li&gt;Readline-like auto-complete with suggestions displayed as you type&lt;/li&gt;
&lt;li&gt;Expected parameter list for any Python function, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_Dfp1ORd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://bpython-interpreter.org/images/full-demo.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_Dfp1ORd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://bpython-interpreter.org/images/full-demo.gif" alt="bpython-demo-gif" title="bpython demo" width="615" height="670"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Probably it would be better to have them as aliases:&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="c"&gt;# .aliases&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;pi&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'python -m IPython -i'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;pib&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'python -m bpython -i'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All done!&lt;/p&gt;

</description>
      <category>python</category>
      <category>shell</category>
      <category>bash</category>
    </item>
    <item>
      <title>Unknown Vim Trick</title>
      <dc:creator>Serhat Teker</dc:creator>
      <pubDate>Thu, 24 Feb 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/serhatteker/unknown-vim-trick-56ih</link>
      <guid>https://dev.to/serhatteker/unknown-vim-trick-56ih</guid>
      <description>&lt;p&gt;One of beautiful thing about &lt;code&gt;vim&lt;/code&gt; is that you can learn something even after using 5+ years. Even though usual vim learning curve characterized like below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XCOTC19b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://tech.serhatteker.com/img/content/2022/vim-learning-curve.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XCOTC19b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://tech.serhatteker.com/img/content/2022/vim-learning-curve.jpeg" alt="Vim Learning Curve" width="880" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the command I've been looking for a long time. I accidentally saw it on one of the &lt;a href="https://www.youtube.com/watch?v=E7NBhSsZouc"&gt;ThePrimeagen&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entrée
&lt;/h2&gt;

&lt;p&gt;Let's assume that I'm on the &lt;em&gt;line 5&lt;/em&gt; and want to update &lt;code&gt;"_cache_update_cache"&lt;/code&gt; on the &lt;em&gt;line 30&lt;/em&gt;, to &lt;code&gt;"_cache_update_current"&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="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;UpdateCacheMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MiddlewareMixin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;"""
    Response-phase cache middleware that updates the cache if the response is
    cacheable.
    Must be used as part of the two-part update/fetch cache middleware.
    UpdateCacheMiddleware must be the first piece of middleware in MIDDLEWARE
    so that it'll get called last during the response phase.
    """&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_timeout&lt;/span&gt; &lt;span class="o"&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;CACHE_MIDDLEWARE_SECONDS&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key_prefix&lt;/span&gt; &lt;span class="o"&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;CACHE_MIDDLEWARE_KEY_PREFIX&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_alias&lt;/span&gt; &lt;span class="o"&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;CACHE_MIDDLEWARE_ALIAS&lt;/span&gt;

    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&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;caches&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_alias&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;_should_update_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&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;response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;hasattr&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="s"&gt;"_cache_update_cache"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&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;_cache_update_cache&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What I was doing: press &lt;code&gt;25jf"ci"&lt;/code&gt; on &lt;code&gt;Normal&lt;/code&gt; &lt;em&gt;mode&lt;/em&gt;, which means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;25j&lt;/code&gt; : down 25 line&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;f"&lt;/code&gt;  : find the first occurrence of &lt;code&gt;"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ci"&lt;/code&gt; : change inside of &lt;code&gt;"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and then write &lt;code&gt;_cache_update_current&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The annoying part is you have to press additional &lt;code&gt;f"&lt;/code&gt; every time. For a normal user it probably means nothing, but for a &lt;code&gt;vim&lt;/code&gt; user it means a lot, since &lt;em&gt;"Real Vim ninjas count every keystroke"&lt;/em&gt;&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Therefore I was using a &lt;code&gt;macro&lt;/code&gt; and &lt;code&gt;key binding&lt;/code&gt; for this. Until now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trick
&lt;/h2&gt;

&lt;p&gt;The trick is just press &lt;code&gt;ci"&lt;/code&gt;; you don't have to press additional &lt;code&gt;f"&lt;/code&gt; (for an unknown reason it works which shouldn't). So our above command is just &lt;code&gt;25jci"&lt;/code&gt; now.&lt;/p&gt;

&lt;p&gt;And it works with usual text objects like &lt;code&gt;{, [, *, '&lt;/code&gt; etc.&lt;/p&gt;

&lt;p&gt;All done!&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://www.vimgolf.com"&gt;https://www.vimgolf.com&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>vim</category>
      <category>nvim</category>
    </item>
    <item>
      <title>Change Default Git Init Branch</title>
      <dc:creator>Serhat Teker</dc:creator>
      <pubDate>Thu, 17 Feb 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/serhatteker/change-default-git-init-branch-20c4</link>
      <guid>https://dev.to/serhatteker/change-default-git-init-branch-20c4</guid>
      <description>&lt;p&gt;As a developer my default branch is usually &lt;strong&gt;develop&lt;/strong&gt; for my personal projects. (I don't want to deep dive into details of &lt;strong&gt;Git Branching strategies&lt;/strong&gt; like &lt;em&gt;Trunk-Based Development&lt;/em&gt; &lt;em&gt;Git Flow (Feature Based Development)&lt;/em&gt; etc. maybe later in another post.)&lt;/p&gt;

&lt;p&gt;So I want to make my default branch name other than &lt;code&gt;master&lt;/code&gt; for the first commit.&lt;/p&gt;

&lt;p&gt;And my common workflow looks like this:&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="nv"&gt;$ &lt;/span&gt;git init &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git commit &lt;span class="nt"&gt;--allow-empty&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial commit"&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; develop
&lt;span class="nv"&gt;$ &lt;/span&gt;git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the question is: Is there any another way to change the default first branch name that git init sets?&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;Yes, there is, but you need minimum Git &lt;a href="https://dev.toreleased%202020-07-27"&gt;version 2.28&lt;/a&gt;.&lt;br&gt;
Just run:&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="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; init.defaultBranch develop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or as usual you can add this directly into your &lt;strong&gt;global config file&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# ~/.gitconfig
# ~/.config/git/config
# or
# ${XDG_CONFIG_HOME}/git/config
&lt;/span&gt;
&lt;span class="err"&gt;...&lt;/span&gt;

&lt;span class="nn"&gt;[init]&lt;/span&gt;
    &lt;span class="c"&gt;# &amp;gt;=2.28.0
&lt;/span&gt;    &lt;span class="py"&gt;defaultBranch&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;develop&lt;/span&gt;

&lt;span class="err"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now whenever I initiate a &lt;em&gt;git repo&lt;/em&gt; my default branch will be &lt;em&gt;develop&lt;/em&gt; and this will save a lot of keystroke.&lt;/p&gt;

&lt;p&gt;All done!&lt;/p&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>Tmux New Session</title>
      <dc:creator>Serhat Teker</dc:creator>
      <pubDate>Thu, 10 Feb 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/serhatteker/tmux-new-session-iec</link>
      <guid>https://dev.to/serhatteker/tmux-new-session-iec</guid>
      <description>&lt;h2&gt;
  
  
  Entrée
&lt;/h2&gt;

&lt;p&gt;I keep forgetting how to create a new tmux session.&lt;/p&gt;

&lt;p&gt;Is it this one?&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="nv"&gt;$ &lt;/span&gt;tmux new
sessions should be nested with care, &lt;span class="nb"&gt;unset&lt;/span&gt; &lt;span class="nv"&gt;$TMUX&lt;/span&gt; to force
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;Is it this one?&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="nv"&gt;$ &lt;/span&gt;tmux new-session
sessions should be nested with care, &lt;span class="nb"&gt;unset&lt;/span&gt; &lt;span class="nv"&gt;$TMUX&lt;/span&gt; to force
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No.&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="nv"&gt;$ &lt;/span&gt;tmux new-session &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;span class="c"&gt;# from tmux cli, prefix/ctrl+b&lt;/span&gt;
&lt;span class="c"&gt;# :new -d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No error? Good. Check session with prefix + s (&lt;code&gt;ctrl + b + s&lt;/code&gt;). Ok it seems this works.&lt;/p&gt;

&lt;p&gt;However this gives a strange session name like &lt;strong&gt;29&lt;/strong&gt;. What is it? I though &lt;strong&gt;the ultimate answer to the universe&lt;/strong&gt; was &lt;strong&gt;42&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;Here is the complete command to create a new tmux session:&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="nv"&gt;$ &lt;/span&gt;tmux new-session &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"new"&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; ~/path/to/some/dir &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"main"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will create a session named &lt;em&gt;new&lt;/em&gt;, with a window named &lt;em&gt;main&lt;/em&gt; in &lt;code&gt;~/path/to/some/dir&lt;/code&gt; as working directory.&lt;/p&gt;

&lt;p&gt;It would probably better to run it from &lt;em&gt;function&lt;/em&gt; with some &lt;em&gt;args&lt;/em&gt; for more customization;&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="c"&gt;# .zshrc/.bashrc&lt;/span&gt;


&lt;span class="c"&gt;# Crate and attach a new session with args&lt;/span&gt;
&lt;span class="c"&gt;# defaults: session named "new" in ${HOME} as working dir with window named "main"&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Usage:&lt;/span&gt;
&lt;span class="c"&gt;# $ tnew&lt;/span&gt;
&lt;span class="c"&gt;# $ tnew remote ~/path/to/dir&lt;/span&gt;
&lt;span class="c"&gt;# $ tnew remote ~/path/to/dir scripts&lt;/span&gt;
tnew&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;session_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;new&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;session_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;~/&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;session_window_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;3&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    tmux new-session &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;session_name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;session_dir&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;session_window_name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As described in function's doc you can use this function as below:&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="nv"&gt;$ &lt;/span&gt;tnew
&lt;span class="nv"&gt;$ &lt;/span&gt;tnew remote ~/path/to/dir
&lt;span class="nv"&gt;$ &lt;/span&gt;tnew remote ~/path/to/dir scripts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I can peacefully forget (again) &lt;em&gt;creating new tmux session&lt;/em&gt;, all I need to&lt;br&gt;
remember: &lt;strong&gt;tnew&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;All done!&lt;/p&gt;

</description>
      <category>tmux</category>
      <category>zsh</category>
      <category>bash</category>
    </item>
    <item>
      <title>How to Run Multiple Long Commands in Docker Compose</title>
      <dc:creator>Serhat Teker</dc:creator>
      <pubDate>Thu, 03 Feb 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/serhatteker/how-to-run-multiple-long-commands-in-docker-compose-1f13</link>
      <guid>https://dev.to/serhatteker/how-to-run-multiple-long-commands-in-docker-compose-1f13</guid>
      <description>&lt;h2&gt;
  
  
  Use Case
&lt;/h2&gt;

&lt;p&gt;I want to run multiple/long commands for my service(s) in my &lt;code&gt;docker-compose&lt;/code&gt; file, like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;# docker-compose.yaml&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;server&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./compose/staging/server/Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;someproject_slug_staging_server:staging_shortsha_unixtime&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./.envs/.staging/.server&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./.envs/.staging/.postgres&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python /app/manage.py collectstatic --no-input&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python /app/manage.py migrate&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gunicorn config.wsgi --bind 0.0.0.0:5000 --chdir=/app&lt;/span&gt;

  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./compose/staging/postgres/Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;someproject_slug_staging_postgres:staging_shortsha_unixtime&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;staging_postgres_data:/var/lib/postgresql/data:Z&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;staging_postgres_data_backups:/backups:z&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./.envs/.staging/.postgres&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However it won't work since it's not possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Script File
&lt;/h3&gt;

&lt;p&gt;One solution is that putting all your commands in a script file -let's say &lt;code&gt;start.sh&lt;/code&gt;, put it into your image, build with it and call it directly.&lt;/p&gt;

&lt;p&gt;As an example here is a &lt;code&gt;docker compose&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;# staging.yaml&lt;/span&gt;

&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.7'&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;staging_postgres_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
  &lt;span class="na"&gt;staging_postgres_data_backups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
  &lt;span class="na"&gt;staging_traefik&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
  &lt;span class="na"&gt;staging_redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;server&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./compose/staging/server/Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;someproject_slug_server:staging_shortsha_unixtime&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./.envs/.staging/.server&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./.envs/.staging/.postgres&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./.envs/.staging/.redis&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/start&lt;/span&gt;

  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./compose/staging/postgres/Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;someproject_slug_postgres:staging_shortsha_unixtime&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;staging_postgres_data:/var/lib/postgresql/data:Z&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;staging_postgres_data_backups:/backups:z&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./.envs/.staging/.postgres&lt;/span&gt;

  &lt;span class="na"&gt;traefik&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./compose/staging/traefik/Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;someproject_slug_traefik:staging_shortsha_unixtime&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;server&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;staging_traefik:/etc/traefik/acme:z&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0:80:80"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0:443:443"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0:5555:5555"&lt;/span&gt;

  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker.io/bitnami/redis:6.2&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./.envs/.staging/.redis&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;6379:6379"&lt;/span&gt; &lt;span class="c1"&gt;# WARNING: In production never bind 0.0.0.0 wildcard adress of the host&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;staging_redis:/bitnami/redis/data:z&lt;/span&gt;

  &lt;span class="na"&gt;celeryworker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*server&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/start-celeryworker&lt;/span&gt;

  &lt;span class="na"&gt;celerybeat&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*server&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/start-celerybeat&lt;/span&gt;

  &lt;span class="na"&gt;celeryflower&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*server&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/start-celeryflower&lt;/span&gt;

  &lt;span class="na"&gt;aws-backup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./compose/staging/aws/Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./.envs/.staging/.server&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;staging_postgres_data_backups:/backups:z&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;WARNING&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Don't bind your host's &lt;code&gt;0.0.0.0&lt;/code&gt; wildcard adress in production environment. (Actually instead of deploying via &lt;code&gt;docker-compose&lt;/code&gt;in production  you should consider to use more reliable, and robust distributed systems like &lt;code&gt;Kubernetes&lt;/code&gt; but this is a topic for another post.)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;6379:6379&lt;/code&gt; means &lt;code&gt;0.0.0.0:6379:6379&lt;/code&gt;, so you open your redis instance to whole open world. And if you don't use &lt;code&gt;AUTH&lt;/code&gt; or don't take required security precaution -like &lt;strong&gt;TLS&lt;/strong&gt; etc. you may get some headache. So use it only if you&lt;br&gt;
know the related consequences.&lt;/p&gt;

&lt;p&gt;For more redis security topic look at this: &lt;a href="https://redis.io/topics/security"&gt;Redis Security&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And as an example here is content of &lt;code&gt;start&lt;/code&gt; from &lt;code&gt;server&lt;/code&gt; service:&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="c"&gt;#!/usr/env/bin bash&lt;/span&gt;
&lt;span class="c"&gt;# start&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; errexit
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; pipefail
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; nounset


python /app/manage.py collectstatic &lt;span class="nt"&gt;--noinput&lt;/span&gt;
python /app/manage.py migrate   &lt;span class="c"&gt;# WARNING: Not a good idea for prod&lt;/span&gt;
gunicorn config.wsgi &lt;span class="nt"&gt;--bind&lt;/span&gt; 0.0.0.0:5000 &lt;span class="nt"&gt;--chdir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;WARNING&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Migration is not a command you want to run every container start but since it's staging environment let's assume it's OK.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Multiline Scalar
&lt;/h3&gt;

&lt;p&gt;Running in a script file is OK however maybe it's &lt;em&gt;local&lt;/em&gt; or &lt;em&gt;staging&lt;/em&gt; environment which means you need to debug and tweak these commands one by one; maybe some flags are not working etc. and you don't want to &lt;em&gt;re-build&lt;/em&gt; the image every time.&lt;/p&gt;

&lt;p&gt;How are we gonna do this?&lt;/p&gt;

&lt;p&gt;The answer lines in the multiline capability of &lt;code&gt;yaml&lt;/code&gt; syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="s"&gt;bash -c "python /app/manage.py collectstatic --noinput&lt;/span&gt;
  &lt;span class="s"&gt;&amp;amp;&amp;amp; python /app/manage.py migrate&lt;/span&gt;
  &lt;span class="s"&gt;&amp;amp;&amp;amp; gunicorn config.wsgi --bind 0.0.0.0:5000 --chdir=/app"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is called &lt;strong&gt;Folded Style&lt;/strong&gt;. The indention in each line will be ignored. A line break (&lt;code&gt;\n&lt;/code&gt;) will be inserted at the end.&lt;/p&gt;

&lt;p&gt;Or you can use &lt;strong&gt;Literal Style&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/bin/bash&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;-c&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;python /app/manage.py collectstatic --noinput&lt;/span&gt;
  &lt;span class="s"&gt;python /app/manage.py migrate&lt;/span&gt;
  &lt;span class="s"&gt;gunicorn config.wsgi --bind 0.0.0.0:5000 --chdir=/app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This turns every newline within the string into a literal newline, and adds one at the end.&lt;/p&gt;

&lt;p&gt;More on these styles:&lt;/p&gt;

&lt;h4&gt;
  
  
  Folded Style
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="s"&gt;this is my very very very&lt;/span&gt;
  &lt;span class="s"&gt;long command&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;this is my very very very long command\n&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Mind new line-&lt;code&gt;\n&lt;/code&gt; (end of line-&lt;code&gt;EOL&lt;/code&gt;)&lt;/p&gt;

&lt;h4&gt;
  
  
  Literal Style
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;this is my very very very&lt;/span&gt;
  &lt;span class="s"&gt;long command&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;this is my very very very\nlong command\n&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Mind new lines-&lt;code&gt;\n&lt;/code&gt;, and compare to it above output.&lt;/p&gt;

&lt;p&gt;Fore more detailed style and &lt;code&gt;yaml&lt;/code&gt; syntax you can look at this amazing explanation in this &lt;a href="https://stackoverflow.com/a/21699210"&gt;link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These were the solutions for running multiple or long commands in your docker-compose file.&lt;/p&gt;

&lt;p&gt;All done!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>dockercompose</category>
      <category>yaml</category>
    </item>
    <item>
      <title>Merge Upstream Pull Request into Your Fork</title>
      <dc:creator>Serhat Teker</dc:creator>
      <pubDate>Thu, 27 Jan 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/serhatteker/merge-upstream-pull-request-into-your-fork-2d39</link>
      <guid>https://dev.to/serhatteker/merge-upstream-pull-request-into-your-fork-2d39</guid>
      <description>&lt;h2&gt;
  
  
  Use Case
&lt;/h2&gt;

&lt;p&gt;I have forked a repo, I've made some changes and my fork and upstream diverged.&lt;/p&gt;

&lt;p&gt;In the meantime someone sent a &lt;em&gt;PR&lt;/em&gt; to &lt;code&gt;upstream&lt;/code&gt; and this &lt;em&gt;PR&lt;/em&gt; is still open or rejected/closed etc by maintainers. However I'd like to apply the changes that &lt;em&gt;PR&lt;/em&gt; proposes into my fork.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  One Time
&lt;/h3&gt;

&lt;p&gt;If this is a one time thing, then you can get with &lt;code&gt;fetch&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;&lt;span class="nv"&gt;$ &lt;/span&gt;git fetch upstream pull/42/head
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can &lt;code&gt;merge&lt;/code&gt;, &lt;code&gt;cherry-pick&lt;/code&gt; etc. these &lt;em&gt;PR&lt;/em&gt; changes.&lt;/p&gt;

&lt;p&gt;Or you can &lt;code&gt;pull&lt;/code&gt; directly:&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="nv"&gt;$ &lt;/span&gt;git pull upstream pull/42/head
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;INFO&lt;/p&gt;

&lt;p&gt;As you may see, above scripts assumes your remote upstream repo named &lt;strong&gt;upstream&lt;/strong&gt; and &lt;strong&gt;42&lt;/strong&gt; is the &lt;em&gt;PR&lt;/em&gt; number you'd like to apply, change them accordingly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Git Alias
&lt;/h3&gt;

&lt;p&gt;If you regularly will apply &lt;em&gt;PR*s then you can add related functions as *aliases&lt;/em&gt; in your &lt;em&gt;local&lt;/em&gt; or &lt;em&gt;global&lt;/em&gt; &lt;code&gt;config&lt;/code&gt;, a.k.a one of the below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;${YOUR_REPO}/.git/config&lt;/code&gt; (local)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.gitconfig&lt;/code&gt; (global)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;${XDG_CONFIG_HOME}/git/config&lt;/code&gt; (global)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# ${REPO}/.git/config
# ~/.gitconfig
# ${XDG_CONFIG_HOME}/git/config
&lt;/span&gt;&lt;span class="nn"&gt;[alias]&lt;/span&gt;
    &lt;span class="py"&gt;gfpr&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"!f() { git fetch upstream refs/pull/$1/head:pr/$1; } ; f"&lt;/span&gt;
    &lt;span class="py"&gt;gppr&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"!f() { git pull upstream pull/$1/head; } ; f"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then fetch all *PR*s.&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="nv"&gt;$ &lt;/span&gt;git fetch upstream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To check out a particular &lt;em&gt;PR&lt;/em&gt; &lt;em&gt;#42&lt;/em&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="nv"&gt;$ &lt;/span&gt;git checkout &lt;span class="nb"&gt;pr&lt;/span&gt;/42
Branch &lt;span class="nb"&gt;pr&lt;/span&gt;/42 &lt;span class="nb"&gt;set &lt;/span&gt;up to track remote branch &lt;span class="nb"&gt;pr&lt;/span&gt;/42 from upstream.
Switched to a new branch &lt;span class="s1"&gt;'pr/42'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Local gitconfig
&lt;/h3&gt;

&lt;p&gt;You can append &lt;em&gt;fetch config&lt;/em&gt; in your local &lt;code&gt;config&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# .git/config
&lt;/span&gt;&lt;span class="nn"&gt;[remote "upstream"]&lt;/span&gt;
    &lt;span class="py"&gt;fetch&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;+refs/heads/*:refs/remotes/origin/*&lt;/span&gt;
    &lt;span class="py"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;git@github.com:joyent/node.git&lt;/span&gt;
    &lt;span class="py"&gt;fetch&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;+refs/pull/*/head:refs/remotes/origin/pr/*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rest is the same as above.&lt;/p&gt;

&lt;h3&gt;
  
  
  With Script
&lt;/h3&gt;

&lt;p&gt;You can append above related &lt;em&gt;fetch config&lt;/em&gt; with below script:&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="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# git-fetch-pr.sh&lt;/span&gt;

git remote &lt;span class="nt"&gt;-v&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;fetch | &lt;span class="nb"&gt;grep &lt;/span&gt;github | &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;remote url _&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
        if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; git config &lt;span class="nt"&gt;--get-all&lt;/span&gt; &lt;span class="s2"&gt;"remote.&lt;/span&gt;&lt;span class="nv"&gt;$remote&lt;/span&gt;&lt;span class="s2"&gt;.fetch"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; refs/pull
        &lt;span class="k"&gt;then
            &lt;/span&gt;git config &lt;span class="nt"&gt;--add&lt;/span&gt; &lt;span class="s2"&gt;"remote.&lt;/span&gt;&lt;span class="nv"&gt;$remote&lt;/span&gt;&lt;span class="s2"&gt;.fetch"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                &lt;span class="s1"&gt;'+refs/pull/*/head:refs/remotes/'&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$remote&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s1"&gt;'/pull/*'&lt;/span&gt;
        &lt;span class="k"&gt;fi
    done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rest is the same.&lt;/p&gt;

&lt;p&gt;All done!&lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/piscisaureus/3342247"&gt;gist #1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/chernjie/b16fe4dccf3f386d52ff"&gt;gist #2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
      <category>vcs</category>
    </item>
    <item>
      <title>Convert Strings To Be URL Safe</title>
      <dc:creator>Serhat Teker</dc:creator>
      <pubDate>Thu, 20 Jan 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/serhatteker/convert-strings-to-be-url-safe-1b05</link>
      <guid>https://dev.to/serhatteker/convert-strings-to-be-url-safe-1b05</guid>
      <description>&lt;p&gt;In order to convert your strings to be URL safe you can use python's built-in &lt;code&gt;urllib&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="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;urllib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;string_raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Test: Hey! this is an example string"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s"&gt;'Test%3A%20Hey%21%20This%20is%20an%20example%20string'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;quote()&lt;/code&gt; replaces special characters in string using the &lt;code&gt;%xx&lt;/code&gt; escape. Letters, digits, and the characters &lt;code&gt;_.-~&lt;/code&gt; are never touched. By default, this function is intended for converting the path section of a URL.&lt;/p&gt;

&lt;p&gt;If you want to use your strings as query strings you can use &lt;code&gt;quote_plus&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="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;urllib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;string_raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Test: Hey! this is an example string"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s"&gt;'Test%3A+Hey%21+This+is+an+example+string'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;quote_plus()&lt;/code&gt; is like &lt;code&gt;quote()&lt;/code&gt; but also replace spaces with plus signs. It is required for building HTML form values when building up a query string to go into a URL.&lt;/p&gt;

&lt;p&gt;For more info you can look at official python doc: &lt;a href="https://docs.python.org/3/library/urllib.parse.html#urllib.parse.quote"&gt;quote&lt;/a&gt;, &lt;a href="https://docs.python.org/3/library/urllib.parse.html#urllib.parse.quote_plus"&gt;quote_plus&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All done!&lt;/p&gt;

</description>
      <category>python</category>
    </item>
    <item>
      <title>List Files Tracked by Git</title>
      <dc:creator>Serhat Teker</dc:creator>
      <pubDate>Thu, 13 Jan 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/serhatteker/list-files-tracked-by-git-5gcb</link>
      <guid>https://dev.to/serhatteker/list-files-tracked-by-git-5gcb</guid>
      <description>&lt;h2&gt;
  
  
  All current files
&lt;/h2&gt;

&lt;p&gt;In order to show all of the tracked files that have been committed on the current branch, run:&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="nv"&gt;$ &lt;/span&gt;git ls-tree &lt;span class="nt"&gt;--full-tree&lt;/span&gt; &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--full-tree&lt;/code&gt; makes the command run as if you were in the repo's root directory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-r&lt;/code&gt; recurses into subdirectories. Combined with &lt;code&gt;--full-tree&lt;/code&gt; this gives you all committed, tracked files.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--name-only&lt;/code&gt; removes SHA / permission info for when you just want the file paths.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HEAD&lt;/code&gt; specifies which branch you want the list of tracked, committed files
for. &lt;code&gt;HEAD&lt;/code&gt; is the pointer for the commit you have checked out currently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the output will be like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;...
static/img/logopal.png
static/img/logos/bitcoin.png
static/img/logos/bmc-button.svg
static/img/logos/django-logo.png
static/img/logos/git-logo-full.png
static/img/logos/git-logo-red.png
static/img/logos/git-logo-white.png
static/img/logos/neovim-logo.png
static/img/logos/python-logo.png
static/img/logos/python-logo2.png
static/img/logos/python-logo3.png
static/img/logos/python-logo4.png
static/img/logos/python-logo5.png
static/img/logos/python-logo6.png
static/img/logos/python-logo8.svg
static/img/logos/vim-logo.png
static/img/python3.7-default.jpg
static/img/safari-pinned-tab.svg
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to show the files on the &lt;code&gt;master&lt;/code&gt; branch, replace &lt;code&gt;HEAD&lt;/code&gt; with &lt;code&gt;master&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;&lt;span class="nv"&gt;$ &lt;/span&gt;git ls-tree &lt;span class="nt"&gt;--full-tree&lt;/span&gt; &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Probably you also want a alias for that:&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;alias &lt;/span&gt;&lt;span class="nv"&gt;gtf&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'git ls-tree --full-tree --name-only -r HEAD'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  All files including deleted
&lt;/h2&gt;

&lt;p&gt;If you want to list all of files that ever existed including deleted files, run below:&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="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format: &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="nt"&gt;--diff-filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;A | &lt;span class="nb"&gt;sort&lt;/span&gt; - | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'/^$/d'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All done!&lt;/p&gt;

&lt;p&gt;References:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/a/55081559/10802538"&gt;stackoverflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
    </item>
  </channel>
</rss>
