<?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: Peiwen Li</title>
    <description>The latest articles on DEV Community by Peiwen Li (@ld8).</description>
    <link>https://dev.to/ld8</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%2F581482%2F7a16c106-e359-4493-a620-3d2891273245.JPG</url>
      <title>DEV Community: Peiwen Li</title>
      <link>https://dev.to/ld8</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ld8"/>
    <language>en</language>
    <item>
      <title>Configure A Fresh VPS To Host A Website</title>
      <dc:creator>Peiwen Li</dc:creator>
      <pubDate>Sun, 17 Jul 2022 03:25:24 +0000</pubDate>
      <link>https://dev.to/ld8/configure-a-fresh-vps-to-host-a-website-4lh0</link>
      <guid>https://dev.to/ld8/configure-a-fresh-vps-to-host-a-website-4lh0</guid>
      <description>&lt;p&gt;Got a new VPS (Ubuntu 20.04) on Namecheap. It seems that the basic VPS tier on Namecheap offers double CPU, RAM and storage than that of my old basic tier on AWS lightsail.&lt;/p&gt;

&lt;p&gt;This journal concisely notes: How to configurate a fresh VPS to host my new website &lt;a href="https://peiwen.me"&gt;peiwen.me&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Just run these commands once ssh into remote server&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;apt&lt;/code&gt; is a Linux package management system&lt;/li&gt;
&lt;li&gt;'fun' fact: &lt;code&gt;apt&lt;/code&gt; cmd was introduced in 2014, partly replaced &lt;code&gt;apt-get&lt;/code&gt; after the release of Ubuntu 16.04, for being faster, friendlier, easier to use&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Firstly! &lt;code&gt;SSH&lt;/code&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;mosh&lt;/code&gt; is a good mobile shell - highly responsive, gotta be installed both locally and remotely.&lt;/li&gt;
&lt;li&gt;local ssh config for convenience:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="c"&gt;# add info to local file: ~/.ssh/config&lt;/span&gt;
  Host &amp;lt;name_your_remote&amp;gt;
    HostName &amp;lt;static_IP&amp;gt;
    User &amp;lt;remote_username&amp;gt;
    IdentityFile &amp;lt;path_to_local_id_rsa&amp;gt;
    IdentitiesOnly &lt;span class="nb"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;remote ssh config:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="c"&gt;# local shell&lt;/span&gt;
  ssh &amp;lt;user&amp;gt;@&amp;lt;static_IP&amp;gt;

  &lt;span class="c"&gt;# remote shell&lt;/span&gt;
  &lt;span class="nb"&gt;mkdir&lt;/span&gt; .ssh
  &lt;span class="nb"&gt;touch &lt;/span&gt;authorized_keys
  apt-get &lt;span class="nb"&gt;install &lt;/span&gt;nano &lt;span class="c"&gt;# just in case&lt;/span&gt;
  apt-get &lt;span class="nb"&gt;install &lt;/span&gt;mosh &lt;span class="c"&gt;# just in case&lt;/span&gt;
  nano authorized_keys
  &lt;span class="c"&gt;# paste the content of the local file 'id_rsa.pub' to this file, save and exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;NOW! YOU CAN~
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="c"&gt;# local shell&lt;/span&gt;
  mosh &amp;lt;name_your_remote&amp;gt;
  ssh &amp;lt;name_your_remote&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  NodeJS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;nvm&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-o-&lt;/span&gt; https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
&lt;span class="c"&gt;# might need to reconnect remote for `nvm` command to work properly&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: check the latest &lt;code&gt;nvm&lt;/code&gt; installation script &lt;a href="https://github.com/nvm-sh/nvm"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;node&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm list-remote
nvm &lt;span class="nb"&gt;install &lt;/span&gt;stable &lt;span class="c"&gt;# or pick one from the list&lt;/span&gt;
nvm list
node &lt;span class="nt"&gt;-v&lt;/span&gt;
npm &lt;span class="nt"&gt;-v&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--global&lt;/span&gt; yarn &lt;span class="c"&gt;# recommended&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: if "nvm 'command' not found" - check &lt;a href="https://github.com/nvm-sh/nvm#troubleshooting-on-linux"&gt;'Troubleshooting on Linux Section'&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  MongoDB
&lt;/h2&gt;

&lt;p&gt;Problems with installing v5.0&lt;/p&gt;

&lt;p&gt;🔥 This exact &lt;a href="https://www.linuxfixes.com/2022/03/solved-mongod-does-not-start.html"&gt;problem&lt;/a&gt; encountered when I installed v5.0 - &lt;code&gt;mongod&lt;/code&gt; service won't start. The reason might be:&lt;/p&gt;

&lt;p&gt;&amp;gt; the VM’s CPU does not support instructions required by MongoDB 5.0 (such as AVX and SSE) which should be listed in the &lt;code&gt;CPU flags&lt;/code&gt;:&lt;br&gt;
&amp;gt; &lt;code&gt;flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Similar issues found:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.mongodb.com/community/forums/t/setting-up-mongodb-v5-0-on-ubuntu-20-core-dump-status-4-ill/120705/3"&gt;mongodb community forum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/68609678/mongodb-result-signal-code-killed-signal-ill"&gt;stack-overflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You might need to install &lt;code&gt;apt install procinfo&lt;/code&gt; to run &lt;code&gt;cat /proc/cpuinfo&lt;/code&gt; to checkout your CPU type.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.mongodb.com/docs/v4.4/tutorial/install-mongodb-on-ubuntu/#install-mongodb-community-edition"&gt;Install MongoDB v4.4 Community Edition&lt;/a&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget &lt;span class="nt"&gt;-qO&lt;/span&gt; - https://www.mongodb.org/static/pgp/server-4.4.asc | &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-key add -

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/mongodb-org-4.4.list

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; mongodb-org&lt;span class="o"&gt;=&lt;/span&gt;4.4.15 mongodb-org-server&lt;span class="o"&gt;=&lt;/span&gt;4.4.15 mongodb-org-shell&lt;span class="o"&gt;=&lt;/span&gt;4.4.15 mongodb-org-mongos&lt;span class="o"&gt;=&lt;/span&gt;4.4.15 mongodb-org-tools&lt;span class="o"&gt;=&lt;/span&gt;4.4.15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Start and config
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start mongod
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status mongod
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;mongod
mongo
mongosh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: &lt;code&gt;sudo&lt;/code&gt; can be omitted if you are the &lt;code&gt;root&lt;/code&gt; superuser&lt;/p&gt;

&lt;p&gt;Uninstall MongoDB&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;service mongod stop
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get purge mongodb-org&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-fr&lt;/span&gt; /var/log/mongodb
&lt;span class="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-fr&lt;/span&gt; /var/lib/mongodb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Security Checklist
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/manual/administration/security-checklist/"&gt;MongoDB Guide&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  IP Binding to create a replica backup
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/manual/core/security-mongodb-configuration/"&gt;Mongo&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Git
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt update
apt &lt;span class="nb"&gt;install &lt;/span&gt;git
git &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;To setup username if push to source is needed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name &amp;lt;username&amp;gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email &amp;lt;email&amp;gt;
git config &lt;span class="nt"&gt;--list&lt;/span&gt; &lt;span class="c"&gt;# or ↓ directly check gitconfig file&lt;/span&gt;
nano ~/.gitconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is NOT enough anyway if you were to edit code and push to source, for only SSH communication is allowed with github repos since 2021.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clone repo
&lt;/h3&gt;

&lt;p&gt;Clone web repo to &lt;code&gt;~/web/&lt;/code&gt;, install the deps&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;repo_address&amp;gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; &amp;lt;project&amp;gt;

yarn
&lt;span class="c"&gt;# OR&lt;/span&gt;
npm i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure &lt;code&gt;.env.local&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; .env.local
nano .env.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;.env.local&lt;/code&gt; content ↓&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MONGODB_URI=&amp;lt;get_this by typing mongosh&amp;gt;
MONGODB_DB=journal

PASS=&amp;lt;some_password&amp;gt;
NEXT_PUBLIC_PASS_TOKEN=&amp;lt;some_JWT_like_token&amp;gt;

NEXT_PUBLIC_REVAL_TOKEN=&amp;lt;some_token_for_revalidation_token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn build
yarn global add pm2
pm2 start yarn &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"peiwen.me"&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; start
pm2 &lt;span class="nb"&gt;ls&lt;/span&gt;

&lt;span class="c"&gt;# to start on startup&lt;/span&gt;
pm2 startup
&lt;span class="c"&gt;# to freeze/save the processes&lt;/span&gt;
pm2 save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Nginx
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Install, config firewall and enable nginx
&lt;/h3&gt;



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

&lt;span class="c"&gt;# firewall&lt;/span&gt;
ufw app list

&lt;span class="c"&gt;# returns&lt;/span&gt;
Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH
  mosh

&lt;span class="c"&gt;# enable firewall&lt;/span&gt;
ufw allow &lt;span class="s1"&gt;'Nginx Full'&lt;/span&gt;
ufw allow OpenSSH &lt;span class="c"&gt;# important&lt;/span&gt;
ufw allow mosh
ufw &lt;span class="nb"&gt;enable
&lt;/span&gt;ufw status

&lt;span class="c"&gt;# returns&lt;/span&gt;
Status: active
To                         Action      From
&lt;span class="nt"&gt;--&lt;/span&gt;                         &lt;span class="nt"&gt;------&lt;/span&gt;      &lt;span class="nt"&gt;----&lt;/span&gt;
Nginx Full                 ALLOW       Anywhere
OpenSSH                    ALLOW       Anywhere
mosh                       ALLOW       Anywhere
Nginx Full &lt;span class="o"&gt;(&lt;/span&gt;v6&lt;span class="o"&gt;)&lt;/span&gt;            ALLOW       Anywhere &lt;span class="o"&gt;(&lt;/span&gt;v6&lt;span class="o"&gt;)&lt;/span&gt;
OpenSSH &lt;span class="o"&gt;(&lt;/span&gt;v6&lt;span class="o"&gt;)&lt;/span&gt;               ALLOW       Anywhere &lt;span class="o"&gt;(&lt;/span&gt;v6&lt;span class="o"&gt;)&lt;/span&gt;
mosh &lt;span class="o"&gt;(&lt;/span&gt;v6&lt;span class="o"&gt;)&lt;/span&gt;                  ALLOW       Anywhere &lt;span class="o"&gt;(&lt;/span&gt;v6&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# check your nginx server&lt;/span&gt;
systemctl status nginx

&lt;span class="c"&gt;# get your IP if you don't already know for some reason&lt;/span&gt;
curl &lt;span class="nt"&gt;-4&lt;/span&gt; icanhazip.com
&amp;lt;IP_address&amp;gt;

&lt;span class="c"&gt;# enter this &amp;lt;IP_address&amp;gt; into the browser, you should be able to see the landing page of nginx&lt;/span&gt;

&lt;span class="c"&gt;# lastely, enable it on every boot&lt;/span&gt;
systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Setting Up Server Blocks
&lt;/h3&gt;

&lt;p&gt;An nginx &lt;code&gt;server block&lt;/code&gt; is a file inside folder &lt;code&gt;/etc/nginx/sites-available/&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="nb"&gt;cd&lt;/span&gt; /etc/nginx/sites-available
&lt;span class="nb"&gt;touch&lt;/span&gt; &amp;lt;new_domain&amp;gt; &lt;span class="c"&gt;# optional&lt;/span&gt;
nano &amp;lt;new_domain&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Insert content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;server &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;# the name of your domain&lt;/span&gt;
  server_name &amp;lt;new_domain&amp;gt; www.&amp;lt;new_domain&amp;gt;&lt;span class="p"&gt;;&lt;/span&gt;

  location / &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;# this must stay localhost. The port must be the same as your Next.js project&lt;/span&gt;
    proxy_pass http://localhost:3000&lt;span class="p"&gt;;&lt;/span&gt;
    proxy_http_version 1.1&lt;span class="p"&gt;;&lt;/span&gt;
    proxy_set_header Upgrade &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    proxy_set_header Connection &lt;span class="s1"&gt;'upgrade'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    proxy_set_header Host &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    proxy_cache_bypass &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="c"&gt;# simple headers&lt;/span&gt;
  add_header Strict-Transport-Security &lt;span class="s2"&gt;"max-age=31536000; includeSubDomains; preload"&lt;/span&gt; always&lt;span class="p"&gt;;&lt;/span&gt;
  add_header X-XSS-Protection          &lt;span class="s2"&gt;"1; mode=block"&lt;/span&gt; always&lt;span class="p"&gt;;&lt;/span&gt;
  add_header X-Frame-Options DENY always&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c"&gt;# this will serve the project on port 80&lt;/span&gt;
  listen 80&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Verify and reload nginx for it to take effect
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# check all working&lt;/span&gt;
nginx &lt;span class="nt"&gt;-t&lt;/span&gt;

&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /etc/nginx/sites-available/&amp;lt;new_domain&amp;gt; /etc/nginx/sites-enabled/

systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  PS. Do NOT forget
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;UPDATE &lt;code&gt;host records&lt;/code&gt;: point  to server IP (&lt;a href="https://www.namecheap.com/support/knowledgebase/article.aspx/579/2237/which-record-type-option-should-i-choose-for-the-information-im-about-to-enter/"&gt;which record type to choose&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Refs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-20-04"&gt;Digital ocean guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.debian.org/Nginx/DirectoryStructure"&gt;Nginx Directory Structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nginx.org/en/docs/beginners_guide.html"&gt;nginx beginners guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  SSL
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Install &lt;code&gt;certbot&lt;/code&gt; and some preparation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;certbot python3-certbot-nginx

&lt;span class="c"&gt;# firewall settings&lt;/span&gt;
ufw allow &lt;span class="s1"&gt;'Nginx Full'&lt;/span&gt;
ufw allow &lt;span class="s1"&gt;'Nginx HTTPS'&lt;/span&gt;
ufw deny &lt;span class="s1"&gt;'Nginx HTTP'&lt;/span&gt;
ufw status

&lt;span class="c"&gt;# check if the &amp;lt;server_name&amp;gt; is exactly the format "example.com www.example.com"&lt;/span&gt;
nano /etc/nginx/sites-available/example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Obtain the SSL/TLS Certificate
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# do not forget the '-d' before www.example.com&lt;/span&gt;
certbot &lt;span class="nt"&gt;--nginx&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; example.com &lt;span class="nt"&gt;-d&lt;/span&gt; www.example.com
&lt;span class="c"&gt;# enter your email...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Once you configure HTTPS, Certbot completes generating the certificate and reloads Nginx with the new settings.&lt;/p&gt;

&lt;p&gt;Finally, the output displays that you have successfully generated a certificate and specifies the location of the certificate on your server. &lt;code&gt;/etc/letsencrypt/live/example.com/fullchain.pem (success)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ref: &lt;a href="https://phoenixnap.com/kb/letsencrypt-nginx"&gt;How to Secure Nginx with Let's Encrypt On Ubuntu 20.04&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you open your nginx file now &lt;code&gt;nano /etc/nginx/sites-available/example.com&lt;/code&gt;, you'll find the extra info has been added:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;server &lt;span class="o"&gt;{&lt;/span&gt;
  server_name &amp;lt;new_domain&amp;gt; www.&amp;lt;new_domain&amp;gt;&lt;span class="p"&gt;;&lt;/span&gt;

  location / &lt;span class="o"&gt;{&lt;/span&gt;
    proxy_pass http://localhost:3000&lt;span class="p"&gt;;&lt;/span&gt;
    proxy_http_version 1.1&lt;span class="p"&gt;;&lt;/span&gt;
    proxy_set_header Upgrade &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    proxy_set_header Connection &lt;span class="s1"&gt;'upgrade'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    proxy_set_header Host &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    proxy_cache_bypass &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  add_header Strict-Transport-Security &lt;span class="s2"&gt;"max-age=31536000; includeSubDomains; preload"&lt;/span&gt; always&lt;span class="p"&gt;;&lt;/span&gt;
  add_header X-XSS-Protection          &lt;span class="s2"&gt;"1; mode=block"&lt;/span&gt; always&lt;span class="p"&gt;;&lt;/span&gt;
  add_header X-Frame-Options DENY always&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c"&gt;# ↓ the following lines are added by Certbot&lt;/span&gt;

  listen 443 ssl&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;# managed by Certbot&lt;/span&gt;
  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;# managed by Certbot&lt;/span&gt;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;# managed by Certbot&lt;/span&gt;
  include /etc/letsencrypt/options-ssl-nginx.conf&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;# managed by Certbot&lt;/span&gt;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;# managed by Certbot&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

server &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="nv"&gt;$host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; www.example.com&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return &lt;/span&gt;301 https://&lt;span class="nv"&gt;$host$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="c"&gt;# managed by Certbot&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; example.com&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return &lt;/span&gt;301 https://&lt;span class="nv"&gt;$host$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="c"&gt;# managed by Certbot&lt;/span&gt;

  server_name example.com www.example.com&lt;span class="p"&gt;;&lt;/span&gt;
  listen 80&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;404&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;# managed by Certbot&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="c"&gt;# an extra for some reason...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# check certificate's auto-renewal&lt;/span&gt;
certbot renew &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Setup Cronjob to Enable Automatic Certificate Renewal
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# open Crontab&lt;/span&gt;
crontab &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a line:&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;# Schedule it to run daily at a specified time (in this example, it does so at 05:00 a.m.)&lt;/span&gt;
0 5 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /usr/bin/certbot renew &lt;span class="nt"&gt;--quiet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Maintain
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# in remote &amp;lt;site_folder&amp;gt;&lt;/span&gt;
git pull &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn build &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pm2 restart peiwen.me
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Useful articles 😄
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://help.ubuntu.com/community/LinuxFilesystemTreeOverview"&gt;Linux Filesystem Tree Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://manpages.ubuntu.com/manpages/bionic/man7/file-hierarchy.7.html"&gt;Ubuntu manual - file hierarchy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mariestarck.com/add-google-analytics-to-your-next-js-application-in-5-easy-steps/"&gt;Add Google Analytics to NextJS App&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vp</category>
      <category>ubuntu</category>
      <category>nextjs</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Django Retail Website Deployment</title>
      <dc:creator>Peiwen Li</dc:creator>
      <pubDate>Sat, 16 Jul 2022 15:02:27 +0000</pubDate>
      <link>https://dev.to/ld8/django-retail-website-deployment-266l</link>
      <guid>https://dev.to/ld8/django-retail-website-deployment-266l</guid>
      <description>&lt;p&gt;After a month of development of this retail website, this is the note on how to deploy this django app on VPS ubuntu 18&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally the &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-18-04"&gt;Deployment on Ubuntu 18.04&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt;:&lt;br&gt;
Don't forget the &lt;a href="https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/"&gt;official checklist&lt;/a&gt; before your deployment. And delete all migrations files in &lt;code&gt;migrations&lt;/code&gt; folder except for &lt;code&gt;__init__.py&lt;/code&gt; for a clean start. And do not forget to &lt;code&gt;pip freeze &amp;gt; requirements.txt&lt;/code&gt; before commiting your project to be cloned to the server.&lt;/p&gt;



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

&lt;ol&gt;
&lt;li&gt;connect to the server with SSH: &lt;a href="https://serversforhackers.com/c/configuring-ssh-locally"&gt;setting up SSH&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;update &lt;code&gt;apt&lt;/code&gt; package index
&lt;/li&gt;
&lt;/ol&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-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;install python: Ubuntu 18.04 came with python 3.6, you can verify this by typing:
&lt;/li&gt;
&lt;/ol&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;python3 &lt;span class="nt"&gt;-V&lt;/span&gt;
   Python 3.6.9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;other files to install: &lt;code&gt;pip&lt;/code&gt;, the Python development files needed to build Gunicorn later, the Postgres database system and the libraries needed to interact with it, and the Nginx web server:
&lt;/li&gt;
&lt;/ol&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;python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;upgrade pip and install virtual env
&lt;/li&gt;
&lt;/ol&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; &lt;span class="nt"&gt;-H&lt;/span&gt; pip3 &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; pip
   &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; pip3 &lt;span class="nb"&gt;install &lt;/span&gt;virtualenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;add root user and grant privilege: (&lt;a href="https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-18-04"&gt;more&lt;/a&gt; about initial server setup with Ubuntu 18.4)
&lt;/li&gt;
&lt;/ol&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;adduser username
   ......
   &lt;span class="nv"&gt;$ &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;username
   &lt;span class="c"&gt;# privilege granted for this user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;### in Ubuntu, 'root' directory and 'user home' directory are different&lt;br&gt;
   &lt;code&gt;root@0-0-0-0:/root$ command under root directory with ultimate root user signed in&lt;/code&gt;&lt;br&gt;
   ### 'user home' directory is&lt;br&gt;
   &lt;code&gt;username@0-0-0-0:/root$ command under root directory using 'user' signed in&lt;/code&gt;&lt;br&gt;
   &lt;code&gt;username@0-0-0-0:~$ command under user's home directory, and it's usually in /root/home/username/ directory&lt;/code&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Creating PostgreSQL Database and User&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Log&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;interactive&lt;/span&gt; &lt;span class="n"&gt;Postgres&lt;/span&gt; &lt;span class="k"&gt;session&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="n"&gt;postgres&lt;/span&gt; &lt;span class="n"&gt;psql&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="k"&gt;database&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;myproject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;careful&lt;/span&gt; &lt;span class="n"&gt;here&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;if&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;need&lt;/span&gt; &lt;span class="n"&gt;utf&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="k"&gt;encoding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="n"&gt;specify&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;new_db_name&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="k"&gt;ENCODING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'UTF8'&lt;/span&gt; &lt;span class="n"&gt;LC_CTYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ru_RU.UTF-8'&lt;/span&gt; &lt;span class="n"&gt;LC_COLLATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ru_RU.UTF-8'&lt;/span&gt; &lt;span class="k"&gt;OWNER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;postgres&lt;/span&gt; &lt;span class="k"&gt;TEMPLATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;template0&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;USER&lt;/span&gt; &lt;span class="n"&gt;myprojectuser&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;PASSWORD&lt;/span&gt; &lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;modify&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;few&lt;/span&gt; &lt;span class="k"&gt;connection&lt;/span&gt; &lt;span class="k"&gt;parameters&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;setting&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;encoding&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="n"&gt;UTF&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;myprojectuser&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;client_encoding&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="s1"&gt;'utf8'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;setting&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt; &lt;span class="k"&gt;isolation&lt;/span&gt; &lt;span class="n"&gt;scheme&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="k"&gt;read&lt;/span&gt; &lt;span class="k"&gt;committed&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;which&lt;/span&gt; &lt;span class="n"&gt;blocks&lt;/span&gt; &lt;span class="k"&gt;reads&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="k"&gt;uncommitted&lt;/span&gt; &lt;span class="n"&gt;transactions&lt;/span&gt;
&lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;myprojectuser&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;default_transaction_isolation&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="s1"&gt;'read committed'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;setting&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="k"&gt;By&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;our&lt;/span&gt; &lt;span class="n"&gt;Django&lt;/span&gt; &lt;span class="n"&gt;projects&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;UTC&lt;/span&gt;
&lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;myprojectuser&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="s1"&gt;'UTC'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;give&lt;/span&gt; &lt;span class="n"&gt;our&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt; &lt;span class="k"&gt;access&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="n"&gt;administer&lt;/span&gt; &lt;span class="n"&gt;our&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="k"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;myproject&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;myprojectuser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;quit&lt;/span&gt; &lt;span class="n"&gt;PostgresSQL&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;useful&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;see&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="n"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;du&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="k"&gt;database&lt;/span&gt;
&lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;database_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;strong&gt;Some useful sql commands&lt;/strong&gt; &lt;a href="https://www.postgresqltutorial.com/psql-commands/"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: it doesn't matter whether you set your database name to capital letters or not when you setting up, they will convert uppercase to lowercase anyway... However, the password is case sensitive...&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Host a project on server&lt;/strong&gt;&lt;br&gt;
Do not forget to &lt;code&gt;pip freeze &amp;gt; requirements.txt&lt;/code&gt; before commiting your project to be cloned to the server&lt;/p&gt;

&lt;p&gt;&lt;em&gt;cloning&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;$ su username&lt;/code&gt; Switch to a User which you just created and have the root privilege&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$ cd ~/&lt;/code&gt; go to the user's home directory&lt;/li&gt;
&lt;li&gt;if you haven't installed git: &lt;code&gt;$ sudo apt install git&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$ git clone repo/HTTP/address&lt;/code&gt; CLONE the repo&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$ cd project_directory&lt;/code&gt; go to this project's directory&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$ virtualenv venv&lt;/code&gt; create the virtual environment&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$ source venv/bin/activate&lt;/code&gt; activate the virtual environment
&lt;strong&gt;Note&lt;/strong&gt;: in venv, you can use pip instead of pip3, python instead of python3&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(venv)$ pip install -r requirements.txt&lt;/code&gt; install all packages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(venv)$ nano project/foler/settings.py&lt;/code&gt; adjust a few things in settings:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Note&lt;/strong&gt;: Of course you can choose to edit the file locally and commit to GitHub, then pull it to your server, the important things are the following:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;STATIC_ROOT = os.path.join(BASE_DIR, 'static/')&lt;/code&gt; Normally you wouldn't have to set this up locally when developing&lt;/li&gt;
&lt;li&gt;change the database from &lt;code&gt;sqlite3&lt;/code&gt; to &lt;code&gt;postgres&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="n"&gt;DATABASES&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'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="s"&gt;'ENGINE'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'django.db.backends.postgresql_psycopg2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s"&gt;'NAME'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'myproject_database_name'&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;'myproject_database_user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s"&gt;'PASSWORD'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'myproject_database_user_password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s"&gt;'HOST'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s"&gt;'PORT'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . ., 'localhost']&lt;/code&gt; be careful here, at the end, include 'localhost' as you'll be proxying connections through a local Nginx instance, whatever that is...&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;setting up &lt;code&gt;SECRET_KEY&lt;/code&gt; (followed &lt;a href="https://help.pythonanywhere.com/pages/environment-variables-for-web-apps/"&gt;this blog&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- `$ pip install python-dotenv` or simply included in your `requirements.txt` file: `echo python-doctenv &amp;gt;&amp;gt; requirements.txt` before pulling the repo
- on server:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ```bash
  $ cd ~/project_directory/`
  $ echo "export SECRET_KEY=seekratevalue" &amp;gt; .env
  ```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  You can edit `.env` file and adding more environment variable, or you can use commandline like so:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ```bash
  # you can also directly export one-off environment variable directly on commandline
  $ export CAPITAL_NAME=true
  # it doesn't matter whether you add quotation marks for the value when you export, even when they are strings, the value 'true' will always be a string

  # if you export directly in command, be careful of ! as it needs to be excaped \!
  $ export PASSWD_DB = something\!and@#others
  ```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  But I would recommand to use `.env` file if you set it up already. Keep everything in one place.

- in `wsgi.py` file in the same directory of `settings.py`, as well as `manage.py` file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ```python
  import os
  from dotenv import load_dotenv
  project_folder = os.path.expanduser('~/my-project-dir')  # adjust as appropriate
  load_dotenv(os.path.join(project_folder, '.env'))
  ```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Be very careful the path of the folder, or you won't get the correct env variable. A way to check whether you have the variable in your environment is go to `python manage.py shell` and `import os`, like below:

- finally in `settings.py`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ```python
  import os
  SECRET_KEY = os.getenv("SECRET_KEY")
  ```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;$ python manage.py migrate&lt;/code&gt; no need to &lt;code&gt;make migrations&lt;/code&gt; in production&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;$ python manage.py collectstatic&lt;/code&gt; to collect static files&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allow port 8000 to test locally: &lt;code&gt;$ sudo ufw allow 8000&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;$ python manage.py runserver 0.0.0.0:8000&lt;/code&gt;, then you should be able to visit the site through 'your_ip:8000' port.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;$ gunicorn --bind 0.0.0.0:8000 myproject.wsgi&lt;/code&gt; to bind it with &lt;code&gt;unicorn&lt;/code&gt;, testing Gunicorn's ability to serve the project. You would still be able to visit the site through the same port just this time, it would be served by gunicorn (Note: &lt;code&gt;myproject&lt;/code&gt; in &lt;code&gt;myproject.wsgi&lt;/code&gt; is the folder where &lt;code&gt;wsgi.py&lt;/code&gt; file exists)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;$ deactivate&lt;/code&gt; now we can exit the virtual environment&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;strong&gt;Gunicorn: Creating systems Socket and Service Files&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;$ sudo nano /etc/systemd/system/gunicorn.socket&lt;/code&gt; &lt;strong&gt;system socket&lt;/strong&gt; creation
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   # /etc/systemd/system/gunicorn.socket
   [Unit]
   Description=gunicorn socket

   [Socket]
   ListenStream=/run/gunicorn.sock

   [Install]
   WantedBy=sockets.target
   # save and close
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;$ sudo nano /etc/systemd/system/gunicorn.service&lt;/code&gt; &lt;strong&gt;system service file&lt;/strong&gt; for Gunicorn:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   [Unit]
   Description=gunicorn daemon
   Requires=gunicorn.socket
   After=network.target

   [Service]
   User=sammy
   Group=www-data
   WorkingDirectory=/home/sammy/myprojectdir
   ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn \
             --access-logfile - \
             --workers 3 \
             --bind unix:/run/gunicorn.sock \
             myproject.wsgi:application

   [Install]
   WantedBy=multi-user.target

   # Note: User is the system user with writing privilege, so change that, also change 'WorkingDirectory' and 'ExecStart', DO NOT forget 'project_folder_contains_wsgi.wsgi:application'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Start and enable Gunicorn socket, so that connections can be handled by gunicorn.service:
&lt;/li&gt;
&lt;/ol&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;systemctl start gunicorn.socket
   &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;gunicorn.socket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Status Check:
&lt;/li&gt;
&lt;/ol&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;systemctl status gunicorn.socket
   &lt;span class="c"&gt;# Check the status of the process to find out whether it was able to start&lt;/span&gt;

   &lt;span class="nv"&gt;$ &lt;/span&gt;file /run/gunicorn.sock
   /run/gunicorn.sock: socket
   &lt;span class="c"&gt;# check for the existence of the gunicorn.sock file within the /run directory&lt;/span&gt;

   &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; gunicorn.socket
   &lt;span class="c"&gt;# Check the Gunicorn socket’s logs by typing for debugging&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Test Socket Activation:
&lt;/li&gt;
&lt;/ol&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;systemctl status gunicorn
   &lt;span class="c"&gt;# gunicorn.service won't be active since there's no connections made, so this output should be 'Active: inactive (dead)'&lt;/span&gt;

   &lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;--unix-socket&lt;/span&gt; /run/gunicorn.sock localhost
   &lt;span class="c"&gt;# To test the socket activation mechanism, we can send a connection to the socket through curl by typing the above, and you should be able to see the HTML output, meaning that Gunicorn is serving your Django app&lt;/span&gt;

   &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status gunicorn
   &lt;span class="c"&gt;# You can verify that the Gunicorn service is running by typing the above&lt;/span&gt;

   &lt;span class="c"&gt;# check the logs for additional details:&lt;/span&gt;
   &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; gunicorn

   &lt;span class="c"&gt;# Check your /etc/systemd/system/gunicorn.service file for problems. If you make changes to the /etc/systemd/system/gunicorn.service file, reload the daemon to reread the service definition and restart the Gunicorn process by typing:&lt;/span&gt;
   &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reload
   &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart gunicorn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Note: Make sure everything above is debugged before continue&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Nginx: Configuration to Proxy Pass to Gunicorn&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After Gunicorn is set, Nginx is to be configured to pass traffic to the process&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;$ sudo nano /etc/nginx/sites-available/myproject&lt;/code&gt; create a &lt;strong&gt;server block&lt;/strong&gt; for Nginx (&lt;em&gt;myproject&lt;/em&gt; name is case sensitive)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside: open a new &lt;em&gt;server block&lt;/em&gt;; to ignore problems with finding a favicon; tell Nginx to find static assets and media assets:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   server {
       listen 80;
       server_name server_domain_or_IP;

       location = /favicon.ico { access_log off; log_not_found off; }
       location /static/ {
           root /home/sammy/myprojectdir;
       }
       location /media/ {
           root /home/sammy/myprojectdir;
       }

       location / {
           include proxy_params;
           proxy_pass http://unix:/run/gunicorn.sock;
       }
   }

   # save and close the file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Afterwards:
&lt;/li&gt;
&lt;/ol&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 ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
   &lt;span class="c"&gt;# Enable the file by linking it to the `sites-enabled` directory&lt;/span&gt;

   &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt;
   &lt;span class="c"&gt;# Test your Nginx configuration for syntax errors by typing the above&lt;/span&gt;

   &lt;span class="c"&gt;# If no errors are reported, go ahead and restart Nginx by typing:&lt;/span&gt;
   &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;4) Firewall settings:&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;# Finally, we need to open up our firewall to normal traffic on port 80. Since we no longer need access to the development server, we can remove the rule to open port 8000 as well:&lt;/span&gt;
   &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw delete allow 8000
   &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow &lt;span class="s1"&gt;'Nginx Full'&lt;/span&gt;

   &lt;span class="c"&gt;# check the registered profiles to be managed by UFW&lt;/span&gt;
   &lt;span class="nv"&gt;$ &lt;/span&gt;ufw app list
   Available applications:
    Nginx Full
     Nginx HTTP
     Nginx HTTPS
     OpenSSH

   &lt;span class="c"&gt;# make sure that the firewall allows SSH connections&lt;/span&gt;
   &lt;span class="nv"&gt;$ &lt;/span&gt;ufw allow OpenSSH
   &lt;span class="c"&gt;# enable the firewall by typing&lt;/span&gt;
   &lt;span class="nv"&gt;$ &lt;/span&gt;ufw &lt;span class="nb"&gt;enable&lt;/span&gt;
   &lt;span class="c"&gt;# type "y" and press `Enter` to proceed&lt;/span&gt;

   &lt;span class="c"&gt;# You can see that SSH connections are still allowed by typing:&lt;/span&gt;
   &lt;span class="nv"&gt;$ &lt;/span&gt;ufw status
   &lt;span class="c"&gt;# you should be able to see all apps allowed by the firewall&lt;/span&gt;

   &lt;span class="c"&gt;# Note: you can log in by using a user's name as well&lt;/span&gt;
   &lt;span class="nv"&gt;$ &lt;/span&gt;ssh sammy@your_server_ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Make sure:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You have run &lt;a href="https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-18-04"&gt;initial server setup for Ubuntu 18.04&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your domain names (&lt;a href="https://docs.ispsystem.com/ispmanager-lite/domain-names/resource-records#Resourcerecords-A-record"&gt;A-record&lt;/a&gt;) are pointing to your VPS's IP address: &lt;a href="https://www.hostinger.com/tutorials/dns/how-to-point-domain-to-vps"&gt;How to&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="c"&gt;# basically if you run:&lt;/span&gt;
   &lt;span class="nv"&gt;$ &lt;/span&gt;dig NS +short your_domain.com
   &lt;span class="c"&gt;# shows the desired host name servers and:&lt;/span&gt;

   &lt;span class="nv"&gt;$ &lt;/span&gt;dig A +short your_domain.com
   &lt;span class="c"&gt;# shoes your VPS IP, then you are good to go&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might need to wait for the change to take effect, it takes up to 24 hours if you requested DNS propagation (changed your DNS in any way)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Nginx installed: &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-18-04"&gt;How to&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-18-04"&gt;SSL with &lt;em&gt;Let's Certbot&lt;/em&gt; on &lt;em&gt;Nginx&lt;/em&gt;&lt;/a&gt;&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# installation&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;python-certbot-nginx

&lt;span class="c"&gt;# open the server block file created earlier&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/nginx/sites-available/myproject
&lt;span class="c"&gt;# 'myproject' name is case sensitive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;find the existing &lt;code&gt;server_name&lt;/code&gt; line, and make sure it looks like this:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
server_name example.com www.example.com;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save and exit.&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;# always verify the syntax of your configuration edits:&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt;

&lt;span class="c"&gt;# Once your configuration file’s syntax is correct, reload Nginx to load the new configuration:&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload nginx

&lt;span class="c"&gt;# check your ufw (firewall) status&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw status

&lt;span class="c"&gt;# if there's no 'Nginx Full' or simply 'Nginx HTTP':&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow &lt;span class="s1"&gt;'Nginx Full'&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw delete allow &lt;span class="s1"&gt;'Nginx HTTP'&lt;/span&gt;

&lt;span class="c"&gt;# Now when you run 'ufw status' check, it should be looking like this:&lt;/span&gt;
To                         Action      From
&lt;span class="nt"&gt;--&lt;/span&gt;                         &lt;span class="nt"&gt;------&lt;/span&gt;      &lt;span class="nt"&gt;----&lt;/span&gt;
OpenSSH                    ALLOW       Anywhere
Nginx HTTP                 ALLOW       Anywhere
OpenSSH &lt;span class="o"&gt;(&lt;/span&gt;v6&lt;span class="o"&gt;)&lt;/span&gt;               ALLOW       Anywhere &lt;span class="o"&gt;(&lt;/span&gt;v6&lt;span class="o"&gt;)&lt;/span&gt;
Nginx HTTP &lt;span class="o"&gt;(&lt;/span&gt;v6&lt;span class="o"&gt;)&lt;/span&gt;            ALLOW       Anywhere &lt;span class="o"&gt;(&lt;/span&gt;v6&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Finally, Obtaining an SSL Certificate from Cerbot&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;certbot &lt;span class="nt"&gt;--nginx&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; example.com &lt;span class="nt"&gt;-d&lt;/span&gt; www.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;This runs &lt;code&gt;certbot&lt;/code&gt; with the &lt;code&gt;--nginx&lt;/code&gt; plugin&lt;/li&gt;
&lt;li&gt;using &lt;code&gt;-d&lt;/code&gt; to specify the names we’d like the certificate to be valid for&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Try reloading your website using &lt;code&gt;https://&lt;/code&gt; and notice your browser’s security indicator. It should indicate that the site is properly secured, usually with a green lock icon. If you test your server using the &lt;a href="https://www.ssllabs.com/ssltest/"&gt;SSL Labs Server Test&lt;/a&gt;, it will get an &lt;strong&gt;A&lt;/strong&gt; grade.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# You can check certificate's auto-renewal by typing:&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;certbot renew &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Further reading: &lt;a href="https://certbot.eff.org/docs/"&gt;Certbot doc&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Troubleshooting Nginx and Gunicorn&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Near the end of &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-18-04"&gt;this post&lt;/a&gt;, there's a session of troubleshooting.&lt;/p&gt;

</description>
      <category>django</category>
      <category>deploy</category>
      <category>vps</category>
      <category>ubuntu</category>
    </item>
    <item>
      <title>Retail Website built with Django P5 (2020-02-16)</title>
      <dc:creator>Peiwen Li</dc:creator>
      <pubDate>Sun, 15 May 2022 02:41:16 +0000</pubDate>
      <link>https://dev.to/ld8/daily-notes-retail-website-p5-2020-02-16-23cl</link>
      <guid>https://dev.to/ld8/daily-notes-retail-website-p5-2020-02-16-23cl</guid>
      <description>&lt;h2&gt;
  
  
  Django:
&lt;/h2&gt;




&lt;h3&gt;
  
  
  delete one table in django sqlite: &lt;a href="https://stackoverflow.com/a/17041402/11901269"&gt;SO comment&lt;/a&gt;
&lt;/h3&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 manage.py dbshell
&lt;span class="c"&gt;# if you do not know which table to delete/drop, run:&lt;/span&gt;
sqlite &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; SELECT &lt;span class="k"&gt;*&lt;/span&gt; FROM sqlite_master WHERE &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'table'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c"&gt;# if you already know:&lt;/span&gt;
sqlite &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; DROP TABLE appname_modelname&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c"&gt;# DO NOT FORGET the semi-colon at the end, otherwise it will prompt '...&amp;gt;' signalling the expression is unfinished&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;ul&gt;
&lt;li&gt;### where should &lt;code&gt;signal.py&lt;/code&gt; file lives: 
&lt;a href="https://simpleisbetterthancomplex.com/tutorial/2016/07/28/how-to-create-django-signals.html"&gt;article by Vitor Freitas&lt;/a&gt; &amp;amp; &lt;a href="https://docs.djangoproject.com/en/3.0/topics/signals/"&gt;Django official doc&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;create &lt;code&gt;signal.py&lt;/code&gt; file in the same directory as &lt;code&gt;models.py&lt;/code&gt; and &lt;code&gt;urls.py&lt;/code&gt; etc.&lt;/li&gt;
&lt;li&gt;edit the file, write your code&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;add following code in &lt;code&gt;apps.py&lt;/code&gt; file under the same directory&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ready&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;appName.signals&lt;/span&gt; &lt;span class="c1"&gt;# noqa
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;register in &lt;code&gt;settings.py&lt;/code&gt;, in &lt;code&gt;INSTALLED_APPS&lt;/code&gt;, register &lt;code&gt;'appName.apps.appNameConfig',&lt;/code&gt; for signal.py to work properly&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;follow the four steps&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;### models - &lt;code&gt;DateTimeField(auto_now=True)&lt;/code&gt; and &lt;code&gt;DateTimeField(auto_now_add=True)&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DateTimeField(auto_now=True)&lt;/code&gt; -- update everytime this model instance is edited&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DateTimeField(auto_now_add=True)&lt;/code&gt; -- set the time once when this model instance is created&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;




&lt;ul&gt;
&lt;li&gt;### SO ask and answered &lt;a href="https://stackoverflow.com/questions/60256470/django-logout-view-customisation-fail/60256968?noredirect=1#comment106584955_60256968"&gt;Django - logout view customisation fail&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;
  
  
  context processor
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;adding a context processor to your project if you find repetitive bahavior in passing the same context to different views:

&lt;ol&gt;
&lt;li&gt;in the same directory of &lt;code&gt;models.py&lt;/code&gt; create a file named &lt;code&gt;context_processors.py&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;create a function:
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.template.context_processors&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;category_context_processor&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;categories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Category&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'categories'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3. add this processor to `settings.py`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```python
TEMPLATES = [
{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [os.path.join(BASE_DIR, 'templates')],
    'APP_DIRS': True,
    'OPTIONS': {
        'context_processors': [
            ... # other processors
            ... # add code below:&amp;lt;app-name&amp;gt;.&amp;lt;file-name&amp;gt;.&amp;lt;function-name&amp;gt;
            'app-name.context_processors.category_context_processor',
                ],
            },
        },
    ]
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you don't have to pass &lt;code&gt;categories&lt;/code&gt; to each view now! And this code will run on every request on the site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bootstrap
&lt;/h2&gt;




&lt;h3&gt;
  
  
  to override default
&lt;/h3&gt;

&lt;p&gt;simply add an id to body tag&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"bootstrap-override"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and refer to this id when overriding default css&lt;/p&gt;




&lt;h2&gt;
  
  
  General knowledge
&lt;/h2&gt;




&lt;h3&gt;
  
  
  url in css:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Because css is a static file, so the url inside is better be static as well. so just use relative url for url() in css files.&lt;/li&gt;
&lt;li&gt;for some reason it's slow to load a file when you pupdate it in css. sometime I have to restart the local server for it to take effect&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ## &lt;a href="https://django-debug-toolbar.readthedocs.io/en/latest/index.html"&gt;Debug Toolbar&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To optimize database queries: &lt;a href="https://simpleisbetterthancomplex.com/tips/2016/05/16/django-tip-3-optimize-database-queries.html"&gt;article&lt;/a&gt; by Victor Freitas

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;select_related&lt;/code&gt; to avoid unnecessary queries&lt;/li&gt;
&lt;li&gt;Use Debug Toolbar to track the queries&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>django</category>
      <category>dailynotes</category>
    </item>
    <item>
      <title>Retail Website built with Django P4 (2020-02-10)</title>
      <dc:creator>Peiwen Li</dc:creator>
      <pubDate>Sun, 15 May 2022 02:38:21 +0000</pubDate>
      <link>https://dev.to/ld8/daily-notes-retail-website-in-russian-p4-2020-02-10-405e</link>
      <guid>https://dev.to/ld8/daily-notes-retail-website-in-russian-p4-2020-02-10-405e</guid>
      <description>&lt;h2&gt;
  
  
  Django:
&lt;/h2&gt;




&lt;h3&gt;
  
  
  template &lt;code&gt;{{forloop.counter0}}&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{% for image in item.itemimage_set.all %}
&lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;data-target=&lt;/span&gt;&lt;span class="s"&gt;"#item{{item.pk}}Carousel"&lt;/span&gt; &lt;span class="na"&gt;data-slide-to=&lt;/span&gt;&lt;span class="s"&gt;"{{forloop.counter0}}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
{% endfor %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;forloop.counter0&lt;/code&gt; is 0-indexed&lt;br&gt;
&lt;code&gt;forloop.counter&lt;/code&gt; is 1-indexed&lt;/p&gt;

&lt;p&gt;more variables in forloop can be found &lt;a href="https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#for"&gt;here&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;forloop.revcounter&lt;/li&gt;
&lt;li&gt;forloop.revcounter0&lt;/li&gt;
&lt;li&gt;forloop.first&lt;/li&gt;
&lt;li&gt;forloop.last&lt;/li&gt;
&lt;li&gt;forloop.parentloop&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ForeignKey.on_delete
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ForeignKey&lt;/code&gt; takes in &lt;code&gt;on_delete&lt;/code&gt; argument to deal with the situation where the &lt;code&gt;ForeignKey&lt;/code&gt; object is being deleted. The value of &lt;code&gt;on_delete&lt;/code&gt; argument represents this behaviour. There are 3 options (In the examples below, &lt;code&gt;Item&lt;/code&gt; model has &lt;code&gt;Category&lt;/code&gt; as a &lt;code&gt;ForeignKey&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;on_delete=models.CASCADE&lt;/code&gt; : deleting a foreign object, i.e. a &lt;code&gt;category&lt;/code&gt;, will automatically delete all of the &lt;code&gt;item&lt;/code&gt;s under that category&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;on_delete=models.PROTECT&lt;/code&gt;: deleteing a foreign object, i.e. a &lt;code&gt;category&lt;/code&gt;, will automatically prompt 'Can Not Delete' if there's &lt;code&gt;item&lt;/code&gt;s under that category, And the &lt;code&gt;item&lt;/code&gt;s will be listed&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;on_delete=models.SET_NULL&lt;/code&gt;: deleteing a foreign object, i.e. a &lt;code&gt;category&lt;/code&gt;, will set this foreign key to &lt;code&gt;Null&lt;/code&gt; in all of the &lt;code&gt;item&lt;/code&gt;s originally under that category.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Google Font
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to Google Fonts: &lt;a href="https://fonts.google.com/"&gt;https://fonts.google.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;add the fonts for your website&lt;/li&gt;
&lt;li&gt;interact with the pop up at bottom right corner&lt;/li&gt;
&lt;li&gt;copy url&lt;/li&gt;
&lt;li&gt;go to your css file&lt;/li&gt;
&lt;li&gt;paste: @import url(...)&lt;/li&gt;
&lt;li&gt;apply the font into css element as usual (font-family: 'Forum', cursive;). you can also copy this on the popup&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Python
&lt;/h2&gt;




&lt;h3&gt;
  
  
  why @property decorator? &lt;a href="https://stackoverflow.com/questions/58558989/what-does-djangos-property-do"&gt;SO question ref&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;the function within the class can be accessed like a class' property instead of a function()&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;you don't have to call it with &lt;code&gt;()&lt;/code&gt; to gain access to the result&lt;/li&gt;
&lt;li&gt;you can pass parameter into it and process existing class values
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;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;50&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;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;birth_date&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;DateField&lt;/span&gt;&lt;span class="p"&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="s"&gt;"Returns the person's full name."&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;'%s %s'&lt;/span&gt; &lt;span class="o"&gt;%&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;first_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="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setter&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="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
     &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;' '&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;first_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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;last_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  VS Code
&lt;/h2&gt;




&lt;p&gt;Shortcuts - Find and replace:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Find: command + F&lt;/li&gt;
&lt;li&gt;Add next occurrence: command + D&lt;/li&gt;
&lt;li&gt;Add ALL occurrences: option + Enter&lt;/li&gt;
&lt;li&gt;Replacement: command + option + F&lt;/li&gt;
&lt;li&gt;Replace: command + Enter&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>django</category>
      <category>dailynotes</category>
    </item>
    <item>
      <title>Retail Website built with Django P3 (2020-02-07)</title>
      <dc:creator>Peiwen Li</dc:creator>
      <pubDate>Sun, 15 May 2022 02:34:44 +0000</pubDate>
      <link>https://dev.to/ld8/daily-notes-retail-website-in-russian-p3-2020-02-07-2n5k</link>
      <guid>https://dev.to/ld8/daily-notes-retail-website-in-russian-p3-2020-02-07-2n5k</guid>
      <description>&lt;h2&gt;
  
  
  Django:
&lt;/h2&gt;




&lt;h3&gt;
  
  
  in &lt;code&gt;urls.py&lt;/code&gt; be careful which goes first
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;app_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'boutique'&lt;/span&gt;
&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;# show index page
&lt;/span&gt;    &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IndexView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'index'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="c1"&gt;# show a specific item
&lt;/span&gt;    &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'item_&amp;lt;int:item_pk&amp;gt;/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ItemDetailView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'item'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="c1"&gt;# show categories of products for men or women
&lt;/span&gt;    &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&amp;lt;slug:gender&amp;gt;/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CategoryListView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'show-all'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="c1"&gt;# show a specific category for men or women
&lt;/span&gt;    &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&amp;lt;slug:gender&amp;gt;/cat_&amp;lt;int:category_pk&amp;gt;/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CategoryListView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'category'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="c1"&gt;# show a specific subcategory under a specific category for men or women
&lt;/span&gt;    &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&amp;lt;slug:gender&amp;gt;/cat_&amp;lt;int:category_pk&amp;gt;/subcat_&amp;lt;int:subcategory_pk&amp;gt;/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CategoryListView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'subcategory'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In this file, if you put &lt;code&gt;item&lt;/code&gt; after &lt;code&gt;subcategory&lt;/code&gt;, &lt;code&gt;item&lt;/code&gt; view will never render the correct page, as it will be hjacked by &lt;code&gt;ListView&lt;/code&gt;s before it.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  models - gender choices
&lt;/h3&gt;

&lt;p&gt;example 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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Category&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;'''Category for men's and women's items'''&lt;/span&gt;
    &lt;span class="n"&gt;gender&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;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Women'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Men'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;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;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;description&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;300&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;uploaded_date&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;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;auto_now_add&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;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="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;verbose_name_plural&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'Categories'&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="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_gender_display&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;' '&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;name&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_category_url&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;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'boutique:category'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'gender'&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_gender_display&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;'category_pk'&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;pk&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  A couple of things to notice in this example:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;gender's choices: 
    * &lt;code&gt;choices&lt;/code&gt; is in small letters
    * &lt;code&gt;choices&lt;/code&gt; is a list with tuples&lt;/li&gt;
&lt;li&gt;access gender's choices: you can use &lt;code&gt;get_FOO_display()&lt;/code&gt; to access a field's choices, checkout &lt;a href="https://docs.djangoproject.com/en/3.0/ref/models/instances/#extra-instance-methods"&gt;this&lt;/a&gt; for more details&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;def get_absolute_url()&lt;/code&gt; in &lt;code&gt;models.py&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;models.py&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;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SomeModel&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="o"&gt;&amp;lt;---&lt;/span&gt;&lt;span class="n"&gt;snip&lt;/span&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt;

    &lt;span class="c1"&gt;# it can be any name you like because it doesn't seem to be inheriting from anything
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_absolute_url&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;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'app_name:view_name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'key'&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;field_name&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="c1"&gt;# reverse returns a string for href content
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When implementing the url into html tag, make sure SomeModel is accessable (either by iteration or it is an object passed through context):&lt;br&gt;&lt;br&gt;
*html&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{{ SomeModel.get_absolute_url }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;link&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  dynamic handling url: checkout this &lt;a href="https://stackoverflow.com/questions/60111776/django-models-py-does-get-absolute-url-function-take-conditions/60111926#60111926"&gt;SO question&lt;/a&gt; I posted
&lt;/h3&gt;

&lt;p&gt;based on the answer by &lt;em&gt;Mathias&lt;/em&gt;, it's not possible unless installing a &lt;a href="https://pypi.org/project/django-middleware-global-request/"&gt;django-middleware-global-request&lt;/a&gt;&lt;br&gt;
Then you can:&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;django_global_request.middleware&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_request&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestModel&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="p"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_absolute_url&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="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'whatever'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You just need to make sure, you could still access this method without any available request. So make sure it's fail save and has a fallback in case of the absence of a request (like in a shell, upgrade, etc.)&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;get_queryset(self)&lt;/code&gt; and &lt;code&gt;get_context_data(self, **kwargs)&lt;/code&gt; in &lt;code&gt;ListView&lt;/code&gt; - &lt;a href="https://ccbv.co.uk/projects/Django/3.0/django.views.generic.list/ListView/"&gt;CCBV&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;_&lt;em&gt;&lt;code&gt;get_queryset()&lt;/code&gt; is more useful in &lt;code&gt;ListView&lt;/code&gt;, because it returns a queryset for templates to render. &lt;code&gt;queryset&lt;/code&gt;s are passed through context automagically! _&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;if a model is defined in the CBV, &lt;code&gt;get_queryset()&lt;/code&gt; will automatically run and acquire &lt;code&gt;model.objects.all()&lt;/code&gt;, if to override it:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SomeView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;---&lt;/span&gt;&lt;span class="n"&gt;snip&lt;/span&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;# context_object_name represents the result of get_queryset()
&lt;/span&gt;    &lt;span class="c1"&gt;# you can directly access this from the template even if you do not set context_object_name
&lt;/span&gt;    &lt;span class="n"&gt;context_object_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'coobna'&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="c1"&gt;# if you still need the default functionality of this function
&lt;/span&gt;      &lt;span class="c1"&gt;# it's like to inherite from it's superior, instead of writing a whole new function
&lt;/span&gt;      &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&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;get_queryset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

      &lt;span class="c1"&gt;# before returning the queryset, you can print(queryset) to debug or for referencing purposes
&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_context_data&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="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
      &lt;span class="c1"&gt;# inherite the functionality from its 'superior'
&lt;/span&gt;      &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&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;get_context_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="c1"&gt;# now you can add more context to it
&lt;/span&gt;      &lt;span class="n"&gt;new_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Category&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;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'new_context'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_context&lt;/span&gt;

      &lt;span class="c1"&gt;# you can always print out the context for debugging
&lt;/span&gt;      &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An example of a ListView:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CategoryListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;'''display a list of items'''&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;Category&lt;/span&gt;
    &lt;span class="n"&gt;template_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'boutique/items.html'&lt;/span&gt;
    &lt;span class="c1"&gt;# context_object_name is actually the result of `get_queryset()`
&lt;/span&gt;    &lt;span class="n"&gt;context_object_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'category_shown'&lt;/span&gt;
    &lt;span class="c1"&gt;# paginate_by = 12
&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="c1"&gt;# get original queryset: Category.objects.all()
&lt;/span&gt;        &lt;span class="n"&gt;qs&lt;/span&gt; &lt;span class="o"&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;get_queryset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;# filter men/women
&lt;/span&gt;        &lt;span class="k"&gt;if&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;kwargs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'gender'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'Women'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;qs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qs&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;gender&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&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;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'gender'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'Men'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;qs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qs&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;gender&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&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;kwargs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'category_pk'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;qs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qs&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;pk&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;kwargs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'category_pk'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="c1"&gt;# print('\nqs= ', qs, '\n')
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;qs&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_context_data&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="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&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;get_context_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# add categories for navbar link texts
&lt;/span&gt;        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'categories'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Category&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="k"&gt;if&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;kwargs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'subcategory_pk'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'subcategory_shown'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_object_or_404&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;SubCategory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'subcategory_pk'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'item_list'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Item&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;subcategory&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;kwargs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'subcategory_pk'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="c1"&gt;# print('\ncontext with subcat= ', context, '\n')
&lt;/span&gt;            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;

        &lt;span class="c1"&gt;# Because context_object_name actually represents the result of `get_queryset()`
&lt;/span&gt;        &lt;span class="c1"&gt;# Therefore, if context_object_name is set to the same name as the context name
&lt;/span&gt;        &lt;span class="c1"&gt;# the following expression can be omitted
&lt;/span&gt;        &lt;span class="c1"&gt;# context['category_shown'] = self.get_queryset()
&lt;/span&gt;        &lt;span class="c1"&gt;# The benefit of this is you don't need to run get_queryset() again!!
&lt;/span&gt;
        &lt;span class="k"&gt;if&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;kwargs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'category_pk'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'item_list'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Item&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;category&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;kwargs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'category_pk'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="c1"&gt;# print('\ncontext= ', context, '\n')
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  DetailView in &lt;a href="https://ccbv.co.uk/projects/Django/3.0/django.views.generic.detail/DetailView/"&gt;CCBV&lt;/a&gt;
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ItemDetailView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DetailView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;'''display an individual item'''&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;Item&lt;/span&gt;
    &lt;span class="n"&gt;template_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'boutique/item.html'&lt;/span&gt;
    &lt;span class="c1"&gt;# no need to specify as default context_object_name depends on the model
&lt;/span&gt;    &lt;span class="c1"&gt;# they are actually the same (with lower case first letter)
&lt;/span&gt;    &lt;span class="c1"&gt;# context_object_name = 'item'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A couple of things to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;context_object_name (see comment above)&lt;/li&gt;
&lt;li&gt;Two lines are sufficient for displaying standard DetailView of an item
### HOWEVER:
One should be very careful about the url value passed into the CBV, checkout &lt;a href="https://stackoverflow.com/questions/60113746/django-detailview-get-object-function-confusion"&gt;my question&lt;/a&gt; on StackO.
url.py
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'item_&amp;lt;int:pk&amp;gt;/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ItemDetailView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'item'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used &lt;strong&gt;&lt;code&gt;path('item_&amp;lt;int:item_pk&amp;gt;/'...)&lt;/code&gt;&lt;/strong&gt; that's why it didn't work. For DetailView to work, you either have to pass in &lt;code&gt;&amp;lt;pk&amp;gt;&lt;/code&gt; or specify in your CBV of your &lt;code&gt;pk_url_kwarg = 'item_pk'&lt;/code&gt;. &lt;a href="https://docs.djangoproject.com/en/3.0/topics/class-based-views/generic-display/#performing-extra-work"&gt;docs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>django</category>
      <category>dailynotes</category>
    </item>
    <item>
      <title>Retail Website built with Django P2 (2020-02-05)</title>
      <dc:creator>Peiwen Li</dc:creator>
      <pubDate>Sun, 15 May 2022 02:34:18 +0000</pubDate>
      <link>https://dev.to/ld8/daily-notes-retail-website-in-russian-p2-2020-02-05-179f</link>
      <guid>https://dev.to/ld8/daily-notes-retail-website-in-russian-p2-2020-02-05-179f</guid>
      <description>&lt;h2&gt;
  
  
  Django:
&lt;/h2&gt;




&lt;h3&gt;
  
  
  Animate your element
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://daneden.github.io/animate.css/"&gt;&lt;strong&gt;Animate.css&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wowjs.uk/docs.html"&gt;&lt;strong&gt;wowjs&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/46547695/how-to-animate-a-image-with-waypoint-or-wow-with-bootstrap-4"&gt;StackO: how to animate an image&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  after cloned a django project:
&lt;/h3&gt;

&lt;p&gt;execute the following command&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;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
&lt;span class="o"&gt;(&lt;/span&gt;venv&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$ &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirement.txt
&lt;span class="o"&gt;(&lt;/span&gt;venv&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$ &lt;/span&gt;pythong manage.py runserver 127.0.0.1:8080 &lt;span class="c"&gt;#(or some other port)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Django admin site
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;$ python manage.py creatsuperuser&lt;/code&gt; creates users with attr &lt;code&gt;is_superuser&lt;/code&gt; or &lt;code&gt;is_staff&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;class ModelAdmin&lt;/code&gt; from &lt;code&gt;django.contrib.admin&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if you need to make changes to the default admin interface, you need to create a object of &lt;code&gt;ModelAdmin&lt;/code&gt; like so: &lt;code&gt;class AuthorAdmin(admin.ModelAdmin):&lt;/code&gt;, this represent &lt;code&gt;Author&lt;/code&gt; model on admin dashboard&lt;/li&gt;
&lt;li&gt;instead of registering like this: &lt;code&gt;admin.site.register(Author)&lt;/code&gt;, you have to use a decorator to your &lt;code&gt;AuthorAdmin&lt;/code&gt; class like so:
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.contrib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;.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;myproject.admin_site&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;custom_admin_site&lt;/span&gt;

&lt;span class="c1"&gt;# Reader and Editor objects have to have a ForeignKey field pointing at Author
&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&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;Reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Editor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;custom_admin_site&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;AuthorAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelAdmin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;ul&gt;
&lt;li&gt;Create &lt;a href="https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#inlinemodeladmin-objects"&gt;InlineModelAdmin&lt;/a&gt; object to display extra info on a model in admin add page.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>django</category>
      <category>dailynotes</category>
    </item>
    <item>
      <title>Retail Website built with Django P1 (2020-02-04)</title>
      <dc:creator>Peiwen Li</dc:creator>
      <pubDate>Sun, 15 May 2022 02:33:54 +0000</pubDate>
      <link>https://dev.to/ld8/daily-notes-retail-website-in-russian-p1-2020-02-04-n20</link>
      <guid>https://dev.to/ld8/daily-notes-retail-website-in-russian-p1-2020-02-04-n20</guid>
      <description>&lt;h2&gt;
  
  
  Django:
&lt;/h2&gt;




&lt;h3&gt;
  
  
  templates builtins!!!
&lt;/h3&gt;

&lt;p&gt;very useful &lt;a href="https://docs.djangoproject.com/en/3.0/ref/templates/builtins/"&gt;&lt;strong&gt;template shortcuts, tags and many more...&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Class based views: Generic VIEWS
&lt;/h3&gt;

&lt;p&gt;learning source: &lt;br&gt;
&lt;a href="https://www.codingforentrepreneurs.com/projects/class-based-views/handling-exceptions-objects"&gt;codingforentrepreneurs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.djangoproject.com/en/3.0/ref/class-based-views/generic-display/"&gt;generic views official documentation&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  to iterate through a folder
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/37270170/iterate-through-a-static-image-folder-in-django"&gt;StackO: iterate through a static image folder in django&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This isn't something Django has built in. But Django is just Python, and you can use normal Python file functions to get your list in the view:&lt;/p&gt;


&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STATIC_ROOT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"styles/jamia"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  filter in queryset
&lt;/h3&gt;

&lt;p&gt;When you know what to look for:&lt;br&gt;
&lt;code&gt;category_handbags = Category.objects.filter(name='Handbags')&lt;/code&gt;&lt;br&gt;
furthur reading: &lt;a href="https://docs.djangoproject.com/en/3.0/ref/models/database-functions/"&gt;Database Functions&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  * filter()
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;By using filter(), we can retrieve a QuerySet of just those books that were published within the last 90 days period, like so:&lt;/p&gt;


&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt; 
&lt;span class="n"&gt;Book&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;date_published__gte&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# __isnull
&lt;/span&gt;&lt;span class="n"&gt;Book&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;author__isnull&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;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# __exact
&lt;/span&gt;&lt;span class="n"&gt;Book&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;title__exact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;
&lt;h4&gt;
  
  
  * exclude()
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;if we use the exact same date_published example above but swap out filter() for exclude(), we’d expect the resulting book count to be the inverse: from 3 of 20 to now 17 of 20:&lt;/p&gt;


&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;
&lt;span class="n"&gt;Book&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;exclude&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;date_published__gte&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# combining filters
&lt;/span&gt;&lt;span class="n"&gt;Book&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;exclude&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author__isnull&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;exclude&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title__exact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;categories.count()&lt;/code&gt; vs &lt;code&gt;len(categories)&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;len()&lt;/code&gt; loads all the data in memory then do the counting&lt;br&gt;&lt;br&gt;
&lt;code&gt;count()&lt;/code&gt; is normally faster when the data is not pre loaded&lt;br&gt;
be careful not to count a queryset manager like &lt;code&gt;categories.first().count()&lt;/code&gt; will prompt &lt;code&gt;AttributeError&lt;/code&gt;; however, &lt;code&gt;categories.first().subcategory_set.count()&lt;/code&gt; will tell you the number of its subcategories correctly and it's the same as &lt;code&gt;len(categories.first().subcategory_set.all())&lt;/code&gt;, as you can see, ALL of the subcategories are read to count the length.&lt;/p&gt;
&lt;h2&gt;
  
  
  Django - Images:
&lt;/h2&gt;


&lt;h3&gt;
  
  
  ImageField
&lt;/h3&gt;

&lt;p&gt;To add &lt;code&gt;ImageField&lt;/code&gt; in a model and to load the image in the database onto your web:&lt;br&gt;
ref: &lt;a href="https://wsvincent.com/django-image-uploads/"&gt;William Vincent&lt;/a&gt;&lt;br&gt;
ref: &lt;a href="https://www.geeksforgeeks.org/imagefield-django-models/"&gt;GeeksforGeeks&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  uploaded images in wrong orientation:
&lt;/h3&gt;

&lt;p&gt;photos taken by phones have this problem sometimes, the &lt;a href="https://medium.com/@giovanni_cortes/rotate-image-in-django-when-saved-in-a-model-8fd98aac8f2a"&gt;post&lt;/a&gt; by Giovanni solved the problem:&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;django.db.models.signals&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;post_save&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.dispatch&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;receiver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ExifTags&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;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&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;ItemImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;item&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;Item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;image&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;ImageField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upload_to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'itemimages'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# solves the problem that uploaded images are in wrong orientation
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rotate_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;orientation&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ExifTags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TAGS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ExifTags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TAGS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'Orientation'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="n"&gt;exif&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_getexif&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;exif&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expand&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="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;exif&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;270&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expand&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="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;exif&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expand&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;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;KeyError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;IndexError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# cases: image don't have getexif
&lt;/span&gt;        &lt;span class="k"&gt;pass&lt;/span&gt;


&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post_save&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ItemImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dispatch_uid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"update_image_item"&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;update_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;BASE_DIR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abspath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="n"&gt;fullpath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BASE_DIR&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;instanc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;
    &lt;span class="n"&gt;rotate_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullpath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;furture reading: &lt;a href="https://www.lfchosting.com/fix-uploaded-images-python-webapps/"&gt;FIX UPLOADED IMAGES IN PYTHON WEBAPPS&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  image files in image field deleted but the file remains in the MEDIA foler
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://timonweb.com/posts/cleanup-files-and-images-on-model-delete-in-django/"&gt;Cleanup Files (and Images) On Model Delete in Django&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ref: Online Retail websites
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.asos.com/women/"&gt;asos&lt;/a&gt;: most referenced in item displaying style, categorisation filtering, most responsive&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://us.louisvuitton.com/eng-us/homepage"&gt;LOUIS VUITTON&lt;/a&gt;: most elegant in wording and minimalistic in styling&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.bottegaveneta.com/us"&gt;BOTTEGA VENETA&lt;/a&gt;: not responsive enough on laptop&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://global.accessorize.com/en-cn/ru?skipRedirection=true"&gt;ACCESSORIZE LONDON&lt;/a&gt;: not responsive enough on laptop&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.kupivip.ru/search?q=&amp;amp;page=2&amp;amp;quantity_per_page=60"&gt;KUPIVIP&lt;/a&gt;: looks cheap&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  django-bootstrap4
&lt;/h2&gt;




&lt;h3&gt;
  
  
  containers, row and columns
&lt;/h3&gt;

&lt;p&gt;containers and grid &lt;a href="https://getbootstrap.com/docs/4.4/examples/grid/#containers"&gt;examples&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;col-sm-12&lt;/code&gt;: when page is 'small' width, occupy 12 columns&lt;br&gt;&lt;br&gt;
&lt;code&gt;col-md-6&lt;/code&gt;: when page is 'medium' width, occupy 6 columns&lt;br&gt;&lt;br&gt;
&lt;code&gt;col-lg-4&lt;/code&gt;: when page is 'large' width, occupy 4 columns&lt;br&gt;&lt;br&gt;
&lt;code&gt;col-4&lt;/code&gt;: At ALL time, occupy 4 columns, unless other rules applied  &lt;/p&gt;

&lt;p&gt;&lt;code&gt;col-md-auto&lt;/code&gt;: when page is 'medium' width, occupy whatever columns remain  &lt;/p&gt;

&lt;h3&gt;
  
  
  Default grid settings: &lt;a href="https://getbootstrap.com/docs/4.4/layout/grid/"&gt;docs/4.4/layout/grid&lt;/a&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;grid-columns&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="err"&gt;12&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;grid-gutter-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;30&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;grid-breakpoints&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="nt"&gt;xs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;      &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nt"&gt;Extra&lt;/span&gt; &lt;span class="nt"&gt;small&lt;/span&gt; &lt;span class="nt"&gt;screen&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nt"&gt;phone&lt;/span&gt;
  &lt;span class="nt"&gt;sm&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;576&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nt"&gt;Small&lt;/span&gt; &lt;span class="nt"&gt;screen&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nt"&gt;phone&lt;/span&gt;
  &lt;span class="nt"&gt;md&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;768&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nt"&gt;Medium&lt;/span&gt; &lt;span class="nt"&gt;screen&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nt"&gt;tablet&lt;/span&gt;
  &lt;span class="nt"&gt;lg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;992&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nt"&gt;Large&lt;/span&gt; &lt;span class="nt"&gt;screen&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nt"&gt;desktop&lt;/span&gt;
  &lt;span class="nt"&gt;xl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;1200&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;  &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nt"&gt;Extra&lt;/span&gt; &lt;span class="nt"&gt;large&lt;/span&gt; &lt;span class="nt"&gt;screen&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nt"&gt;wide&lt;/span&gt; &lt;span class="nt"&gt;desktop&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;container-max-widths&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="nt"&gt;sm&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;540&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="nt"&gt;md&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;720&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="nt"&gt;lg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;960&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="nt"&gt;xl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;1140&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Simply Python:
&lt;/h2&gt;




&lt;h3&gt;
  
  
  to iterate through a dictionary:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;dict.keys()&lt;/code&gt; method and &lt;code&gt;dict.items()&lt;/code&gt; method
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# using dict.keys() method
&lt;/span&gt;&lt;span class="n"&gt;D1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;D1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;D1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;# 1 a
# 2 b
# 3 c
&lt;/span&gt;
&lt;span class="c1"&gt;# using dict.items() method
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;D1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# same result
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>django</category>
      <category>dailynotes</category>
    </item>
    <item>
      <title>React Django Integration</title>
      <dc:creator>Peiwen Li</dc:creator>
      <pubDate>Sun, 15 May 2022 02:29:43 +0000</pubDate>
      <link>https://dev.to/ld8/react-django-integration-1dm7</link>
      <guid>https://dev.to/ld8/react-django-integration-1dm7</guid>
      <description>&lt;h2&gt;
  
  
  Make a Django app as usual
&lt;/h2&gt;

&lt;p&gt;When working with React, Django mainly serves as an API. Django REST framework is a must.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make a React app as usual
&lt;/h2&gt;

&lt;p&gt;The react app can be created with &lt;code&gt;create-react-app&lt;/code&gt;, it doesn't really matter. Whenever you need to make an API request to get data to render, fetch it from the API you just made with Django. Of course you can use dummy data if you start off with React instead of Django.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integration
&lt;/h2&gt;

&lt;p&gt;There should be at least 3 folders in your Django app:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;project/project&lt;/code&gt; folder, meaning the one with &lt;code&gt;settings.py&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;project/api&lt;/code&gt; folder, the one with the api &lt;code&gt;models.py&lt;/code&gt;, &lt;code&gt;serializers.py&lt;/code&gt; etc.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;project/frontend&lt;/code&gt; folder, it's created by &lt;code&gt;manage.py startapp frontend&lt;/code&gt; command and in this folder, more folders should be created:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;src&lt;/code&gt;folder: contains an &lt;code&gt;index.js&lt;/code&gt; file and all other react components in &lt;code&gt;src/components&lt;/code&gt; folder&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;static/frontend&lt;/code&gt; folder: where &lt;code&gt;main.js&lt;/code&gt; file lives after you run &lt;code&gt;npm run build&lt;/code&gt; or &lt;code&gt;npm run dev&lt;/code&gt; (depends on the script you write --&amp;gt; keep reading)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;templates/frontend&lt;/code&gt; folder: where you store your django template &lt;code&gt;index.html&lt;/code&gt;, remember you can use django template language/syntax in these html files&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reminders - Make sure:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;you added &lt;code&gt;frontend&lt;/code&gt; app in your &lt;code&gt;settings.py&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;added &lt;code&gt;{% load static %}&lt;/code&gt; and &lt;code&gt;&amp;lt;script src="{% static 'frontend/main.js' %}&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt; in &lt;code&gt;index.html&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;added &lt;code&gt;index&lt;/code&gt; function in your &lt;code&gt;views.py&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;added according url patters in your &lt;code&gt;urls.py&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;included url patterns in &lt;code&gt;frontend/urls.py&lt;/code&gt; into &lt;code&gt;project/urls.py&lt;/code&gt; file&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Webpack configuration:
&lt;/h2&gt;

&lt;p&gt;Assuming you've had &lt;a href="http://Nodejs.org"&gt;&lt;code&gt;Node.js&lt;/code&gt; installed&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;package.json&lt;/code&gt;
&lt;/h3&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;npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create a &lt;code&gt;package.json&lt;/code&gt; file with all your javascript dependencies, &lt;code&gt;-y&lt;/code&gt; means to install the defaults and not answering any questions&lt;/p&gt;

&lt;p&gt;Now the &lt;code&gt;package.json&lt;/code&gt; file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"frontend"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&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.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&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;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1"&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;"keywords"&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;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ISC"&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;h3&gt;
  
  
  2. install &lt;code&gt;webpack&lt;/code&gt; and &lt;code&gt;webpack-cli&lt;/code&gt;
&lt;/h3&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;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; webpack webpack-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-D&lt;/code&gt; means to install as &lt;em&gt;&lt;strong&gt;D&lt;/strong&gt;evelopment&lt;/em&gt; dependencies&lt;/p&gt;

&lt;p&gt;Now a new key added to &lt;code&gt;package.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&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;"webpack"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.43.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"webpack-cli"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.3.11"&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;h3&gt;
  
  
  3. install &lt;code&gt;babel&lt;/code&gt; and &lt;code&gt;react preset&lt;/code&gt;
&lt;/h3&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;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; @babel/core babel-loader @babel/preset-env @babel/preset-react babel-plugin-transform-class-properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@babel/core&lt;/code&gt;: the babel core package&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;babel-loader&lt;/code&gt;: helps to transpile the code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@babel/preset-env&lt;/code&gt;: compile down ES6 to be compatible with other versions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@babel/preset-react&lt;/code&gt;: react preset&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;babel-plugin-transform-class-properties&lt;/code&gt;: handles static class properties for ES2015 and ES2016&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the &lt;code&gt;package.json&lt;/code&gt; file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...added&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;step&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&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;"@babel/core"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^7.9.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@babel/preset-env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^7.9.5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@babel/preset-react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^7.9.4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"babel-loader"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^8.1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"babel-plugin-transform-class-properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^6.24.1"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...added&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;step&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&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;h3&gt;
  
  
  4. install &lt;code&gt;react&lt;/code&gt; and &lt;code&gt;react-dom&lt;/code&gt;
&lt;/h3&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;npm i react react-dom prop-types
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/prop-types"&gt;prop-types&lt;/a&gt;:
&amp;gt; Runtime type checking for React props and similar objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the &lt;code&gt;package.json&lt;/code&gt; file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...added&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;stop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&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;"prop-types"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^15.7.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^16.13.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"react-dom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^16.13.1"&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;In my project, I also installed other dependencies: &lt;code&gt;$ npm i react-router-dom react-markdown react-syntax-highlighter react-spring styled-components&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And you might need to install more loaders for different file types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;$ npm i -D style-loader css-loader&lt;/code&gt; for css files&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$ npm i -D file-loader url-loader&lt;/code&gt; for image files&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. create file: &lt;code&gt;.babelrc&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;In order to use the previously installed &lt;em&gt;presets&lt;/em&gt; and &lt;em&gt;plugin&lt;/em&gt;, we need to create a &lt;code&gt;.babelrc&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;~/project/frontend/.babelrc&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"presets"&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="s2"&gt;"@babel/preset-env"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@babel/preset-react"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&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="s2"&gt;"transform-class-properties"&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;h3&gt;
  
  
  6. create file: &lt;code&gt;webpack.config.js&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Whenever you use &lt;code&gt;webpack&lt;/code&gt; you'll have this config file. All we want to do here is to load &lt;code&gt;babel-loader&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;js$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/node_modules/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;babel-loader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What the object does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;test&lt;/code&gt;: a regular expression to look through all of the js files&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;exclude&lt;/code&gt;: exclude &lt;code&gt;node_modules&lt;/code&gt; folder&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;use&lt;/code&gt;: the &lt;code&gt;babel-loader&lt;/code&gt; to transpile our code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The above is the simplest webpack config file. In real cases, there must be more &lt;code&gt;loaders&lt;/code&gt; installed, you can refer to the &lt;a href="https://webpack.js.org/loaders/"&gt;offical document&lt;/a&gt; for more information. At the end, my &lt;code&gt;webpack.config.js&lt;/code&gt; becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;m&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;js$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;node_modules|bower_components&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;babel-loader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;presets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@babel/preset-env&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.(&lt;/span&gt;&lt;span class="sr"&gt;png|jpe&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;g|gif|svg&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;$/i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url-loader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;css$/i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;style-loader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;css-loader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7. write &lt;code&gt;scripts&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;To compile our React app which lives in the &lt;code&gt;frontend&lt;/code&gt; app, some scripts have to be defined:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;~/project/frontend/package.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&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;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack --mode development --watch ./src/index.js --output ./static/frontend/main.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack --mode production ./src/index.js --output ./static/frontend/main.js"&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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;The scripts defined above would enable us the following commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;$ npm run dev&lt;/code&gt;: run &lt;code&gt;webpack&lt;/code&gt;, use &lt;code&gt;--mode development&lt;/code&gt;, &lt;code&gt;--watch&lt;/code&gt; every updates in &lt;code&gt;./src/index.js&lt;/code&gt; file, and compile it to &lt;code&gt;./static/frontend/main.js&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$ npm run build&lt;/code&gt;: does a few extra thing for production&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8. &lt;code&gt;$ npm run dev&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;After this script is run, &lt;code&gt;main.js&lt;/code&gt; file will be ready to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes on routing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;In the MAIN &lt;code&gt;urls.py&lt;/code&gt; file, include the frontend urls at then end&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;re_path()&lt;/code&gt; method in frontend &lt;code&gt;urls.py&lt;/code&gt; file to define the url pattern&lt;/li&gt;
&lt;li&gt;Use extra 'negative lookahead' to exclude api calls in order to avoid url clash between different django apps (in this case the &lt;code&gt;frontend&lt;/code&gt; app and my &lt;code&gt;api&lt;/code&gt; app which serves the api calls):&lt;code&gt;re_path(r'^(?!api)(?:.*)/?$', views.index),&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A remember of &lt;code&gt;npm&lt;/code&gt; commands
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;npm uninstall &amp;lt;name&amp;gt;&lt;/code&gt; removes the module from &lt;code&gt;node_modules&lt;/code&gt; but does not update &lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;npm uninstall &amp;lt;name&amp;gt; --save&lt;/code&gt; also removes it from &lt;code&gt;dependencies&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;npm uninstall &amp;lt;name&amp;gt; --save-dev&lt;/code&gt; also removes it from &lt;code&gt;devDependencies&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;npm uninstall -g &amp;lt;name&amp;gt; --save&lt;/code&gt; also removes it globally&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>React Django Deployment</title>
      <dc:creator>Peiwen Li</dc:creator>
      <pubDate>Sun, 15 May 2022 02:29:15 +0000</pubDate>
      <link>https://dev.to/ld8/react-django-deployment-4a63</link>
      <guid>https://dev.to/ld8/react-django-deployment-4a63</guid>
      <description>&lt;p&gt;This is a post about React Django Deployment on VPS Ubuntu LTS 18.04. I couldn't find any detailed guide or tutorials for newbies so I guess sharing my experience is the best I can do for now.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub pull
&lt;/h2&gt;

&lt;p&gt;Basically, everything is up in the repo. All you need is to pull/clone your repo into your Ubuntu directory. Install virtual environment for Django, run &lt;code&gt;pip install -r requirements.txt&lt;/code&gt;, go to your &lt;code&gt;frontend&lt;/code&gt; app where your frontend React files live and run &lt;code&gt;npm install&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But before that you might need to install &lt;code&gt;node.js&lt;/code&gt; and &lt;code&gt;npm&lt;/code&gt;, which should have been a piece of cake however, Ubuntu didn't make it easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install &lt;code&gt;node&lt;/code&gt; and &lt;code&gt;npm&lt;/code&gt; on Ubuntu 18.04
&lt;/h2&gt;

&lt;p&gt;The node.js version on Ubuntu is quite old (8+). So follow these steps:&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;sodu apt &lt;span class="nb"&gt;install &lt;/span&gt;curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;install &lt;code&gt;curl&lt;/code&gt; and download and execute the Node.js 10.x installer:&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;curl &lt;span class="nt"&gt;-sL&lt;/span&gt; https://deb.nodesource.com/setup_10.x | &lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; bash -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then install the package. This will automatically install &lt;code&gt;npm&lt;/code&gt; as well. Thanks for the &lt;a href="https://joshtronic.com/2018/05/08/how-to-install-nodejs-10-on-ubuntu-1804-lts/"&gt;post&lt;/a&gt; by Josh Tronic.&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;nodejs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check your version by typing&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;node &lt;span class="nt"&gt;-v&lt;/span&gt;
v10.20.1
&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nt"&gt;-v&lt;/span&gt;
6.14.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Notes on deployment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;migrattion: remember to ignore migration files when you FIRST deploy the Django app because if you do not and you've made many migrations locally for the mistakes you made during the development process: when deploying the app, migration changes can not be detected, hence no migrations will be made.&lt;/li&gt;
&lt;li&gt;imported image urls: somehow after webpack compiles the js files to &lt;code&gt;main.js&lt;/code&gt;, Django &lt;code&gt;collectstatic&lt;/code&gt; command copies all the necessary static files into the &lt;code&gt;static&lt;/code&gt; folder in root folder, HOWEVER, the url for those imported images (&lt;code&gt;import BG from './assets/img/bg.jpg'&lt;/code&gt;) in js files can not maintain the correct link (to &lt;code&gt;http://www.domain.com/static/img/bg.jpg&lt;/code&gt;), instead, it links to &lt;code&gt;http://www.domain.com/bg.jpg&lt;/code&gt;. I still can't figure out whether it's a webpack.config issue or python settings issue...&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;main.js&lt;/code&gt; is 700kb it's apparently too slow to load from a Russian VPS server to local (China), takes 60 seconds to load. However, it's 7 seconds to load from LA, US. I'll try to split the file (&lt;a href="https://webpack.js.org/guides/code-splitting/"&gt;source&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>An Intro to UmiJS</title>
      <dc:creator>Peiwen Li</dc:creator>
      <pubDate>Sun, 15 May 2022 02:27:30 +0000</pubDate>
      <link>https://dev.to/ld8/an-intro-to-umijs-1630</link>
      <guid>https://dev.to/ld8/an-intro-to-umijs-1630</guid>
      <description>&lt;h2&gt;
  
  
  Why Umi?
&lt;/h2&gt;

&lt;p&gt;Frontend development has been distinguished from backend for quite a while now. Many frameworks and plugins have been developed for frontend developemnt. Sometimes it's difficult to initialise a project because there are too many tools to choose from. To achieve this, &lt;a href="https://umijs.org/"&gt;&lt;em&gt;UmiJS&lt;/em&gt;&lt;/a&gt; came to live.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before everything else -
&lt;/h2&gt;

&lt;p&gt;In order to use Umi (a frontend framework), you need to have &lt;a href="https://nodejs.org/en/"&gt;&lt;em&gt;NodeJS&lt;/em&gt;&lt;/a&gt; installed.&lt;/p&gt;

&lt;p&gt;If you happened to be in China, you can install &lt;em&gt;cnpm&lt;/em&gt; or &lt;em&gt;tyarn&lt;/em&gt; for faster and safer package management:&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;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; cnpm &lt;span class="nt"&gt;--registry&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://registry.npm.taobao.org
&lt;span class="c"&gt;# OR&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;npm i yarn tyarn &lt;span class="nt"&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you can use &lt;code&gt;cnpm&lt;/code&gt;/&lt;code&gt;tyarn&lt;/code&gt; to install your dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Umi Initialisation: Global
&lt;/h2&gt;

&lt;p&gt;You can install umi globally:&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;tyarn global add umi
&lt;span class="c"&gt;# OR&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;cnpm &lt;span class="nb"&gt;install &lt;/span&gt;umi &lt;span class="nt"&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you can use 'umi generator' to fast start some pages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://umijs.org/zh-CN/docs/cli#umi-generate"&gt;generator command&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&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;umi g page index
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will first generate a &lt;code&gt;pages&lt;/code&gt; folder under current directory inside which a &lt;code&gt;index.js&lt;/code&gt; file and a &lt;code&gt;index,css&lt;/code&gt; file will be created automatically. Each &lt;code&gt;js&lt;/code&gt; file in &lt;code&gt;pages&lt;/code&gt; directory will be interpreted as a route. Normally, this command is run at the root directory of the project.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;umi dev
&lt;/li&gt;
&lt;/ul&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;umi dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will start serving the pages on port 8000+.&lt;/p&gt;

&lt;h2&gt;
  
  
  Umi Initialisation: Scaffold
&lt;/h2&gt;

&lt;p&gt;You can also initialise umi project with umi scaffold in a project folder&lt;/p&gt;

&lt;h3&gt;
  
  
  1. make a new directory
&lt;/h3&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;mkdir &lt;/span&gt;antd-testing
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;antd-testing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. install umi
&lt;/h3&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;tyarn create @umijs/umi-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the initialisation process has been complete, following up the configuration of the project.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Install Dependencies &amp;amp; Start
&lt;/h3&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;tyarn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&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;tyarn start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;PS&lt;/strong&gt;: you can use 'Ant Design' default layout by installing &lt;a href="https://www.npmjs.com/package/@ant-design/pro-layout"&gt;&lt;code&gt;pro-layout&lt;/code&gt;&lt;/a&gt; by running:&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;tyarn add @ant-design/pro-layout
&lt;span class="c"&gt;# or&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;cnpm i @ant-design/pro-layout &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, edit &lt;code&gt;.umirc.ts&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;umi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;nodeModulesTransform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="c1"&gt;// add this line&lt;/span&gt;
  &lt;span class="na"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/pages/index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Run script
&lt;/h2&gt;

&lt;p&gt;Now you can run the following commands to start the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;umi dev
&lt;span class="c"&gt;# OR&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;cnpm run dev
&lt;span class="c"&gt;# OR&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;tyarn start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a href="https://umijs.org/zh-CN/docs/routing"&gt;Routing&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://umijs.org/zh-CN/docs/convention-routing"&gt;Conventional Routing (File Routing) - 约定式路由&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The folder structure, i.e. files under &lt;code&gt;src/pages&lt;/code&gt;, represents the default routing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://umijs.org/zh-CN/docs/convention-routing#%E5%8A%A8%E6%80%81%E8%B7%AF%E7%94%B1"&gt;Dynamic Routing&lt;/a&gt;: by convention, folder named &lt;code&gt;[post]&lt;/code&gt; will become a variable in the routes like so &lt;code&gt;/index/:post&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://umijs.org/zh-CN/docs/convention-routing#%E5%B5%8C%E5%A5%97%E8%B7%AF%E7%94%B1"&gt;Nested Routing&lt;/a&gt;: by convention, if &lt;code&gt;_layout.tsx&lt;/code&gt; exists in a sub-folder of &lt;code&gt;pages&lt;/code&gt; folder, &lt;code&gt;_layout.tsx&lt;/code&gt; becomes the parent component of all the other components within the same folder&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://umijs.org/zh-CN/docs/convention-routing#%E5%85%A8%E5%B1%80-layout"&gt;Overall layout&lt;/a&gt;: by convention, &lt;strong&gt;&lt;em&gt;&lt;code&gt;index.tsx&lt;/code&gt; file in &lt;code&gt;src/layouts&lt;/code&gt; folder&lt;/em&gt;&lt;/strong&gt; is the parent component of all the components in &lt;strong&gt;&lt;em&gt;&lt;code&gt;src/pages&lt;/code&gt; folder&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://umijs.org/zh-CN/docs/convention-routing#404-%E8%B7%AF%E7%94%B1"&gt;404 Routing&lt;/a&gt;: by convention, &lt;code&gt;404.tsx&lt;/code&gt; in &lt;code&gt;pages&lt;/code&gt; folder is the component renders 404 page&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://umijs.org/zh-CN/docs/convention-routing#%E6%89%A9%E5%B1%95%E8%B7%AF%E7%94%B1%E5%B1%9E%E6%80%A7"&gt;Extra Routing Attribute&lt;/a&gt;: before exporting a component, add this line &lt;code&gt;HomePage.title = 'Home Page'&lt;/code&gt;, now you can access an extra routing attribute &lt;code&gt;title&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configured Routing - 配置式路由
&lt;/h3&gt;

&lt;p&gt;If you are not satisfied with this routing method, configure your &lt;code&gt;config/config.js&lt;/code&gt;/&lt;code&gt;.umirc.ts&lt;/code&gt; file to appoint the routes yourself (i.e. &lt;em&gt;configured routing (配置式路由)&lt;/em&gt; as opposed to the default &lt;em&gt;conventional routing (约定式路由)&lt;/em&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;exact&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@pages/FirstPage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// relative path from `src` folder&lt;/span&gt;
      &lt;span class="na"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;List&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/listing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// redirecting to other routes&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NOTES&lt;/strong&gt;: &lt;code&gt;@&lt;/code&gt; represents &lt;code&gt;./src&lt;/code&gt; -- referring to the relative path; it is the same as &lt;code&gt;..&lt;/code&gt; as in &lt;code&gt;../Firstpage&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  history: to navigate
&lt;/h3&gt;

&lt;p&gt;In Umi, there are two ways to direct user from one page to another: &lt;code&gt;&amp;lt;Link to="/link_url"&amp;gt;Somewhere&amp;lt;/Link&amp;gt;&lt;/code&gt; component and &lt;code&gt;history.push('/link_url')&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;history&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;umi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// simply redirecting&lt;/span&gt;
&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// redirecting with variables&lt;/span&gt;
&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/list?a=b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// go back&lt;/span&gt;
&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;goBack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Build
&lt;/h2&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;cnpm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run this code to build the &lt;code&gt;dist&lt;/code&gt; folder. Do not forget to install &lt;code&gt;serve&lt;/code&gt; globally.&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;cnpm &lt;span class="nb"&gt;install &lt;/span&gt;serve &lt;span class="nt"&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can serve the dist folder directly on port 5000:&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;serve ./dist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  plugins
&lt;/h2&gt;

&lt;p&gt;To check the list of plugins in an umi project:&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;umi plugin list

&lt;span class="c"&gt;# showing the keys&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;umi plugin list &lt;span class="nt"&gt;--key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you know the &lt;code&gt;key&lt;/code&gt; of a &lt;code&gt;plugin&lt;/code&gt;, you can config the plugin in your config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// OR&lt;/span&gt;
  &lt;span class="na"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a href="https://umijs.org/zh-CN/docs/mock"&gt;Mock data&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Mock data lives in &lt;code&gt;/mock&lt;/code&gt; folder. A tipical mockup &lt;code&gt;api.ts&lt;/code&gt; file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 支持值为 Object 和 Array&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET /api/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// GET 可忽略&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/users/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// 支持自定义函数，API 参考 express@4&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST /api/users/create&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 添加跨域请求头&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ok&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if you visit &lt;code&gt;/api/users&lt;/code&gt;, &lt;code&gt;{ users: [1, 2] }&lt;/code&gt; will be returned. &lt;code&gt;GET&lt;/code&gt; key word can be omitted.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="http://mockjs.com/"&gt;Mock.js&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;You can use mock.js to auto-generate some mockup data, visit the website for more info.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://umijs.org/zh-CN/docs/env-variables"&gt;Environment Variables&lt;/a&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://umijs.org/zh-CN/docs/load-on-demand"&gt;DynamicImport&lt;/a&gt;
&lt;/h2&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Install `Fira Code Font` in VSCode</title>
      <dc:creator>Peiwen Li</dc:creator>
      <pubDate>Sun, 15 May 2022 02:23:15 +0000</pubDate>
      <link>https://dev.to/ld8/install-fira-code-font-in-vscode-17p4</link>
      <guid>https://dev.to/ld8/install-fira-code-font-in-vscode-17p4</guid>
      <description>&lt;p&gt;"Fira Code" is a font which helps the readability of your code. This is how you install it on VSCode.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Firstly, install the font:
You can run the following command on mac or visit &lt;a href="https://github.com/tonsky/FiraCode/wiki/Installing"&gt;this post on github&lt;/a&gt; for other OS.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew tap homebrew/cask-fonts
brew cask &lt;span class="nb"&gt;install &lt;/span&gt;font-fira-code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Edit the&lt;code&gt;settings.json&lt;/code&gt; file in VSCode
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//settings.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="err"&gt;//...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.fontFamily"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"'Fira Code', Menlo, Monaco, 'Courier New', monospace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.fontLigatures"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;ul&gt;
&lt;li&gt;Other ways and more options &lt;a href="https://github.com/tonsky/FiraCode/wiki/VS-Code-Instructions"&gt;visit this post here&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>beginners</category>
      <category>vscode</category>
    </item>
  </channel>
</rss>
