<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Website and Phone App Strategy for Tech Companies | Harry Moreno</title>
    <description>Website and Phone App Strategy for Tech Companies | Harry Moreno
</description>
    <link>https://morenoh149.github.io/</link>
    <atom:link href="https://morenoh149.github.io/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Wed, 04 Mar 2026 03:21:56 +0000</pubDate>
    <lastBuildDate>Wed, 04 Mar 2026 03:21:56 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Google Cloud SQL Provision Cheapest Postgres Database</title>
        <description>&lt;p&gt;&lt;img src=&quot;/img/2024-11-15-pricing-calculator.png&quot; alt=&quot;Google pricing calculator&quot; /&gt;
Here is the command for provisioning the cheapest database on Google Cloud SQL. There were a couple of pitfalls as I’ll explain.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;gcloud sql instances create myinstance &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--project&lt;/span&gt; my-project &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--database-version&lt;/span&gt; POSTGRES_16 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--tier&lt;/span&gt; db-f1-micro &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--region&lt;/span&gt; your-region &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--edition&lt;/span&gt; ENTERPRISE&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

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

&lt;p&gt;By default you may be instructed in the code labs to run&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;gcloud sql instances create myinstance &lt;span class=&quot;nt&quot;&gt;--project&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PROJECT_ID&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--database-version&lt;/span&gt; POSTGRES_14 &lt;span class=&quot;nt&quot;&gt;--tier&lt;/span&gt; db-f1-micro &lt;span class=&quot;nt&quot;&gt;--region&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$REGION&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can change the postgres engine version to something modern like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;POSTGRES_16&lt;/code&gt;. The versions are listed &lt;a href=&quot;https://cloud.google.com/sql/docs/postgres/db-versions&quot;&gt;here&lt;/a&gt;. As of this writing postgresql 16.3 is the default version.&lt;/p&gt;

&lt;p&gt;When you run&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;gcloud sql instances create myinstance &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--project&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PROJECT_ID&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--database-version&lt;/span&gt; POSTGRES_16 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--tier&lt;/span&gt; db-f1-micro &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--region&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$REGION&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;you get the error&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;ERROR: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gcloud.sql.instances.create&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; HTTPError 400: Invalid request:
Invalid Tier &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;db-f1-micro&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;ENTERPRISE_PLUS&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; Edition.
Use a predefined Tier like db-perf-optimized-N-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; instead.
Learn more at https://cloud.google.com/sql/docs/postgres/create-instance#machine-types.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can bypass this by specifying a lower tier for edition&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;gcloud sql instances create myinstance &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--project&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PROJECT_ID&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--database-version&lt;/span&gt; POSTGRES_16 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--tier&lt;/span&gt; db-f1-micro &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--region&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$REGION&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--edition&lt;/span&gt; ENTERPRISE&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In the pricing calculator you can get the cost of the database down to &lt;a href=&quot;https://cloud.google.com/products/calculator/?hl=en&amp;amp;dl=CjhDaVEzTm1GaE56WmxNaTFoTURVeUxUUXhZekV0WVdWaVpTMDFZek00TWpCbE5UQTJORElRQVE9PRAHGiRFNDlBQzE5NC04REM1LTRBQ0YtQkY5QS04RTBGQzAwRTZEQUQ&quot;&gt;$10.60 per month&lt;/a&gt;. I did this by choosing a shared vcpu database&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2024-11-15-dropdown-engine.png&quot; alt=&quot;postgres engine&quot; /&gt;&lt;/p&gt;

&lt;p&gt;and lowering the disk size to 16gb.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2024-11-15-pricing-list.png&quot; alt=&quot;pricing list&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Delete your database to avoid being billed&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;gcloud sql instances delete myinstance &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</description>
        <pubDate>Fri, 15 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://morenoh149.github.io/2024/11/15/Google-Cloud-SQL-provision-cheapest-postgres.html</link>
        <guid isPermaLink="true">https://morenoh149.github.io/2024/11/15/Google-Cloud-SQL-provision-cheapest-postgres.html</guid>
        
        
      </item>
    
      <item>
        <title>Sliding Window in python trapezoid</title>
        <description>&lt;p&gt;I often find myself having to reimplement the sliding window algorithm. Here is
a basic template for sliding windows. It is a good starting point for adding
other features like counting characters or tracking the largest size of the window.&lt;/p&gt;

&lt;p&gt;This template takes a basic two-pointer approach. But it reads better from top to
bottom and generalizes more than other solutions I have seen. First we increase the window size by shifting the right pointer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt;.
If the window reaches the max size we slide it by incrementing pointer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; and
the left pointer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;l&lt;/code&gt;. If we reach the right side we shrink the window by increasing
the left pointer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;l&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ABCDEFG&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;window_length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;window_length&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;window_length&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;win&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;output&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;A
AB
ABC
BCD
CDE
DEF
EFG
FG
G&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can rewrite this as a generator if you prefer&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# sliding_window.py
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sliding_window_generator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;window_length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;window_length&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;window_length&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;win&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;interaction&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; sliding_window.py
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; g &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; sliding_window_generator&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;ABCDEFG&apos;&lt;/span&gt;, 3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; next&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;g&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&apos;A&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; print&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;next&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;g&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
AB
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; next&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;g&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&apos;ABC&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; next&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;g&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&apos;BCD&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; next&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;g&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&apos;CDE&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; next&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;g&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&apos;DEF&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; next&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;g&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&apos;EFG&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; next&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;g&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&apos;FG&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; next&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;g&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&apos;G&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</description>
        <pubDate>Sun, 29 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://morenoh149.github.io/2023/10/29/Sliding-window-python-basic-template.html</link>
        <guid isPermaLink="true">https://morenoh149.github.io/2023/10/29/Sliding-window-python-basic-template.html</guid>
        
        
      </item>
    
      <item>
        <title>Django log slow queries</title>
        <description>&lt;p&gt;&lt;img src=&quot;/img/2023-09-12-stopwatch.png&quot; alt=&quot;Stopwatch running a marathon&quot; /&gt;
It is important to keep track of the performance of your application. One
popular way to do this is to log slow queries. Below is how to do this in Django
python. Your logging config will vary depending on how your django app is setup.
On simpler django sites it might be in &lt;a href=&quot;https://docs.djangoproject.com/en/4.2/topics/logging/#examples&quot;&gt;settings.py&lt;/a&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;LOGGING&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&apos;version&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&apos;disable_existing_loggers&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&apos;filters&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&apos;slow_queries&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&apos;()&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;django.utils.log.CallbackFilter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# output slow queries only, unit are 1s, so 0.3 is 300ms
&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;# ref 300ms * 0.001 = 0.3, 50ms * 0.001 = 0.05
&lt;/span&gt;            &lt;span class=&quot;s&quot;&gt;&apos;callback&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.05&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&apos;handlers&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&apos;console&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&apos;class&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;logging.StreamHandler&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&apos;loggers&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&apos;django&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&apos;handlers&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;console&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&apos;level&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;DEBUG&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&apos;propagate&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&apos;django.db.backends&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&apos;handlers&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;console&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&apos;level&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;DEBUG&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&apos;propagate&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&apos;filters&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;slow_queries&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This config has two &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loggers&lt;/code&gt;. One named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;django&lt;/code&gt; and one named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;django.db.backends&lt;/code&gt;.
Loggers are the entry point for the logging system in django. We apply our slow
query logic only to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;django.db.backends&lt;/code&gt; handler. After a logger has
dealt with a log it applies any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filters&lt;/code&gt; onto it.&lt;/p&gt;

&lt;p&gt;Filters provide extra control over logs. We define one filter in the example above.
This filter will allow only slow queries to go through, thus we would log slow
queries so that the developer can read them later. The filter applies a python
lambda inline that will only let logs with a duration &amp;gt; 50 milliseconds pass through.&lt;/p&gt;

&lt;p&gt;This config has one handler &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console&lt;/code&gt;. A handler is a destination for where
the django logs should go. This could be a file writer, stdout, another handler,
etc.&lt;/p&gt;
</description>
        <pubDate>Tue, 12 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://morenoh149.github.io/2023/09/12/Django-log-slow-queries.html</link>
        <guid isPermaLink="true">https://morenoh149.github.io/2023/09/12/Django-log-slow-queries.html</guid>
        
        
      </item>
    
      <item>
        <title>My review of Pandas 30 day challenge</title>
        <description>&lt;p&gt;&lt;img src=&quot;/img/2023-08-30-python-pandas.png&quot; alt=&quot;Python Pandas&quot; /&gt;
Recently I completed the Leetcode 30 day Pandas Challenge. Pandas is a popular python
library for data analysis and Leetcode has made a set of problems to learn it.
Here I share my thoughts on the problems and whether you should try it too.&lt;/p&gt;

&lt;p&gt;Some background. Before this challenge I felt I had a good understanding of
Pandas. I understood what dataframes and Series are. How pandas builds upon
numpy datatypes. I also used pandas professionally in the past to build ETL
pipelines.&lt;/p&gt;

&lt;p&gt;After the challenge I felt like I had a deeper understanding of pandas. I
am much more comfortable renaming columns in a dataframe, changing dataframe
datatypes, merging frames sql-style and more comfortable solving tasks I may
run into daily.&lt;/p&gt;

&lt;h2 id=&quot;based-on-the-sql-problems&quot;&gt;Based on the SQL problems&lt;/h2&gt;

&lt;p&gt;The set consists of 30 problems to solve. Behind the scenes the problems are
the same as other SQL problems on the website, except you have to solve them with python and pandas. This leads to many sql comments on the problems which
can be annoying for someone trying to learn only pandas.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2023-08-30-leetcode-comments.png&quot; alt=&quot;Leetcode sql comments on a pandas problem&quot; /&gt;(SQL comments mixed with Pandas comments)&lt;/p&gt;

&lt;p&gt;Also because the problem
statements are for sql you end up getting very comfortable with the pandas
apis. For example in many problems you have to construct the final dataframe
with specific column names&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;food_delivery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delivery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delivery&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;immediate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;order_date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;customer_pref_delivery_date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;immediate_percentage&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;immediate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If we were a python data analyst we wouldn’t be naming columns like this very often.&lt;/p&gt;

&lt;h2 id=&quot;example&quot;&gt;Example&lt;/h2&gt;

&lt;p&gt;One problem is called “Customers who never order” in the Data Filtering section. You first get a schema describing the data&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2023-08-30-problem-schema.png&quot; alt=&quot;Pandas problem schema&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Then you get a task, here it asks to find all customers who never order anything&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2023-08-30-problem-statement.png&quot; alt=&quot;Pandas problem statement&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Then you get some example results when they run your solution on different data&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2023-08-30-problem-expectations.png&quot; alt=&quot;Pandas problem expectations&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Then you are to write your solution in the editor&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2023-08-30-problem-editor.png&quot; alt=&quot;Pandas problem editor&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The editor is in pandas mode. It is the same throughout the website for
java questions, javascript question, ruby, etc. You write your solution and can
try it on the tests by clicking Run. When you are happy with the solution you
can submit and Leetcode will run your solution on a larger test suite serverside.&lt;/p&gt;

&lt;h3 id=&quot;my-solution&quot;&gt;My Solution&lt;/h3&gt;
&lt;p&gt;My solution to this problem is&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find_customers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;customers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;orders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;customers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;orders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left_on&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;id&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right_on&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;customerId&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;how&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;left&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;no_order_ids&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isnull&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;id_x&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;names&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;customers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;id in &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;no_order_ids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;Customers&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;First I merge the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;customer&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;orders&lt;/code&gt; table on the ids&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;customers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;orders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left_on&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;id&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right_on&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;customerId&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;how&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;left&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then I get all ids for the customers that made no orders with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.isnull()&lt;/code&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;no_order_ids&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isnull&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;id_x&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.query()&lt;/code&gt; to get all the customers in the original dataframe that
we know have no orders (are in the no_order_ids series)&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;names&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;customers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;id in &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;no_order_ids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Finally we narrow down the original &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;names&lt;/code&gt; dataframe to get the customer’s name
and rename the column to fit the problem requirements.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;Customers&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;By the way, there is more than one way to solve each problem. You are allowed
to use the full expressivity of python and the pandas apis.&lt;/p&gt;

&lt;h2 id=&quot;topics&quot;&gt;Topics&lt;/h2&gt;

&lt;p&gt;The 30 pandas questions are split into 6 section.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Data Filtering&lt;/li&gt;
  &lt;li&gt;String Methods&lt;/li&gt;
  &lt;li&gt;Data Manipulation&lt;/li&gt;
  &lt;li&gt;Statistics&lt;/li&gt;
  &lt;li&gt;Data Aggregation&lt;/li&gt;
  &lt;li&gt;Data Integration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the following sections we list the pandas apis we used to solve the problems.&lt;/p&gt;

&lt;h3 id=&quot;data-filtering&quot;&gt;Data Filtering&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://pandas.pydata.org/docs/user_guide/10min.html#boolean-indexing&quot;&gt;Boolean Indexing&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://pandas.pydata.org/docs/user_guide/indexing.html?highlight=query#the-query-method&quot;&gt;.query() method&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;string-methods&quot;&gt;String Methods&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Series.str Family of methods &lt;a href=&quot;https://github.com/pandas-dev/pandas/blob/v2.0.3/pandas/core/strings/accessor.py#L2962&quot;&gt;https://github.com/pandas-dev/pandas/blob/v2.0.3/pandas/core/strings/accessor.py#L2962&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Adding columns with &lt;a href=&quot;https://devdocs.io/numpy~1.23/reference/generated/numpy.where&quot;&gt;numpy.where&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Regex with Series.str.contains() and Series.str.match()&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;data-manipulation&quot;&gt;Data Manipulation&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;DataFrames’s &lt;a href=&quot;https://pandas.pydata.org/docs/user_guide/basics.html#head-and-tail&quot;&gt;head() and tail()&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Numbering rows with &lt;a href=&quot;https://devdocs.io/pandas~1/reference/api/pandas.dataframe.rank&quot;&gt;rank() https://devdocs.io/pandas~1/reference/api/pandas.dataframe.rank&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Reshaping and pivot tables with &lt;a href=&quot;https://pandas.pydata.org/docs/user_guide/reshaping.html?highlight=melt#reshaping-by-melt&quot;&gt;melt()&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;deduplicating with &lt;a href=&quot;https://pandas.pydata.org/docs/user_guide/indexing.html?highlight=drop_duplicates#duplicate-data&quot;&gt;drop_duplicates()&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;statistics&quot;&gt;Statistics&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;constructing dataframes with &lt;a href=&quot;&quot;&gt;pd.Dataframe()&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Quantizing with &lt;a href=&quot;https://pandas.pydata.org/docs/user_guide/basics.html?highlight=cut#discretization-and-quantiling&quot;&gt;pd.cut()&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;data-aggregation&quot;&gt;Data Aggregation&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Aggregations with &lt;a href=&quot;&quot;&gt;groupby()&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://pandas.pydata.org/docs/user_guide/groupby.html?highlight=namedagg#named-aggregation&quot;&gt;Named Aggregations&lt;/a&gt; with lambdas&lt;/li&gt;
  &lt;li&gt;Adding new columns with &lt;a href=&quot;https://pandas.pydata.org/docs/user_guide/dsintro.html?highlight=assign#assigning-new-columns-in-method-chains&quot;&gt;assign()&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;data-integration&quot;&gt;Data Integration&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Promoting a group’s index to a column with &lt;a href=&quot;https://pandas.pydata.org/docs/getting_started/intro_tutorials/07_reshape_table_layout.html?highlight=reset_index#wide-to-long-format&quot;&gt;reset_index()&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;sql-style-join with &lt;a href=&quot;https://pandas.pydata.org/docs/user_guide/merging.html#database-style-dataframe-or-named-series-joining-merging&quot;&gt;merge()&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;testing membership with &lt;a href=&quot;https://pandas.pydata.org/docs/user_guide/indexing.html?highlight=isin#indexing-with-isin&quot;&gt;Series.isin()&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://pandas.pydata.org/docs/user_guide/indexing.html?highlight=isin#boolean-operators&quot;&gt;Negating .isin() with the unary not ~&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Overall I would recommend doing this challenge. The questions seem realistic to
the tasks a data analyst may encounter in everyday work. The questions force
you to use a large amount of the pandas api. The problems are rated as “beginner”
pandas difficulty. You could complement this challenge with some Kaggle
competitions so you could apply your pandas knowledge.&lt;/p&gt;
</description>
        <pubDate>Wed, 30 Aug 2023 00:00:00 +0000</pubDate>
        <link>https://morenoh149.github.io/2023/08/30/My-review-of-pandas-30-day-challenge.html</link>
        <guid isPermaLink="true">https://morenoh149.github.io/2023/08/30/My-review-of-pandas-30-day-challenge.html</guid>
        
        
      </item>
    
      <item>
        <title>How to prepare for the Flask Backend Engineer Interview</title>
        <description>&lt;p&gt;&lt;img src=&quot;/img/2023-03-13-flask.jpg&quot; alt=&quot;Flask&quot; /&gt;
Python development is great for modern web development. There are several python based web frameworks
that can help speed up building your web app.
In this post we’ll go over one popular framework, Flask, and some of the topics you
might get asked in an interview setting.&lt;/p&gt;

&lt;h2 id=&quot;how-to-prepare&quot;&gt;How to prepare&lt;/h2&gt;

&lt;p&gt;Review &lt;a href=&quot;https://devdocs.io/flask~2.2/&quot;&gt;Flask documentation&lt;/a&gt;: It’s important to have a good understanding of the Flask framework and its features. Flask documentation is a great resource to learn about its capabilities, features and how to use them.&lt;/p&gt;

&lt;p&gt;Understand Flask Architecture: Flask follows the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/MVC&quot;&gt;Model-View-Controller&lt;/a&gt; (MVC) architecture. Make sure you understand the basics of the architecture and how it’s implemented in Flask.&lt;/p&gt;

&lt;p&gt;Practice Flask basics: Start practicing Flask basics such as creating &lt;a href=&quot;https://devdocs.io/flask~2.2/api/index#flask.Flask.route&quot;&gt;routes&lt;/a&gt;, templates, views, and handling requests. Review the differences between Flask and Django and how they handle these concepts. All of these topics are covered in the &lt;a href=&quot;https://flask.palletsprojects.com/en/2.2.x/quickstart/&quot;&gt;quickstart&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Review &lt;a href=&quot;https://python.plainenglish.io/some-useful-python-flask-plugins-3ac57faaca7e&quot;&gt;Flask extensions&lt;/a&gt;: Flask has many extensions that can help you build your application more easily. Some examples of popular extensions include Flask-WTF, Flask-Login, Flask-Mail, Flask-SQLAlchemy, and Flask-RESTful. Review the extensions that you might be using and how to use them.&lt;/p&gt;

&lt;p&gt;Prepare for database and ORM questions: Flask supports multiple ORMs, such as SQLAlchemy, Peewee, and &lt;a href=&quot;https://docs.ponyorm.org/&quot;&gt;PonyORM&lt;/a&gt;. Prepare yourself with basic ORM concepts and review how to use Flask’s most popular orm &lt;a href=&quot;https://docs.sqlalchemy.org/en/20/orm/quickstart.html&quot;&gt;SQLAlchemy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Understand Flask’s security features: Flask has built-in security features, such as password hashing, CSRF protection, and &lt;a href=&quot;https://devdocs.io/flask~2.2/api/index#flask.session&quot;&gt;session management&lt;/a&gt;. It’s important to understand how these features work and how to use them.&lt;/p&gt;

&lt;p&gt;Build sample projects: Build some sample projects using Flask to demonstrate your understanding of the framework. You can start with a simple CRUD application and gradually move on to more complex projects like an ETL pipeline. This will help you gain more experience and confidence in working with Flask.&lt;/p&gt;

&lt;h2 id=&quot;common-questions&quot;&gt;Common questions&lt;/h2&gt;

&lt;p&gt;What is Flask? How is it different from other web frameworks?&lt;/p&gt;

&lt;p&gt;What is the difference between Flask and Django?&lt;/p&gt;

&lt;p&gt;Explain the Model-View-Controller (MVC) architecture in Flask.&lt;/p&gt;

&lt;p&gt;What are &lt;a href=&quot;https://devdocs.io/flask~2.2/blueprints/index&quot;&gt;Flask blueprints&lt;/a&gt;? How do they help in structuring a large application?&lt;/p&gt;

&lt;p&gt;How do you create a route in Flask? Explain the different types of routes in Flask.&lt;/p&gt;

&lt;p&gt;What is Flask’s template engine? How do you use it? &lt;a href=&quot;https://devdocs.io/flask~2.2/templating/index&quot;&gt;Jinja&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How does Flask handle sessions? What are some &lt;a href=&quot;https://flask.palletsprojects.com/en/2.2.x/security/?highlight=session#set-cookie-options&quot;&gt;security measures&lt;/a&gt; Flask provides?&lt;/p&gt;

&lt;p&gt;What is an ORM? What are some popular ORMs used in Flask?&lt;/p&gt;

&lt;p&gt;What is &lt;a href=&quot;https://flask-wtf.readthedocs.io/en/1.0.x/&quot;&gt;Flask-WTF&lt;/a&gt;? How do you use it for form validation?&lt;/p&gt;

&lt;p&gt;What are Flask extensions? Give some &lt;a href=&quot;https://python.plainenglish.io/some-useful-python-flask-plugins-3ac57faaca7e&quot;&gt;examples&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What is Flask-SQLAlchemy? How do you use it?&lt;/p&gt;

&lt;p&gt;How do you handle &lt;a href=&quot;https://flask-login.readthedocs.io/en/latest/&quot;&gt;authentication&lt;/a&gt; and authorization in Flask?&lt;/p&gt;

&lt;p&gt;How do you &lt;a href=&quot;https://docs.docker.com/samples/flask/&quot;&gt;deploy&lt;/a&gt; a Flask application? What are some popular hosting platforms for Flask?&lt;/p&gt;

&lt;p&gt;What are some &lt;a href=&quot;https://github.com/mjhea0/flaskr-tdd&quot;&gt;best practices&lt;/a&gt; for Flask development?&lt;/p&gt;

&lt;h2 id=&quot;differences-between-flask-and-django&quot;&gt;Differences between Flask and Django&lt;/h2&gt;

&lt;p&gt;Complexity: Django is a full-stack web framework, which means it comes with built-in features and modules for various functionalities such as ORM, Admin Interface, Routing, Forms, Authentication, and Security. Flask, on the other hand, is a micro-framework, which means it has less built-in functionality and allows developers to add only the necessary modules and packages as per the project requirements.&lt;/p&gt;

&lt;p&gt;Scalability: Django is well-suited for large-scale applications, and its built-in modules and features can help developers build complex applications quickly. Flask, on the other hand, is lightweight and highly customizable, making it more suitable for small to medium-sized applications that require flexibility.&lt;/p&gt;

&lt;p&gt;Database: Django has its Object-Relational Mapping (ORM) layer, which allows developers to interact with databases using Python syntax without writing SQL queries explicitly. Flask supports various ORMs like SQLAlchemy, Peewee, PonyORM, and more.&lt;/p&gt;

&lt;p&gt;Routing: Django has a built-in routing system that makes it easy to define URL patterns and route requests to specific views. Flask also has a routing system but allows developers to create their routing logic using decorators.&lt;/p&gt;

&lt;p&gt;Template Engine: Django has its &lt;a href=&quot;https://docs.djangoproject.com/en/4.1/ref/templates/language/&quot;&gt;built-in template engine&lt;/a&gt;, whereas Flask allows developers to choose their preferred template engine like Jinja2, Mako, and others.&lt;/p&gt;

&lt;p&gt;Community: Django has a large and active community, and there are many third-party libraries and plugins available to use. Flask has a smaller community compared to Django, but it’s growing steadily, and there are many useful extensions available.&lt;/p&gt;

&lt;p&gt;In summary, Flask is a micro-framework that provides more flexibility, while Django is a full-stack framework that provides more built-in features and is more suitable for large-scale applications. You may choose Django as the main api for a platform or a Saas. Flask is a better choice to power a specific service within a microservices architecture. The choice of framework depends on the project requirements, team expertise, and development goals.&lt;/p&gt;
</description>
        <pubDate>Mon, 13 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://morenoh149.github.io/2023/03/13/How-to-Prepare-for-the-Flask-Backend-interview.html</link>
        <guid isPermaLink="true">https://morenoh149.github.io/2023/03/13/How-to-Prepare-for-the-Flask-Backend-interview.html</guid>
        
        
      </item>
    
      <item>
        <title>Monitoring Django with Tracing and OpenTelemetry</title>
        <description>&lt;p&gt;&lt;img src=&quot;/img/2022-09-22-uptrace.png&quot; alt=&quot;Uptrace tracing tool&quot; /&gt;
&lt;a href=&quot;https://opentelemetry.uptrace.dev/guide/distributed-tracing.html&quot;&gt;Distributed tracing&lt;/a&gt; allows to observe requests as they propagate through distributed systems, especially those built using a microservices architecture. In a distributed environment, tracing also helps you understand relationships and interactions between microservices. Distributed tracing gives an insight into how a particular microservice is performing and how that service affects other microservices.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2022-09-22-tracing-graph.png&quot; alt=&quot;Tracing&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Using tracing, you can break down requests into &lt;a href=&quot;https://opentelemetry.uptrace.dev/guide/distributed-tracing.html#spans&quot;&gt;spans&lt;/a&gt;. &lt;strong&gt;Span&lt;/strong&gt; is an operation (unit of work) your app performs handling a request, for example, a database query or a network call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trace&lt;/strong&gt; is a tree of spans that shows the path that a request makes through an app. Root span is the first span in a trace.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2022-09-22-trace-graph.png&quot; alt=&quot;Trace&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To learn more about tracing, see &lt;a href=&quot;https://opentelemetry.uptrace.dev/guide/distributed-tracing.html&quot;&gt;Distributed tracing using OpenTelemetry&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-is-opentelemetry&quot;&gt;What is OpenTelemetry?&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://opentelemetry.uptrace.dev/&quot;&gt;OpenTelemetry&lt;/a&gt; is a vendor-neutral standard that allows you to collect and export &lt;a href=&quot;https://opentelemetry.uptrace.dev/guide/distributed-tracing.html&quot;&gt;traces&lt;/a&gt;, &lt;a href=&quot;https://opentelemetry.uptrace.dev/guide/logs.html&quot;&gt;logs&lt;/a&gt;, and &lt;a href=&quot;https://opentelemetry.uptrace.dev/guide/metrics.html&quot;&gt;metrics&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;OpenTelemetry is available for most programming languages and allows to send performance data to any &lt;a href=&quot;https://get.uptrace.dev/compare/distributed-tracing-tools.html&quot;&gt;tracing tool&lt;/a&gt; of your choice.&lt;/p&gt;

&lt;p&gt;OpenTelemetry is a community-driven open source project that offers several components:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;OpenTelemetry API&lt;/strong&gt; is a programming interface that you can use to &lt;a href=&quot;https://opentelemetry.uptrace.dev/guide/distributed-tracing.html#what-to-instrument&quot;&gt;instrument code&lt;/a&gt; and collect telemetry data.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;OpenTelemetry SDK&lt;/strong&gt; is the official implementation of OpenTelemetry API that processes and exports collected telemetry to backends.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://opentelemetry.uptrace.dev/guide/collector.html&quot;&gt;OpenTelemetry Collector&lt;/a&gt; is a proxy between your application and a backend. It receives telemetry data, transforms it, and then exports data to backends that can store it permanently. Collector can also act as an agent that pulls telemetry data from monitored systems, for example, &lt;a href=&quot;https://opentelemetry.uptrace.dev/collector/?receiver=redis&quot;&gt;Redis&lt;/a&gt; or filesystem metrics.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;OTLP&lt;/strong&gt; is the OpenTelemetry protocol used by SDK and Collector to export data to backends or other collectors. As a transport, OTLP can use gRPC (OTLP/gRPC) or HTTP (OTLP/HTTP).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;how-to-use-opentelemetry&quot;&gt;How to use OpenTelemetry?&lt;/h2&gt;

&lt;p&gt;OpenTelemetry is available for most programming languages and provides interoperability across different languages and environments.&lt;/p&gt;

&lt;p&gt;You can &lt;a href=&quot;https://opentelemetry.uptrace.dev/&quot;&gt;get started with OpenTelemetry&lt;/a&gt; by following these 5 steps:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;. Install a &lt;a href=&quot;https://get.uptrace.dev/compare/distributed-tracing-tools.html&quot;&gt;distributed tracing tool&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;. Browse &lt;a href=&quot;https://opentelemetry.uptrace.dev/instrumentations/&quot;&gt;OpenTelemetry instrumentations&lt;/a&gt; to find examples for your framework and libraries.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt;. &lt;a href=&quot;https://docs.uptrace.dev/#getting-started&quot;&gt;Configure&lt;/a&gt; OpenTelemetry SDK to export telemetry data to the tracing tool.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Step 4&lt;/strong&gt;. Learn about &lt;a href=&quot;https://opentelemetry.uptrace.dev/guide/distributed-tracing.html#what-s-next&quot;&gt;OpenTelemetry Tracing API&lt;/a&gt; for your programming language to create custom instrumentations.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Step 5&lt;/strong&gt;. Install &lt;a href=&quot;https://opentelemetry.uptrace.dev/guide/collector.html&quot;&gt;OpenTelemetry Collector&lt;/a&gt; to gather &lt;a href=&quot;https://opentelemetry.uptrace.dev/guide/collector.html#host-metrics&quot;&gt;infrastructure metrics&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;opentelemetry-python-api&quot;&gt;OpenTelemetry Python API&lt;/h2&gt;

&lt;p&gt;You can create spans using &lt;a href=&quot;https://opentelemetry.uptrace.dev/guide/python-tracing.html&quot;&gt;OpenTelemetry Python API&lt;/a&gt; like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;opentelemetry&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trace&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;tracer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_tracer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;app_or_package_name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1.0.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;insert_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tracer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_as_current_span&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;insert-user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;span&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can also record &lt;a href=&quot;https://opentelemetry.uptrace.dev/guide/distributed-tracing.html#attributes&quot;&gt;attributes&lt;/a&gt; and errors:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;insert_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tracer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_as_current_span&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;insert-user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;span&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;span&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_recording&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;span&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;enduser.id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;span&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;enduser.email&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;email&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;OpenTelemetry also has plans to add support for &lt;a href=&quot;https://opentelemetry.uptrace.dev/guide/python-metrics.html&quot;&gt;Python Metrics&lt;/a&gt; and &lt;a href=&quot;https://opentelemetry.uptrace.dev/guide/python-logs.html&quot;&gt;Python Logs&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;django-opentelemetry-instrumentation&quot;&gt;Django OpenTelemetry instrumentation&lt;/h2&gt;

&lt;p&gt;To instrument Django, you need a correspoding &lt;a href=&quot;https://opentelemetry.uptrace.dev/instrumentations/python-django.html&quot;&gt;OpenTelemetry Django instrumentation&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;opentelemetry-instrumentation-django&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Django instrumentation uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DJANGO_SETTINGS_MODULE&lt;/code&gt; env variable to find settings file. Django defines that variable in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;manage.py&lt;/code&gt; file so you should instrument Django app from that file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# manage.py
&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;opentelemetry.instrumentation.django&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DjangoInstrumentor&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# DjangoInstrumentor uses DJANGO_SETTINGS_MODULE to instrument the project.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Make sure the var is available before you call the DjangoInstrumentor.
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setdefault&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;DJANGO_SETTINGS_MODULE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;mysite.settings&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;DjangoInstrumentor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instrument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;For more details, see &lt;a href=&quot;https://get.uptrace.dev/opentelemetry/django.html&quot;&gt;OpenTelemetry Django guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-is-uptrace&quot;&gt;What is Uptrace?&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://uptrace.dev/&quot;&gt;Uptrace&lt;/a&gt; is an open source &lt;a href=&quot;https://get.uptrace.dev/compare/datadog-competitors.html&quot;&gt;DataDog competitor&lt;/a&gt; powered by OpenTelemetry and ClickHouse. It helps developers pinpoint failures and find performance bottlenecks.&lt;/p&gt;

&lt;p&gt;Uptrace uses OpenTelemetry to collect observability data and ClickHouse database to store that data. By using an optimized &lt;a href=&quot;https://clickhouse.uptrace.dev/&quot;&gt;ClickHouse Go&lt;/a&gt; scheme, Uptrace allows to significantly reduce storage requirements, improve query performance, and lower monthly SaaS bills.&lt;/p&gt;

&lt;p&gt;Uptrace itself is a single Go binary that can process billions of spans and that can be easily &lt;a href=&quot;https://get.uptrace.dev/guide/opentelemetry-tracing-tool.html&quot;&gt;installed&lt;/a&gt; with a single command using DEB/RPM packages. Uptrace binary and ClickHouse database is all you need to get started.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2022-09-22-uptrace.png&quot; alt=&quot;Uptrace tracing tool&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s next?&lt;/h2&gt;

&lt;p&gt;Next, you can continue exploring &lt;a href=&quot;https://opentelemetry.uptrace.dev/&quot;&gt;OpenTelemetry&lt;/a&gt; or start instrumenting your app using popular instrumentations:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://get.uptrace.dev/opentelemetry/gin-gorm.html&quot;&gt;OpenTelemetry guide for Gin and GORM&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://opentelemetry.uptrace.dev/instrumentations/go-grpc.html&quot;&gt;gRPC OpenTelemetry&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bun.uptrace.dev/guide/performance-monitoring.html&quot;&gt;Golang ORM OpenTelemetry&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://redis.uptrace.dev/guide/go-redis-monitoring.html&quot;&gt;Go Redis OpenTelemetry&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://opentelemetry.uptrace.dev/instrumentations/go-zap.html&quot;&gt;Zap OpenTelemetry&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 23 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://morenoh149.github.io/2022/09/23/Monitoring-Django-with-Tracing-and-OpenTelemetry.html</link>
        <guid isPermaLink="true">https://morenoh149.github.io/2022/09/23/Monitoring-Django-with-Tracing-and-OpenTelemetry.html</guid>
        
        
      </item>
    
      <item>
        <title>How to Test TLS in SWAKS</title>
        <description>&lt;p&gt;In this post we detail how to use Swaks for testing emails over tls. This
post picks up where the manual page leaves off and more explicitly goes
over how to send a test email over tls. Swaks is a popular tool in penetration
testing circles, it is written in Perl and according to it’s github history it
was first published on December 12th 2001.&lt;/p&gt;

&lt;h2 id=&quot;installing&quot;&gt;Installing&lt;/h2&gt;
&lt;p&gt;Swaks is available from most popular package managers for
&lt;a href=&quot;http://www.jetmore.org/john/code/swaks/installation.html&quot;&gt;installation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With ubuntu or debian:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;swaks&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In a Dockerfile you can append it to the list of dependencies:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;RUN apt-get update &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# for testing smtp&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; swaks &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  ...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note Swaks is not available in apk for alpine linux base images. I mention this because
alpine is a popular base image for docker containers.&lt;/p&gt;

&lt;h2 id=&quot;send-email-with-tls-12&quot;&gt;Send email with tls 1.2&lt;/h2&gt;
&lt;p&gt;This is the heart of the post. To send an email using swaks and tls 1.2 do:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;swaks &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--to&lt;/span&gt; harry@test.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--server&lt;/span&gt; smtp.server.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--from&lt;/span&gt; email@address.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--auth-user&lt;/span&gt; username &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--auth-password&lt;/span&gt; password &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 587 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-tls&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--tls-protocol&lt;/span&gt; tlsv1_2&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;in my case we had to specify port 587 and a specific from address due to the security
preferences on the smtp server. Your mileage may vary.&lt;/p&gt;

&lt;h2 id=&quot;more-use&quot;&gt;More use&lt;/h2&gt;
&lt;p&gt;For completeness here is what I first tried. Running swaks by only specifying the credentials
swaks negotiated NTLM (windows NT Lan Manager (a weak protocol)).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;swaks &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--to&lt;/span&gt; harry@test.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--server&lt;/span&gt; smtp.server.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--from&lt;/span&gt; email@address.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--auth-user&lt;/span&gt; username &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--auth-password&lt;/span&gt; password &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 587

&lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; Trying smtp.server.com:587...
&lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; Connected to smtp.server.com.
&amp;lt;- 220 foo.bar.com Microsoft ESMTP MAIL Service ready at Sat, 3 Apr 2021 19:21:16 &lt;span class=&quot;nt&quot;&gt;-0400&lt;/span&gt;
-&amp;gt; EHLO foo.bar.com
&amp;lt;- 250-foo.bar.com Hello
&amp;lt;- 250-SIZE 
&amp;lt;- 250-PIPELINING
&amp;lt;- 250-DSN
&amp;lt;- 250-ENHANCEDSTATUSCODES
&amp;lt;- 250-STARTTLS
&amp;lt;- 250-AUTH GSSAPI NTLM
&amp;lt;- 250-8BITMIME
&amp;lt;- 250-BINARYMIME
&amp;lt;- 250 CHUNKING
-&amp;gt; AUTH NTLM
&amp;lt;- 334 NTLM supported
-&amp;gt; foobar
&amp;lt;- foobar
-&amp;gt; foobar
&amp;lt;- 235  Authentication successful
-&amp;gt; MAIL FROM:&amp;lt;&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;@server.com&amp;gt;
&amp;lt;- 250 2.1.0 Sender OK
-&amp;gt; RCPT TO:&amp;lt;harry@test.com&amp;gt;
&amp;lt;- 250 2.1.5 Recipient OK
-&amp;gt; DATA
&amp;lt;- 354 Start 
-&amp;gt; Date: Sat, 03 Apr 2021 19:21:16 &lt;span class=&quot;nt&quot;&gt;-0400&lt;/span&gt;
-&amp;gt; To: harry@test.com
-&amp;gt; From: email@address.com
-&amp;gt; Subject: &lt;span class=&quot;nb&quot;&gt;test &lt;/span&gt;Sat, 03 Apr 2021 19:21:16 &lt;span class=&quot;nt&quot;&gt;-0400&lt;/span&gt;
-&amp;gt; Message-Id: &amp;lt;foobar@foo.bar.com&amp;gt;
-&amp;gt; X-Mailer: swaks v20170101.0 jetmore.org/john/code/swaks/
-&amp;gt;
-&amp;gt; This is a &lt;span class=&quot;nb&quot;&gt;test &lt;/span&gt;mailing
-&amp;gt;
-&amp;gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&amp;lt;- 250 2.6.0 &amp;lt;foobar@foo.bar.com&amp;gt; Queued mail &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;delivery
-&amp;gt; QUIT
&amp;lt;- 221 2.0.0 Service closing transmission channel
&lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; Connection closed with remote host.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;openssl&quot;&gt;OpenSSL&lt;/h2&gt;
&lt;p&gt;If for whatever reason you cannot install swaks (for example on alpine linux) you
can try the openssl command.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;openssl s_client &lt;span class=&quot;nt&quot;&gt;-no_tls1&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-no_tls1_1&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-no_tls1_2&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; your.mail.host:port&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</description>
        <pubDate>Sat, 03 Apr 2021 00:00:00 +0000</pubDate>
        <link>https://morenoh149.github.io/2021/04/03/How-to-test-tls-in-swaks.html</link>
        <guid isPermaLink="true">https://morenoh149.github.io/2021/04/03/How-to-test-tls-in-swaks.html</guid>
        
        
      </item>
    
      <item>
        <title>Cybersecurity Tips that Could Save Your Small Business</title>
        <description>&lt;p&gt;&lt;img src=&quot;/img/2020-03-11-ipad.jpeg&quot; alt=&quot;Ipad&quot; /&gt;
Cybercriminals like to go after small businesses because they tend to be vulnerable and unprotected compared to larger companies. In fact, nearly half of all
&lt;a href=&quot;https://smallbiztrends.com/2019/05/2019-small-business-cyber-attack-statistics.html&quot;&gt;cyber attacks&lt;/a&gt;
target small businesses! Did you know that most small companies that experience a cyber attack go out of business within just six months? Fortunately, there are several precautions you can take to protect your customers’ data and safeguard the future of your company.&lt;/p&gt;

&lt;h2 id=&quot;hire-professional-help&quot;&gt;Hire Professional Help&lt;/h2&gt;

&lt;p&gt;If your business does experience a cyber attack and you lose valuable data, don’t try to fix the problem yourself. Many small businesses don’t have in-house IT professionals, so business owners often attempt data recovery on their own. However, recovering lost data is an extremely technical process. If you lose valuable business data to an email scam or phishing attack, it’s best to hire an expert to remedy the situation. Consider hiring the help of a data recovery company to get your business back up and running as quickly as possible and avoid major productivity losses. For example, &lt;a href=&quot;https://www.esentire.com/&quot;&gt;eSentire&lt;/a&gt;, &lt;a href=&quot;https://ithemes.com/security/&quot;&gt;iThemes Security Pro&lt;/a&gt;, and &lt;a href=&quot;https://www.fireeye.com/&quot;&gt;FireEye&lt;/a&gt; are among the trusted names in security solutions that can help protect your small business.&lt;/p&gt;

&lt;h2 id=&quot;educate-yourself-and-your-employees&quot;&gt;Educate Yourself and Your Employees&lt;/h2&gt;

&lt;p&gt;According to CNBC,
&lt;a href=&quot;https://www.cnbc.com/2018/06/21/the-biggest-cybersecurity-risk-to-us-businesses-is-employee-negligence-study-says.html&quot;&gt;employee negligence&lt;/a&gt;
is the greatest cybersecurity risk to American businesses. Employees can put businesses at risk in a variety of ways, from leaving their computers unlocked and unattended to working remotely on unsecured networks. Take some time to educate your employees on good cybersecurity habits. Encourage your employees to create long, complex passwords and change them regularly. Your employees should also know how to recognize
&lt;a href=&quot;https://staysafeonline.org/blog/5-ways-spot-phishing-emails/&quot;&gt;phishing emails&lt;/a&gt;
and social engineering attacks. You may even have to implement policies to ensure that employees’
&lt;a href=&quot;http://www.leaderschoiceinsurance.com/blog/the-risks-of-staff-using-personal-devices-for-work/&quot;&gt;personal devices&lt;/a&gt;
are kept secure.&lt;/p&gt;

&lt;p&gt;If you (or one of your employees) really want to become an expert in cybersecurity, you could earn a master’s in information technology so you can learn how to better thwart viruses, malware, and scams that could harm your business. Earning a degree online allows you to learn on your own time so you can
&lt;a href=&quot;https://www.wgu.edu/online-it-degrees/masters-programs.html&quot;&gt;stay focused&lt;/a&gt;
on running your business.&lt;/p&gt;

&lt;h2 id=&quot;secure-your-internet-connection-and-wifi-networks&quot;&gt;Secure Your Internet Connection and Wifi Networks&lt;/h2&gt;

&lt;p&gt;No network is immune to attacks. However, there are ways to make your internet connection and wifi networks more secure. A
&lt;a href=&quot;https://www.itcentralstation.com/categories/firewalls&quot;&gt;firewall&lt;/a&gt;
is important for keeping malicious software out of your business network. If your network already has a firewall, remember that it may need to be enabled and should be updated regularly.&lt;/p&gt;

&lt;p&gt;When it comes to wifi, TechRadar recommends using
&lt;a href=&quot;https://www.techradar.com/news/networking/wi-fi/five-tips-for-a-secure-wireless-network-1161225&quot;&gt;strong encryption&lt;/a&gt;
with a WPA-protected network. This is much more secure than old wifi connection types. Plus, each person on your network can use their own username and password to get connected. Make sure to set up a separate wifi network for guests. It’s also smart to hide your network name to avoid attracting the attention of cybercriminals.&lt;/p&gt;

&lt;h2 id=&quot;install-antivirus-software&quot;&gt;Install Antivirus Software&lt;/h2&gt;

&lt;p&gt;Network security isn’t enough to prevent external threats from infiltrating your business. Strong antivirus protection is essential as well.
&lt;a href=&quot;https://smallbusiness.chron.com/benefit-antivirus-28239.html&quot;&gt;Antivirus software&lt;/a&gt;
can help keep your business safe from ransomware, spyware, malware, and viruses. This software provides real-time protection, dealing with infected files or malicious programs immediately. Antivirus software also provides regular device scans to search for threats or security weaknesses. Make sure all of your employee devices have up-to-date antivirus software at all times.&lt;/p&gt;

&lt;h2 id=&quot;perform-regular-backups&quot;&gt;Perform Regular Backups&lt;/h2&gt;

&lt;p&gt;Performing regular data backups is the best way to secure your business against data loss. If an accident or cyber attack results in lost data, you can just restore it from your backups. There are several ways to back up data, but the easiest method is to use a
&lt;a href=&quot;https://www.business2community.com/cloud-computing/business-benefits-of-a-cloud-backup-solution-0455427&quot;&gt;cloud backup service&lt;/a&gt;.
With a cloud backup service, you don’t have to manage any equipment or worry about keeping your backup data safe, and it’s
&lt;a href=&quot;https://seoexpertbrad.com/best-cloud-backup-solutions-for-small-business/&quot;&gt;easy on your budget&lt;/a&gt;.
Cloud services allow you to automate regular backups to secure offsite servers so your data can be recovered quickly and painlessly in the event of data loss. This will get your business up and running fast, minimizing costly downtime.&lt;/p&gt;

&lt;p&gt;Too many small businesses overlook important cybersecurity measures. Many people don’t realize that a single attack or data loss event could spell the end of their business. Protect your most valuable business asset—your data—by adopting smart cybersecurity habits and being prepared with a recovery plan.&lt;/p&gt;
</description>
        <pubDate>Thu, 11 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://morenoh149.github.io/2021/03/11/Cybersecurity-Tips-that-could-save-your-Small-Business.html</link>
        <guid isPermaLink="true">https://morenoh149.github.io/2021/03/11/Cybersecurity-Tips-that-could-save-your-Small-Business.html</guid>
        
        
      </item>
    
      <item>
        <title>Django Find Records in an Hour</title>
        <description>&lt;p&gt;Here we show how to select all records that occur in an hour. This is useful for
cases where you are running an async task at some interval smaller than a day.
My first attempts at doing this type of filtering involved providing a start and
end datetime. But there is a way to do it more simply by leveraging some database
functions.&lt;/p&gt;

&lt;p&gt;I needed to schedule microservice calls based on some business logic. We know with
async tasks its better to add a field to your model with a time to
be acted on rather than delaying tasks (&lt;a href=&quot;https://adamj.eu/tech/2020/02/03/common-celery-issues-on-django-projects/&quot;&gt;5. Using a Long countdown or an eta in the Far Future.&lt;/a&gt;). So with an hourly task, its pretty
natural to want to find all records that should be acted upon at that hour. The
following example shows running some operation when an Event starts 🤗.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# models.py
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DateTimeField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;blank&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# tasks.py
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# In your celery setup area
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup_periodic_tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_periodic_task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;crontab&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;do_for_events_this_hour&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;do_for_events_this_hour&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# the actual celery task
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;do_for_events_this_hour&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.db.models.functions&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TruncHour&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;.models&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;events_this_hour&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;annotate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;hour&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TruncHour&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;start&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hour&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TruncHour&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;events_this_hour&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;event this hour: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This basically truncates the datetime start to the nearest hour. And because we
run the task every hour we don’t have to worry about the minutes and seconds.&lt;/p&gt;

&lt;p&gt;The crontab(minute=15) bit makes the task run at the 15th minute of every hour.
The &lt;a href=&quot;https://docs.celeryproject.org/en/stable/reference/celery.schedules.html#celery.schedules.crontab&quot;&gt;celery crontab&lt;/a&gt; api provides an asterisk for the default values of args like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hour&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;day_of_week&lt;/code&gt;, etc. So an invocation like&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;crontab&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;is evaluated like&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;crontab&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;minute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;hour&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;*&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;day_of_week&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;*&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;day_of_month&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;*&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;month_of_year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;*&apos;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;which is analagous to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;15 * * * *&lt;/code&gt;. &lt;a href=&quot;https://crontab.guru/#15_*_*_*_*&quot;&gt;See in crontab&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My original approach involved tracking start and end times&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timezone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timedelta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;start__gte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;start__lt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;but you have to worry more about edgecases and this might be slower.&lt;/p&gt;
</description>
        <pubDate>Thu, 03 Dec 2020 00:00:00 +0000</pubDate>
        <link>https://morenoh149.github.io/2020/12/03/django-find-records-in-hour.html</link>
        <guid isPermaLink="true">https://morenoh149.github.io/2020/12/03/django-find-records-in-hour.html</guid>
        
        
      </item>
    
      <item>
        <title>Django Email Management Command</title>
        <description>&lt;p&gt;&lt;img src=&quot;/img/2020-10-14-email.png&quot; alt=&quot;Email&quot; /&gt;
Here we share a small django management command that sends an email.
This command is useful because it will use the same email credentials the rest
of your django api is using to send emails. So you can use this as a sanity check
to see if your settings are correct.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# &amp;lt;your app&amp;gt;/management/commands/send_email.py
&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.conf&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.core.mail&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;send_mail&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.core.management.base&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BaseCommand&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseCommand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Sends an email to the provided addresses.
    &quot;&quot;&quot;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;help&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Sends an email to the provided addresses.&quot;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;emails&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;send_email from: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EMAIL_FROM_FIELD&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;emails&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;send_mail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                    &lt;span class=&quot;s&quot;&gt;&quot;Django test email&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;s&quot;&gt;&quot;a simple email body&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EMAIL_FROM_FIELD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;BaseException&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Problem sending email: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;To use this ssh into your api and run:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python manage.py send_email foo@gmail.com bar@gmail.com&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If your django api has working email smtp settings you should see a test email
at the receiving addresses.&lt;/p&gt;

&lt;p&gt;In local development you can use something like &lt;a href=&quot;https://github.com/mailhog/MailHog&quot;&gt;mailhog&lt;/a&gt;
to preview the emails locally. It would look like this&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2020-10-14-mailhog.png&quot; alt=&quot;test email in mailhog&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Wed, 14 Oct 2020 00:00:00 +0000</pubDate>
        <link>https://morenoh149.github.io/2020/10/14/Django-Email-managment-command.html</link>
        <guid isPermaLink="true">https://morenoh149.github.io/2020/10/14/Django-Email-managment-command.html</guid>
        
        
      </item>
    
  </channel>
</rss>
