<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Joseph Mancuso</title>
    <description>The latest articles on DEV Community by Joseph Mancuso (@josephmancuso).</description>
    <link>https://dev.to/josephmancuso</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F80250%2F5d355fb1-d28a-4a8a-b682-cf6280e1db76.jpeg</url>
      <title>DEV Community: Joseph Mancuso</title>
      <link>https://dev.to/josephmancuso</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/josephmancuso"/>
    <language>en</language>
    <item>
      <title>Using Exceptionite 2 in Django with a single line</title>
      <dc:creator>Joseph Mancuso</dc:creator>
      <pubDate>Fri, 15 Apr 2022 04:44:24 +0000</pubDate>
      <link>https://dev.to/josephmancuso/using-exceptionite-2-in-django-with-a-single-line-2021</link>
      <guid>https://dev.to/josephmancuso/using-exceptionite-2-in-django-with-a-single-line-2021</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Exceptionite 2 is a debugging screen package written by the &lt;a href="https://github.com/masoniteframework/masonite"&gt;Masonite&lt;/a&gt; team. Although written by the Masonite maintainer team, it can be used in Flask, Django and of course Masonite.&lt;/p&gt;

&lt;p&gt;Starting in Masonite 4.9 this is the default debugging screen and it comes with a lot of amazing features.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detailed solutions for common or framework specific issues &lt;/li&gt;
&lt;li&gt;Easy to ready stack traces to see exactly which frames were hit&lt;/li&gt;
&lt;li&gt;Easily click any line in the stack trace to open that line in your editor&lt;/li&gt;
&lt;li&gt;Detailed environment and framework specific information&lt;/li&gt;
&lt;li&gt;Easily copy detailed information to quickly paste and share with your team or community.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Notable Features
&lt;/h2&gt;

&lt;p&gt;Before we go into how to quickly install Exceptionite into your Django project I'd like to go over some notable features in a bit more detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharing detailed errors
&lt;/h3&gt;

&lt;p&gt;Sometimes when you hit an exception and you can't figure it out you tend to go to people that can figure it out. Maybe these people are you coworkers or maybe they are a group inside a Discord server.&lt;/p&gt;

&lt;p&gt;In the top right you can click the Share Error link:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kEz34lIY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a0x4mok1cyfyx73k5a8l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kEz34lIY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a0x4mok1cyfyx73k5a8l.png" alt="Share Error Link" width="292" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will open a popup where you can easily select the important information you want to be put on your clipboard so you can paste the info later:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---WND7ryI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/amyuylkf69ptnisb5v8w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---WND7ryI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/amyuylkf69ptnisb5v8w.png" alt="Share Error Popup" width="880" height="904"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can copy this information either as "Raw" (just bullet points and text) or as markdown.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solutions
&lt;/h3&gt;

&lt;p&gt;Another awesome part of Exceptionite is the ability to see solutions to your exception in the first place. This is like having someone over your shoulder giving you suggestions while you develop your application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ghJFc7Ce--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ss7epyt5j0fipz1gpo0.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ghJFc7Ce--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ss7epyt5j0fipz1gpo0.jpeg" alt="Solutions To Errors" width="880" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Clicking on a stack trace line
&lt;/h3&gt;

&lt;p&gt;One of the amazing features is to click on a stack trace line and be able to open that line up directly in your editor to quickly start fixing&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fHoX6EpS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a2fb99uraxgfr87uivbh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fHoX6EpS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a2fb99uraxgfr87uivbh.png" alt="Stack Trace Line" width="880" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3yDvYgoX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e5eoro42p994bp7sdcbf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3yDvYgoX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e5eoro42p994bp7sdcbf.png" alt="Open in Editor" width="880" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dark Mode
&lt;/h2&gt;

&lt;p&gt;Thought this package couldn't get cool enough? It comes with a dark mode:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JeY6v1Pi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lvbfk1hm7fcbww7sy4k7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JeY6v1Pi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lvbfk1hm7fcbww7sy4k7.png" alt="Dark Mode" width="880" height="866"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing it in your Django project
&lt;/h2&gt;

&lt;p&gt;Having Exceptionite 2 serve your debug exception screen is extremely simple.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install Exceptionite:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install exceptionite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Set the Django exception report as the &lt;code&gt;DEFAULT_EXCEPTION_REPORTER&lt;/code&gt; in the &lt;code&gt;settings.py&lt;/code&gt; file.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# mysite/settings.py
&lt;/span&gt;
&lt;span class="n"&gt;DEFAULT_EXCEPTION_REPORTER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"exceptionite.django.ExceptioniteReporter"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>django</category>
      <category>debugging</category>
      <category>masonite</category>
    </item>
    <item>
      <title>The History of the Masonite Framework</title>
      <dc:creator>Joseph Mancuso</dc:creator>
      <pubDate>Mon, 03 Jan 2022 03:04:26 +0000</pubDate>
      <link>https://dev.to/masonite/the-history-of-the-masonite-framework-2n2b</link>
      <guid>https://dev.to/masonite/the-history-of-the-masonite-framework-2n2b</guid>
      <description>&lt;p&gt;Masonite is a batteries-included Python framework. As of the time of this article, it is on the 4th version in 4 years. As the creator of the framework, I thought it would be a good idea to walk through the history of the framework.&lt;/p&gt;

&lt;p&gt;I started learning Python in August 2017. At the time of starting Python, I was a PHP developer for over 6 years so I was very well versed in programming concepts.  &lt;/p&gt;

&lt;h2&gt;
  
  
  History
&lt;/h2&gt;

&lt;p&gt;Masonite actually started in December 2017 as a sandbox environment way to take my Python knowledge apply them to help learn. After a few beta releases which had the basic file structure, routing, controllers, used an ORM called Peewee ORM, and had migration structures similar to how they work today. The foundation of the framework was also completely inside new projects which made making bug fixes nearly impossible as the code didn't live inside the package.&lt;/p&gt;

&lt;p&gt;At this point I posted Masonite on the r/python reddit thread and you could imagine how that went. People &lt;strong&gt;roasted&lt;/strong&gt; Masonite saying how crap it was an how we already have Django and Flask, why do we need another framework. People did code reviews of Masonite and said how crap the code was. The issue is they were right. &lt;/p&gt;

&lt;p&gt;I went back to the drawing board, took the criticism and worked on version 1.&lt;/p&gt;

&lt;p&gt;v1.0 of Masonite was released shortly after in January of 2018. This version of Masonite had the same feature concepts as the beta releases, but changed the Peewee ORM out for the Orator ORM, and added the service providers concept which made the framework extremely extendable. At this point, Masonite also adopted the ROMVER versioning schema. &lt;/p&gt;

&lt;p&gt;v1.1-1.6 was released over in the first half of 2018 and made significant improvements to the internals of the framework, fleshed out the service container and the foundation of the framework and added sessions. At this point, people also started seeing the benefits that Masonite could be and started building a following. I also met a man named Aron who changed my life.&lt;/p&gt;

&lt;p&gt;v2.0 was released in June 2018. The release mainly consisted of improvements to developer experience and really polished he framework. Masonite also moved the core code to a new repository. v2.0 added features like scheduling, seeding, CSRF protection, the tinker command, and other foundational improvements. This was the flagship Masonite version that helped make Masonite into what it is today. &lt;/p&gt;

&lt;p&gt;I posted it again on the /r/python reddit thread and it received incredible feedback. People loved it. it was on the top of the /r/python thread for a week. I got invitations to be on several Python podcasts. Masonite gained hundreds of GitHub stars just from that thread alone. Masonite gained a big following on twitter and in the Slack community.&lt;/p&gt;

&lt;p&gt;v2.1 was release in December of 2018 and made some more structural changes. Added type-hinting parameter resolving, changed registering middleware to be class based only, and added several new commands.&lt;/p&gt;

&lt;p&gt;v2.2 was released in June 2019 and added new HTTP verbs, a new validation package, new testing structures, new drivers and more overall features.&lt;/p&gt;

&lt;p&gt;v2.3 was release in January 2020 as was the last release in Masonite's flagship release line. This brought more features such as authentication improvements, testing improvements, better developer experience changes as well as frontend asset building such as the preset command, Laravel Mix, and webpack files. Masonite also moved all the core code back into the masonite repository and added a cookie-cutter repo for new projects. Samuel Girardin, one of the main maintainers of the Masonite also came on. An excellent coder I am not sure Masonite would be where it is today if Sam didn't find the project.&lt;/p&gt;

&lt;p&gt;v3.0 was released in January 2021. This release brought very few changes to the Masonite codebase but switched out the Orator ORM for a completely new scratch built ORM called Masonite ORM. The Orator ORM at this point became clear that it was abandoned so we needed to either switch to another ORM or create our own. &lt;/p&gt;

&lt;p&gt;v4.0 was released in December 2021. This was rewritten from the ground up to rebuild the Masonite codebase foundation and all features on top of it. Masonite 1-3 was written on the same foundation which made improvements difficult as some features were not written in the same way. This release also moved Masonite to an 8 month release cycle and changed the versioning schema from ROMVER to SEMVER. &lt;/p&gt;

&lt;h2&gt;
  
  
  Masonite 4
&lt;/h2&gt;

&lt;p&gt;Masonite 4 (M4) brings more than just some code changes. M4 is a whole new paradigm shift. I am thinking of M4 as a grand reopening. A new foundation, new packages, new release schedule, new discord server, new ways of learning Masonite, new content. I am taking everything I've learned from running a framework and community over the last 4 years and putting it all into this release. 2022 will be focused on rebuilding the framework, producing content and engaging the community.&lt;/p&gt;

&lt;p&gt;There have been many people who came in during the end of the M3 lifecycle and are giving M4 a lot of attention. We have Sam who is helping me create packages for Masonite, we have Alex who is creating a video tutorial series already for Masonite.&lt;/p&gt;

&lt;p&gt;I can't build a wildly successful framework on my own. I know I need people in the community to help build this with me.&lt;/p&gt;

&lt;p&gt;If you want to learn more about Masonite, visit the GitHub page here: &lt;a href="https://github.com/MasoniteFramework/masonite"&gt;https://github.com/MasoniteFramework/masonite&lt;/a&gt; &lt;/p&gt;

</description>
      <category>masonite</category>
      <category>python</category>
    </item>
    <item>
      <title>My Productivity Workflow</title>
      <dc:creator>Joseph Mancuso</dc:creator>
      <pubDate>Thu, 30 Jan 2020 01:44:48 +0000</pubDate>
      <link>https://dev.to/josephmancuso/my-productivity-workflow-oc0</link>
      <guid>https://dev.to/josephmancuso/my-productivity-workflow-oc0</guid>
      <description>&lt;h1&gt;
  
  
  Preface
&lt;/h1&gt;

&lt;p&gt;Let me first preface this article by talking about something important. I like to change my productivity flow every few months to prevent myself from getting too complacent. I feel like life is like picking up sand and running with it. If I pick up a handful of sand and then start running full speed into deadlines and projects I am more likely to lose the sand quicker. I then need to stop, reorganize, pick up another full handful of sand and keep going.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is for anybody who needs to shift focus on several projects on a daily basis. You also get bonus points if you work in an environment where you can easily be distracted or your attention is pulled in several directions over the course of a single day (colleagues talking, emails coming in, customer support, mini side missions you need complete from the bosses randomly).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I hit a rock a few days ago where I felt like I was down in the dumps because stuff was getting piled up so high it was hard for me to focus even on what needed to happen next. During work, I balance several projects: an ERP system, a business web system, a consumer web system, customer support questions relating to these systems, &lt;a href="https://github.com/masoniteframework/masonite" rel="noopener noreferrer"&gt;Masonite&lt;/a&gt; related questions, an aggressive internal business-related meeting schedule and a team of 7 people. I constantly feel pulled from several directions and it's hard to focus on 1 thing or the other. Especially when everything feels like it's piling up and you're just trying to juggle what's coming next.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Workflow Allows You To Do
&lt;/h2&gt;

&lt;p&gt;This productivity workflow allows me to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quickly pick up where I left off during distractions and when people pull my attention away.&lt;/li&gt;
&lt;li&gt;Always remember what I am working on at the time even when I get distracted&lt;/li&gt;
&lt;li&gt;Ability to see what I need to work on for a specific Action Filter (more on that later) and allows me to cleanly block time out to only focus on very narrow things&lt;/li&gt;
&lt;li&gt;It allows me to switch between a lot of projects where I would normally feel overwhelmed I now feel like I am steadily hacking away at tasks while managing time efficiently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, when deadlines start hitting and projects start piling up, you start to slowly lose the organization needed to stay productive. That's why every few months I stop and reorganize. Sometimes that means cleaning up my &lt;a href="https://todoist.com/r/idmann509_rymves" rel="noopener noreferrer"&gt;Todoist&lt;/a&gt;, maybe reading some more tips and tricks on how to stay organized and prevent what just happened from happening again and sometimes it means revamping how I do productivity completely and learn new ways.&lt;/p&gt;

&lt;p&gt;Let's talk about what I've been doing this week where I feel like I am getting so much done lately. I am doing way more work, on time and feel less stressed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools Preference
&lt;/h2&gt;

&lt;p&gt;Let's talk about why I chose some of the tools you see in this article.&lt;/p&gt;

&lt;p&gt;I use &lt;a href="https://todoist.com/r/idmann509_rymves" rel="noopener noreferrer"&gt;Todoist&lt;/a&gt; because I have been using it for a long time and I think it is honestly the most perfect todo list app and I've used a lot of them. I am also almost a &lt;a href="https://todoist.com/r/idmann509_rymves" rel="noopener noreferrer"&gt;Todoist&lt;/a&gt; Grand Master so I have been using it for a while.&lt;/p&gt;

&lt;p&gt;I also use Bonsai to manage work for my clients. I work a full-time job as well as balance consulting clients who use &lt;a href="https://github.com/masoniteframework/masonite" rel="noopener noreferrer"&gt;Masonite&lt;/a&gt;. Bonsai also has a Time Tracking tool called Bonsai Time Tracker which links directly to Bonsai to add all my time to my projects. You may most likely use another time tracking tool if you follow this article.&lt;/p&gt;

&lt;h1&gt;
  
  
  Todoist
&lt;/h1&gt;

&lt;p&gt;The first thing I use is Todoist. Todoist is a todo app that I've been using for about a year and a half at this point. I'm more than halfway to a grandmaster status.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdqf87krd2q43nwf0zue6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdqf87krd2q43nwf0zue6.png" alt="Grandmaster Status"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I recently discovered a new way to manage Todoist. Instead of managing your work at a project level as most people do, you use something I call "Action Filters".&lt;/p&gt;

&lt;p&gt;The Action Filters are red filters that you use to do the major things you work on. For example, I work on a few major categories at work like: a &lt;code&gt;Web&lt;/code&gt; project and an &lt;code&gt;ERP&lt;/code&gt; project. I'll keep it to those 2 for now.&lt;/p&gt;

&lt;p&gt;I then make 2 filters for that and put it in my favorites section (which just puts it at the top so I can easily click it).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcpd84xptyzuuiwaule69.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcpd84xptyzuuiwaule69.png" alt="Two Filters"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The filters are very simple. I am just checking for the existence of that original &lt;code&gt;ERP&lt;/code&gt; tag and I always want to see the next 7 days so I can plan accordingly and I don't get surprised by any tasks I didn't know were actually coming up at all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdwhnu509bddtf1ne3ib8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdwhnu509bddtf1ne3ib8.png" alt="Todoist Query"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which will show my tasks in addition to the next 7 days out:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbp9c4z3oodp5mgv4zdpx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbp9c4z3oodp5mgv4zdpx.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Another important step is I have an office tag as well. Since these 2 Action Filters happen in the office I don't need to tag them as &lt;code&gt;Office&lt;/code&gt;. I already know they are done at the office. The reason I tag things with &lt;code&gt;Office&lt;/code&gt; is that they happen, or are going to happen, regardless of what Action Filter I am viewing so I want to see those tasks regardless of what I'm currently working on. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can see in the above screenshot that I have a team leader meeting tomorrow. This meeting is actually about the ERP but I want to see that meeting even when I am currently working on the web.&lt;/p&gt;

&lt;p&gt;Ok now that those 2 filters are in place. I simply use Time Blocking (more on that in the next section) which I can then slot time out and say "Ok I am going to start working on web stuff now so let's open that and see what I have to do today and what I have coming up soon I might have to prepare for." If I do a few hours on web stuff I'll open up my ERP Action Filter and do the same thing. I then have a bunch of tasks I can work on related to ERP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Even when unexpected things come up it's ok you can feel free to tackle them. Maybe a web issue hits and you have to switch focus for an hour. That is 100% OK because once you're done you can come back and open back up the current Action Filter and keep working through the list. This strategy allows you to get pulled away but you can sit right back down where you were where you left off.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Time Tracking
&lt;/h1&gt;

&lt;p&gt;Something else I have been typically against is tracking my time. I never wanted someone actually knowing how long I was working on something. It just felt like a little bit of a micromanage to me and that was just another thing I had to worry about was someone questioning me on why I took X amount of time to complete X task.&lt;/p&gt;

&lt;p&gt;But this time I was tracking time for myself. I personally wanted to know how long I was spending on working on various things.&lt;/p&gt;

&lt;p&gt;I started uses Bonsai Time Tracker. Mainly because I use the Bonsai application in order to manage various clients I consult for. If you were doing this you can use whatever time tracker you want. It really helps though if it has a Mac app if you use Mac or some other kind of very easily accessible way of using it. You don't want to be spending too much time inside an app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't Want To Mess Up Time
&lt;/h2&gt;

&lt;p&gt;One of the tricks and reasons that time tracking helps me is it keeps me focused. I simply start up the timer, tell it what project I'm working on (ERP) and it starts a timer. &lt;strong&gt;Whenever I get distracted and look up and see the timer ticking I know I don't want to mess up my time estimates. If at the end of the week I see I spent 12 hours working on ERP but in reality, I know I spent some of that time on the web then I know it's not truly correct. So seeing the timer helps me from getting distracted only because I know I want to see only truly accurate time estimates.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Also if I forget to start the timer I can always modify the time before starting it. For example, if I didn't start the timer but I've been working for 15 minutes then I can just start a timer at 15 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;A cool feature of Bonsai is that you can type what you're working on&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7w1copb6gci8dvhcu834.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7w1copb6gci8dvhcu834.png" alt="Bonsai Time Tracker"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is great if I get pulled away and need to remember what I was working on. I can say "Oh right it says I was working on merging pull requests." I can't tell you the number of times people have asked me for something 2 weeks after they told me to do it and I remember I never completed it because I simply got pulled away and forgot what I was working on and just went to the next task.&lt;/p&gt;

&lt;h2&gt;
  
  
  Liberation
&lt;/h2&gt;

&lt;p&gt;One of the things I feel bad about is when I get distracted while working on a task. When I am halfway through a task and then I think "Let me look up the lyrics to some song because I forgot them." Now I look at the time and don't want it to get messed up but another thing I can do is simply stop the timer.&lt;/p&gt;

&lt;p&gt;There is something about stopping the timer that makes me &lt;strong&gt;feel&lt;/strong&gt; like I am in between tasks. I &lt;strong&gt;feel&lt;/strong&gt; OK to be distracted because it feels more like taking a break than being distracted. I also &lt;strong&gt;feel&lt;/strong&gt; comfortable knowing I can pull away and go right back to where I started because I can see inside the timer where I left off for reference. I know I won't have the issue of forgetting what I was working on and simply moving to the next task.&lt;/p&gt;

&lt;h2&gt;
  
  
  Length
&lt;/h2&gt;

&lt;p&gt;Another nice thing to know is how long I've been working on something. If I see I've only been working on an Action Filter for 1.5 hours I can say "eh let me work for another hour before moving to the next Action Filter." This allows me to manage my time more efficiently and I don't spend 90% of my time on 1 project and neglect another project which is something I used to do quite often.&lt;/p&gt;

&lt;p&gt;It also allows me to say "Wow I've been working at this for 3.5 hours. Let me take a break and walk around some."&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>timemanagement</category>
      <category>softwaredevelopment</category>
      <category>masonite</category>
    </item>
    <item>
      <title>What I learned from Speaking with Taylor Otwell and How its Changing Masonite</title>
      <dc:creator>Joseph Mancuso</dc:creator>
      <pubDate>Mon, 29 Jul 2019 23:17:06 +0000</pubDate>
      <link>https://dev.to/masonite/what-i-learned-from-speaking-with-taylor-otwell-and-how-its-changing-masonite-4fmd</link>
      <guid>https://dev.to/masonite/what-i-learned-from-speaking-with-taylor-otwell-and-how-its-changing-masonite-4fmd</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;I got the awesome opportunity to talk to &lt;a href="https://twitter.com/taylorotwell"&gt;Taylor Otwell&lt;/a&gt;, the creator of Laravel, for a few minutes at Laracon 2019. I knew I only wanted to take a few minutes of his time so I had to think of 1 solid question to ask him.&lt;/p&gt;

&lt;p&gt;So here's the question I asked him:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/MasoniteFramework/masonite"&gt;Masonite&lt;/a&gt; is currently at over 1000 stars. When Laravel was at 1000 stars, what's something you did to really get it to the next level?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Taylor's Response
&lt;/h1&gt;

&lt;p&gt;What Taylor said was pretty straight forward and made a lot of sense:&lt;/p&gt;

&lt;p&gt;He said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Video tutorials, documentation and blog posts. The easier it is to learn, the more people will use it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Reflection
&lt;/h1&gt;

&lt;p&gt;Now, this might be obvious to you but this was sort of profound to me. I feel like its something I always sort of knew but it was one of those things where simply hearing it out loud makes it make more sense than saying it to yourself.&lt;/p&gt;

&lt;p&gt;The interesting part there is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The easier it is to learn, the more people will use it&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is something implicit in that sentence right there. The goals I have been developing towards have been creating a better framework than all of its competitors. &lt;/p&gt;

&lt;p&gt;But I think the real goal here is just as Taylor said, "&lt;strong&gt;The easier it is to learn, the more people will use it&lt;/strong&gt;."&lt;/p&gt;

&lt;p&gt;See, things don't have to be better for people to necessarily use it. It needs to be easy to learn. You need to be able to start development and stay started. &lt;/p&gt;

&lt;p&gt;Think of the best package having no documentation at all &lt;strong&gt;vs&lt;/strong&gt; a less good package with amazing documentation. Which one do you think more people will use?&lt;/p&gt;

&lt;h1&gt;
  
  
  Future Goals
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;So instead of working on a whole bunch of new features, I will be taking the next few months and working on ways to make Masonite easier to learn.&lt;/strong&gt; Masonite will continue to have feature releases of course but less often. &lt;strong&gt;I will let the community be the leaders of the next few releases and take more of a BDFL approach by doing reviews and general pop-ins on PR's.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of coding in my free time, I will be working on things that make Masonite easier to learn. Instead of trying to get new features to be the driver of new users. I will focus on making Masonite the easiest Python web framework to learn and, according to Taylor, that will be the driver of new users.&lt;/p&gt;

&lt;p&gt;This will entail things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Even more documentation&lt;/li&gt;
&lt;li&gt;More video tutorials&lt;/li&gt;
&lt;li&gt;More blog posts&lt;/li&gt;
&lt;li&gt;More code snippets&lt;/li&gt;
&lt;li&gt;More How-tos.&lt;/li&gt;
&lt;li&gt;Build a site where I can store all these video tutorials.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think taking the next few months going with this approach will allow Masonite to take off pretty well.&lt;/p&gt;

</description>
      <category>python</category>
      <category>laravel</category>
      <category>webframework</category>
      <category>laracon</category>
    </item>
    <item>
      <title>Masonite 2.2 Released - The Modern Python Web Framework!</title>
      <dc:creator>Joseph Mancuso</dc:creator>
      <pubDate>Sat, 15 Jun 2019 13:12:34 +0000</pubDate>
      <link>https://dev.to/masonite/masonite-2-2-released-the-modern-python-web-framework-2034</link>
      <guid>https://dev.to/masonite/masonite-2-2-released-the-modern-python-web-framework-2034</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;As the creator of Masonite and a part of the super fast growing Masonite community, I am super excited to release this to the world as the next major version of Masonite.&lt;/p&gt;

&lt;p&gt;A lot of people have worked really hard on this release. I can't take full credit for this release at all. Countless hours coding new features, abstracting out old ones and simply talking out features in our Slack chat.&lt;/p&gt;

&lt;p&gt;Masonite has grown a lot in the past year and a half. I could go into a full-length post on all the features and benefits of using Masonite so below are just some recent highlights about the community and this specific release:&lt;/p&gt;

&lt;h1&gt;
  
  
  Release Highlights:
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Almost 1000 stars now on GitHub&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;230+ people in Masonite Slack channel&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;100's of pages of documentation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Awesome new validation library I built specifically for Masonite that I have been using a LOT in 2.2.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A brand new testing module for Masonite.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added a much better way to test the database and create integration tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DOZENS of quality of life improvements over Masonite 2.1&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generally backward compatible with Masonite 2.1. A few minor changes to upgrade.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Community
&lt;/h1&gt;

&lt;p&gt;Here's a very small portion of what the community is saying about Masonite just in the Slack chat. I really am so honored to have been a part of building the Masonite community. We have some of the warmest welcoming people in the Python community its amazing. Love seeing devs helping out other devs. Make sure you join using the links at the bottom of the thread.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z7Wgoo6W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dfh38nnz0ozcg0bcl6tv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z7Wgoo6W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dfh38nnz0ozcg0bcl6tv.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gpKFp4Fn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/azr6vaaxumsot50qo9dy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gpKFp4Fn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/azr6vaaxumsot50qo9dy.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a2bbprdW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/w0hkcfj8g01tnfc7typn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a2bbprdW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/w0hkcfj8g01tnfc7typn.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JLRAe0Xh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ofvfhivvbdhkz7q1x1u2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JLRAe0Xh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ofvfhivvbdhkz7q1x1u2.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vTJBiLxy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/f4jcnzctvywpq4gnvf6k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vTJBiLxy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/f4jcnzctvywpq4gnvf6k.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cy7g4NuN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/7fngd9w9yzmz800a8bge.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cy7g4NuN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/7fngd9w9yzmz800a8bge.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2gpLAuTU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6bspz217br3h0aieadag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2gpLAuTU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6bspz217br3h0aieadag.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9Zn76eIc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/cn8pqrub5c07u15d7x7q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9Zn76eIc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/cn8pqrub5c07u15d7x7q.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Learn More
&lt;/h1&gt;

&lt;p&gt;To learn more about the framework and start using it, here are some links to help:&lt;/p&gt;

&lt;p&gt;Slack: &lt;a href="http://slack.masoniteproject.com/"&gt;http://slack.masoniteproject.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Docs: &lt;a href="http://docs.masoniteproject.com"&gt;http://docs.masoniteproject.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5 reasons why people are choosing Masonite over Django: &lt;a href="https://dev.to/masonite/5-reasons-why-people-are-choosing-masonite-over-django-ic3"&gt;https://dev.to/masonite/5-reasons-why-people-are-choosing-masonite-over-django-ic3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What's New in 2.2: &lt;a href="https://docs.masoniteproject.com/v/v2.2/whats-new/masonite-2.2"&gt;https://docs.masoniteproject.com/v/v2.2/whats-new/masonite-2.2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Twitter: &lt;a href="https://twitter.com/masoniteproject"&gt;https://twitter.com/masoniteproject&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Masonite: &lt;a href="https://github.com/masoniteframework/masonite"&gt;https://github.com/masoniteframework/masonite&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Masonite Core: &lt;a href="https://github.com/masoniteframework/core"&gt;https://github.com/masoniteframework/core&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Awesome Masonite: &lt;a href="https://awesome.masoniteproject.com/"&gt;https://awesome.masoniteproject.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>framework</category>
      <category>masonite</category>
    </item>
    <item>
      <title>5 reasons why people are choosing Masonite over Django</title>
      <dc:creator>Joseph Mancuso</dc:creator>
      <pubDate>Wed, 27 Feb 2019 02:33:05 +0000</pubDate>
      <link>https://dev.to/masonite/5-reasons-why-people-are-choosing-masonite-over-django-ic3</link>
      <guid>https://dev.to/masonite/5-reasons-why-people-are-choosing-masonite-over-django-ic3</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/masoniteframework/masonite"&gt;Masonite&lt;/a&gt; is an increasingly popular Python web framework that has garnered a lot of attention in the Python community recently.&lt;/p&gt;

&lt;p&gt;I am not here to say that Django is crap and that Masonite is the best thing in the entire world but I have talked with a lot of developers over the past year on why they made the switch from Django to Masonite. Below I will go into some detail on the common reasons I have found between them all and why Masonite may make more sense to use for your next project.&lt;/p&gt;

&lt;p&gt;One of these developers in particular, &lt;a href="https://github.com/aisola"&gt;Abram Isola&lt;/a&gt;, gave some really excellent feedback on why his contract bid (with an extremely large company) ended up winning over all other bids.&lt;/p&gt;

&lt;p&gt;Before we start, here are a few links if you want to follow Masonite to explore a bit further:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://slack.masoniteproject.com"&gt;Official Slack Channel&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/masoniteproject"&gt;Twitter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ok, let's get started :)&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Existing Databases
&lt;/h2&gt;

&lt;p&gt;Some business applications require you to use an existing database in order to create a new integration for them. &lt;/p&gt;

&lt;p&gt;Managing an existing database with Django is not particularly difficult. You can use something like &lt;code&gt;inspect db&lt;/code&gt; with Django in order to generate the proper models and model schema attributes. The issue really arises when you have to manage several databases within the same application, some of which are existing and some of which you need to manage yourself.&lt;/p&gt;

&lt;p&gt;You can still do this with Django with something like database routers but it requires a good amount of setup and testing. When you're starting development on an application, you just want to hit the ground running and start the business logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Active Record Pattern ORM
&lt;/h3&gt;

&lt;p&gt;Masonite and Django both use the Active Record Style of ORM but the main difference is that Orator has more of a dynamically passive approach to it.&lt;/p&gt;

&lt;p&gt;For example, with Django, you specify the columns on the table by using attributes on the class.&lt;/p&gt;

&lt;p&gt;In Django this may look something like:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Musician&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;instrument&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now whenever you retrieve, store and exchange data between your model and the database, Django knows what type of data to handle.&lt;/p&gt;

&lt;p&gt;Orator is a bit more dynamic. Orator will use the schema the table has in order to map the values of the attributes. In fact, Orator does not need explicit definitions of attributes at all. A comparable model in Masonite would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;config.database&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Model&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Notice we do not specify a firstname, lastname or instrument because Orator knows when it fetches the data from the table, which attributes to set on the model.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Class scaffolding
&lt;/h2&gt;

&lt;p&gt;Masonite has what it calls "craft" commands. These are called craft commands because they are a simple command like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;craft model Project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;that .. "crafts" .. these classes for you so you can stop writing redundant boilerplate over and over again. We all know that the start of a controller starts the same, we all know that the declaration of a function based view starts the same, we all know that a class-based view generally starts the same. &lt;/p&gt;

&lt;p&gt;We as developers are constantly writing the same boilerplate over and over again when we get into the rinse-and-repeat cycle of development. Create a file, create some class boilerplate, create the class definition, imports the require classes, etc. &lt;/p&gt;

&lt;p&gt;This is why Masonite has over a dozen commands that allow you to create views, controllers, queue jobs, commands, middleware, models, database seeds, etc all from the command line. This saves you and your team a lot of time in development. &lt;/p&gt;

&lt;p&gt;Spending time writing out that class definition doesn't only take time from the developer but also breaks the concentration of the developer. You as a developer just wants to generate the class definition and then immediately start working on the business logic that class needs to contain.&lt;/p&gt;

&lt;p&gt;Also, the developer no longer needs to remember what base classes or imports are required to be imported in order to get that boilerplate code up and running. Just let the craft command do all the hard work for you so you can keep focusing on your application.&lt;/p&gt;

&lt;p&gt;If you want to save a lot of time writing boilerplate code then consider using Masonite for your next application.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Folder Structure
&lt;/h2&gt;

&lt;p&gt;This is typically a personal preference and many developers may not share this reason but Masonite lends an extremely solid folder structure.&lt;/p&gt;

&lt;p&gt;Masonite has a few different philosophies by default. &lt;/p&gt;

&lt;p&gt;One of these is to keep 1 class 1 file. Some developers may think this is normal but many still write multiple classes per file generally. Once you start using the 1 class 1 file system you will never look back.&lt;/p&gt;

&lt;p&gt;Another philosophy is to maintain a Separation of Concerns. If you run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;craft job SomeJob
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for example, it scaffolds that class in the &lt;code&gt;app/jobs&lt;/code&gt; directory. Need to craft a middleware? Middleware will be created in the &lt;code&gt;app/http/middleware&lt;/code&gt; directory. Need to create a recurring task? Tasks will be created in the &lt;code&gt;app/tasks&lt;/code&gt; directory. For on and so forth. &lt;/p&gt;

&lt;p&gt;This allows you to not accidentally bundle up all your logic in the same place which makes refactoring later on a huge headache. It's generally good practice to keep all related logic together in their respective modules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Self Contained Apps
&lt;/h3&gt;

&lt;p&gt;Django, on the other hand, has a good starting structure and also boasts the self-contained apps portion of the framework. This allows you to create self-contained packages that can swap around, be removed, plugged into other applications if done correctly, etc.&lt;/p&gt;

&lt;p&gt;The issue with this is that it is fantastic in theory, terrible in practice. In fact, it's my opinion that this is a bit of an anti-pattern, at least the way Django does it.&lt;/p&gt;

&lt;p&gt;Anybody who has created a self-contained app knows that it works really well for the first few days and then you start to wrestle it as your app models start to depend on other apps. Finally, you end up putting all your models into a single app and then building your entire application into there. Maybe you use other self-contained apps as packages but they usually end up eventually breaking the "self-contained" promise.&lt;/p&gt;

&lt;p&gt;I think this is one of Django's biggest sells and it is a bit of an over promise. While Django sells you on a single application that is broken up into self-contained apps, Masonite is building a single app with a very well structured separation of the concerns file structure to keep you rolling.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Middleware
&lt;/h2&gt;

&lt;p&gt;Masonite's middleware system allows for some very easy implementations while also staying very complex and dynamic. Abram Isola chose Masonite over Django because Masonite's middleware has a couple of capabilities that Django simply does not.&lt;/p&gt;

&lt;p&gt;Firstly, Masonite has 2 types of middleware. Both types use the exact same class but it just depends on where you put the class after you create it.&lt;/p&gt;

&lt;p&gt;The first type of Masonite middleware is what's called HTTP Middleware. This middleware runs of every request like you would normally expect.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;HTTP_MIDDLEWARE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;AuthenticationMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second type of middleware is what's called Route Middleware:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ROUTE_MIDDLEWARE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;'auth'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AuthenticationMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is also the same middleware class you wrote before, just inside a different list a few lines down the config file. Route middleware is a bit more flexible. You can attach it to a specific route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ROUTES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/dashboard'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'DashboardController@show'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'auth'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or a group of routes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ROUTES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;RouteGroup&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/dashboard'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'DashboardController@profile'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/dashboard/stats'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'DashboardController@stats'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/dashboard/users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'DashboardController@users'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'auth'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your application needs very precise access controls or simple integrations of middleware, you should consider Masonite for your next project.&lt;/p&gt;

&lt;p&gt;Django does have middleware bit it runs on every request and you need to specify inside the middle if it should actually execute any logic based on some input like the request route.&lt;/p&gt;

&lt;h3&gt;
  
  
  Django Middleware Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;global_auth_middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_authenticated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/login/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;get_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;middleware&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Masonite Middleware Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;masonite.request&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationMiddleware&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;redirect_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'login'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;after&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Built in features and drivers
&lt;/h2&gt;

&lt;p&gt;Django and Masonite are both called "batteries included frameworks" but Masonite is boasted as the "Modern and developer-centric Python web framework" because of the types of batteries included features that it contains. &lt;/p&gt;

&lt;p&gt;Masonite has features for built-in Amazon S3 uploading, RabbitMQ queue support, Mailgun, and SMTP email sending support, simple database seeding to easily teardown, rebuild and seed your database with data, built in Pusher for websocket support, built in recurring task scheduling and so much more. All of these features that would be "must haves" if it didn't take so much time to integrate them now takes seconds to set up.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Does your application have notifications? Easy just use the websocket features to push out notifications to your users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does your application send email? Queue all of them with RabbitMQ so your application is much more responsive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does your application handle user uploads? Use the Amazon S3 upload feature to manage them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does some parts of your application require some tasks to run every hour or every day at midnight? Easy just use the Task scheduling feature to schedule tasks to run every day, every 3 days, or every 5 days at 3 pm easily.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Masonite takes a lot of these features that you may spend several hours researching, implementing and testing and allows you to stay focused on your own business logic and use the integrations we built for you!&lt;/p&gt;

&lt;p&gt;Django does have a lot of features out of the box but not remotely as many as Masonite and we are typically adding new features every 2 weeks. You could wake up tomorrow with brand new integration. Update Masonite and you're ready to rock and roll.&lt;/p&gt;




&lt;p&gt;Thanks for giving me the time to explain why people are switching from Django to Masonite :)&lt;/p&gt;

&lt;p&gt;Be sure to follow Masonite using the links below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://slack.masoniteproject.com"&gt;Official Slack Channel&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/masoniteproject"&gt;Twitter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.masoniteproject.com"&gt;Masonite Docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/masoniteframework/masonite"&gt;Masonite&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/masoniteframework/core"&gt;Masonite Core&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://awesome.masoniteproject.com/"&gt;Awesome Masonite&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>masonite</category>
      <category>django</category>
      <category>python</category>
      <category>framework</category>
    </item>
    <item>
      <title>Updated Queue Rework For Masonite 2.1</title>
      <dc:creator>Joseph Mancuso</dc:creator>
      <pubDate>Sun, 10 Feb 2019 13:53:31 +0000</pubDate>
      <link>https://dev.to/masonite/updated-queue-rework-for-masonite-21-4hfh</link>
      <guid>https://dev.to/masonite/updated-queue-rework-for-masonite-21-4hfh</guid>
      <description>&lt;h1&gt;
  
  
  Preface
&lt;/h1&gt;

&lt;p&gt;I would like to write this post to demonstrate some of the changes in this release since this is a bit larger than a few line file change.&lt;/p&gt;

&lt;p&gt;The queue feature in &lt;a href="https://github.com/masoniteframework/masonite"&gt;Masonite&lt;/a&gt; allows you to put jobs into a few supported drivers in order to run them at a later date, either asynchronously or through some message broker like RabbitMQ.&lt;/p&gt;

&lt;p&gt;The original queue feature was written in about 3 days and put into Masonite and released. It did everything i personally needed it to do and since it scratched my itch then maybe other Masonite developers would find it good too.&lt;/p&gt;

&lt;p&gt;During the development of Masonite 2.2 (will be released in June 2019), I wanted to take a few concepts and "rework" them to make them better internally which usually just entails rewriting the implementation from scratch without touching the external interface.&lt;/p&gt;

&lt;p&gt;In other words I wanted to do a pretty big rewrite but also make it an non breaking change that can go into the next minor version of the framework.&lt;/p&gt;

&lt;p&gt;So in this post I'll talk about all the new features of the Queue Rework.&lt;/p&gt;

&lt;h2&gt;
  
  
  queue:work Command
&lt;/h2&gt;

&lt;p&gt;There are a few changes to the &lt;code&gt;queue:work&lt;/code&gt; command. You can now specify the driver that you want to start a worker for using the &lt;code&gt;-d&lt;/code&gt; or &lt;code&gt;--driver&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ craft queue:work -d amqp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will now run a queue worker for the specific driver.&lt;/p&gt;

&lt;h2&gt;
  
  
  Failed Jobs
&lt;/h2&gt;

&lt;p&gt;Failed jobs are a really awesome new addition to Masonite. Before when a job failed it sort of got stuck in the queue. You would have to purge out the job if it failed.&lt;/p&gt;

&lt;p&gt;Now the job inside the queue will try to run 3 times back to back with 1 second in between before finally calling the job a failed job. &lt;/p&gt;

&lt;p&gt;If the job fails it will call the &lt;code&gt;failed&lt;/code&gt; method on the job. A normal job might now look something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;masonite.queues&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Queueable&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;masonite.request&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;masonite&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Mail&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendWelcomeEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Queueable&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Mail&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mail&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;# fails
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'developer@company.com'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'
            The welcome email failed with error {}
        '&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The first parameter is the payload which tried running which is a dictionary of information that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;'obj'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SomeJob&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;'args'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'some_variables'&lt;/span&gt;&lt;span class="p"&gt;,),&lt;/span&gt; 
    &lt;span class="s"&gt;'callback'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'handle'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="s"&gt;'created'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'2019-02-08T18:49:59.588474-05:00'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="s"&gt;'ran'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and the error may be something like &lt;code&gt;division by zero&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now you can get a pretty proactive look at your jobs when they fail&lt;/p&gt;

&lt;h3&gt;
  
  
  Saving Failed Jobs
&lt;/h3&gt;

&lt;p&gt;If a job fails it will sort of just disappear. You cannot run a failed job again. &lt;/p&gt;

&lt;p&gt;This is why we now have a table and migration for failed jobs. You can create the table and migrate it into your database by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;craft&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;craft&lt;/span&gt; &lt;span class="n"&gt;migrate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will create a new migration file for you into your migration directory. You can then migrate manually.&lt;/p&gt;

&lt;p&gt;Now when a job fails it will actually serialize it and store it in this table. In order to run jobs again you can run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;craft&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;work&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;failed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;which sends all the jobs into the queue again to be re-ran.&lt;/p&gt;

&lt;h2&gt;
  
  
  Internal Rewrite
&lt;/h2&gt;

&lt;p&gt;For those developing drivers for Masonite. This feature did to an internal rewrite of how drivers are written. All drivers must now inherit from &lt;code&gt;BaseQueueDriver&lt;/code&gt; which gives each driver a few features now to be compliant with Masonite.&lt;/p&gt;

&lt;p&gt;Since I know there are no other queue drivers currently written for Masonite, I feel comfortable making this change.&lt;/p&gt;

&lt;p&gt;The contract for queues now has more methods in it. Meaning more methods are required to create a queue driver that is in compliance with the queue contract.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;queue:work&lt;/code&gt; command is now queue driver agnostic when previously it was only for the &lt;code&gt;amqp&lt;/code&gt; driver. As long as your driver inherits from the &lt;code&gt;QueueContract&lt;/code&gt; then you will be fine to add a driver to Masonite.&lt;/p&gt;




&lt;p&gt;If you would like to contribute or support Masonite's development, please head over to the &lt;a href="https://github.com/masoniteframework/masonite"&gt;Masonite Github&lt;/a&gt; and give it a star!&lt;/p&gt;

</description>
      <category>python</category>
      <category>framework</category>
      <category>masonite</category>
    </item>
    <item>
      <title>Masonite Lessons - Using The Factory Pattern</title>
      <dc:creator>Joseph Mancuso</dc:creator>
      <pubDate>Thu, 17 Jan 2019 04:13:22 +0000</pubDate>
      <link>https://dev.to/masonite/masonite-lessons---using-the-factory-pattern-o6p</link>
      <guid>https://dev.to/masonite/masonite-lessons---using-the-factory-pattern-o6p</guid>
      <description>

&lt;h1&gt;
  
  
  Preface
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/masoniteframework/masonite"&gt;Masonite&lt;/a&gt; has a lot of very front facing and explicit design patterns. It has always been my goal that developers using &lt;a href="https://github.com/masoniteframework/masonite"&gt;Masonite&lt;/a&gt; will become better developers by being exposed to these patterns either by use or by reading about them in the documentation and understanding through real world examples.&lt;/p&gt;

&lt;p&gt;I will be creating these articles that talk about various design patterns and how I use them in my applications on a daily basis.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Design Patterns are pretty simple. We as developers encounter problems with our code. We as developers have 5 goals of software development is to deliver a product that is&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;on time&lt;/li&gt;
&lt;li&gt;within budget&lt;/li&gt;
&lt;li&gt;fault free (no bugs)&lt;/li&gt;
&lt;li&gt;satisfies needs now&lt;/li&gt;
&lt;li&gt;satisfies need in the future&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We as developers need to be able to accomplish these tasks in a way that can satisfy needs now and in the future. These are problems developers face all the time. Throughout the years, developers have encountered the same issues over and over again and the same way a carpenter has “tricks of the trade,“ so do developers. These tricks-of-the-trade are called Software Design Patterns. They are simply solutions to problems we encounter all the time in our development life.&lt;/p&gt;

&lt;p&gt;Once you start to get good as a developer, you will be able to map issues to certain design patterns and be able to layout a software architecture to fit the needs of the problem you are solving.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Pattern
&lt;/h1&gt;

&lt;p&gt;The factory pattern is used to instantiate an object at runtime. That’s it. It’s just a class that can return different types of objects dependent on whatever value is passed to it. For example you may pass in the value of &lt;code&gt;chocolate&lt;/code&gt; into the &lt;code&gt;IceCreamFactory&lt;/code&gt; and get back a &lt;code&gt;ChocolateIceCream&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;This may need to be done at runtime which is where this pattern comes into play. The value of &lt;code&gt;chocolate&lt;/code&gt; may be stored in a database column that is fetched for a certain user for example.&lt;/p&gt;

&lt;h1&gt;
  
  
  Code Example
&lt;/h1&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IceCreamFactory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="n"&gt;flavors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;'chocolate'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ChocolateIceCream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'vanilla'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;VanillaIceCream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'strawberry'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;StrawberryIceCream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flavor&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flavors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;flavor&lt;/span&gt;&lt;span class="p"&gt;]()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's it. We just created a factory using the factory pattern. Now all we have to do is specify a flavor we need and we can get back the correct flavor:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;flavor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IceCreamFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'strawberry'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#== &amp;lt;some.module.StrawberryIceCream&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  The Problem - Real World Example
&lt;/h1&gt;

&lt;p&gt;Here is a real world example of how I used this pattern. We are provisioning a server. For simplicity sake, we have 2 services we want to provision:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Postgres&lt;/li&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we need to provision both of these services on 2 different types of servers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu&lt;/li&gt;
&lt;li&gt;Debian&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now notice here we have several different possibilities we can choose from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installing Postgres on Ubuntu&lt;/li&gt;
&lt;li&gt;Starting Postgres on Ubuntu&lt;/li&gt;
&lt;li&gt;Stopping Postgres on Ubuntu&lt;/li&gt;
&lt;li&gt;Installing Nginx on Debian
...
... so on and so forth&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is an exponential number of possibilities, especially as we add new servers, new services or add layers in between them (for example installing via docker instead of bash commands).&lt;/p&gt;

&lt;p&gt;How do we solve this issue? A bit of a combination of several patterns but we'll focus on the Factory for this article.&lt;/p&gt;

&lt;h1&gt;
  
  
  Solution
&lt;/h1&gt;

&lt;p&gt;The solution here is to use 2 factories.&lt;/p&gt;

&lt;p&gt;The first factory will be a &lt;code&gt;ServerFactory&lt;/code&gt; which will be responsible for fetching any one of several servers (Ubuntu, Debian, Centos, ..).&lt;/p&gt;

&lt;p&gt;The second factory will be a &lt;code&gt;ServicesFactory&lt;/code&gt; which will be responsible for fetching any one of several services (Postgres, Nginx, RabbitMQ, ..).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Server Factory
&lt;/h2&gt;

&lt;p&gt;Using the boiler plate above let's go ahead and create our &lt;code&gt;ServerFactory&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ServerFactory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="n"&gt;servers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;'ubuntu'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UbuntuServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'debian'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DebianServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'centos'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CentosServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;servers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;]()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Notice we just changed out the ice cream flavors for servers (UNIX flavors?). &lt;/p&gt;

&lt;h2&gt;
  
  
  The Service Factory
&lt;/h2&gt;

&lt;p&gt;Now let's do the exact same thing for services:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ServiceFactory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="n"&gt;services&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;'postgres'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;PostgresService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'nginx'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NginxService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'rabbitmq'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RabbitMQService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;]()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;notice all this code is the same boiler plate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Combining The Factory
&lt;/h2&gt;

&lt;p&gt;Now if we think of it from a database perspective:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A server &lt;strong&gt;has many&lt;/strong&gt; services&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Right? Since a server &lt;strong&gt;has many&lt;/strong&gt; services, let's mimick that. Let's make the &lt;code&gt;UbuntuServer&lt;/code&gt; have access to the &lt;code&gt;ServiceFactory&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;app.factories&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ServiceFactory&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UbuntuServer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="n"&gt;services&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ServiceFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;establish_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Boom. Done. Now our &lt;code&gt;UbuntuServer&lt;/code&gt; has access to all of our services.&lt;/p&gt;

&lt;h1&gt;
  
  
  Using It All Together
&lt;/h1&gt;

&lt;p&gt;Let's go ahead and use these 2 factories in our application:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;app.factories&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ServerFactory&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="c1"&gt;#== 'ubuntu'
&lt;/span&gt;
  &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ServerFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#== &amp;lt;app.servers.UbuntuServer&amp;gt;
&lt;/span&gt;  &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'postgres'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'nginx'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'rabbitmq'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
      &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  The Future
&lt;/h1&gt;

&lt;p&gt;Design patterns are useful for solving problems now and in the future. This pattern is useful because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;supporting more servers is as simple as creating new servers.&lt;/li&gt;
&lt;li&gt;supporting more services is as simple as creating new services.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These two things can exist separately of each other and therefore can be scaled up or down separately of each other. &lt;/p&gt;


</description>
      <category>python</category>
      <category>framework</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>Next version of Masonite - v2.1 released! The Modern Python Web Framework </title>
      <dc:creator>Joseph Mancuso</dc:creator>
      <pubDate>Sat, 01 Dec 2018 13:15:41 +0000</pubDate>
      <link>https://dev.to/masonite/next-version-of-masonite---v21-is-released--1f48</link>
      <guid>https://dev.to/masonite/next-version-of-masonite---v21-is-released--1f48</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Masonite 2.1 has been released! Masonite is an amazing MVC and &lt;strong&gt;true&lt;/strong&gt; batteries included web framework. &lt;/p&gt;

&lt;p&gt;For those familiar with 2.0, 2.1 changes how several classes are inherited in the application to assist in some of the challenges we saw hot fixing Masonite. It also improves some of the quirks with the framework that we noticed devs were doing. If you are coming from 2.0 then be sure to read the &lt;a href="https://docs.masoniteproject.com/v/v2.1/whats-new/masonite-2.1"&gt;What's New - Masonite 2.1&lt;/a&gt; docs as well as the official &lt;a href="https://docs.masoniteproject.com/v/v2.1/upgrade-guide/masonite-2.0-to-2.1"&gt;Upgrade Guide from 2.0 to 2.1&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testimonials and Feedback
&lt;/h2&gt;

&lt;p&gt;Most developers who use the framework have really amazing things to say about it. Some of the feedback I have gotten over the past 6 months include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;René Moser [Nov 21st at 8:03 AM]&lt;/strong&gt;&lt;br&gt;
"really enjoying doing things in Masonite, finally I can make things real"&lt;/p&gt;

&lt;p&gt;When choosing Masonite over Django for a bid for a development contract (which he won):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abram Isola [Sep 20th at 1:55 PM]&lt;/strong&gt;&lt;br&gt;
My deciding factors:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The application has to hook into an existing database with an existing schema AS WELL as manage a database of its own. This almost certainly knocks out Django because of its models. Using masonite allows me to use an ORM (Orator) that is flexible enough for me to access several different databases while managing the schema in only one of them. Huge time save.&lt;/li&gt;
&lt;li&gt;The craft command allows me to generate (or write generators for) most of my code that I'll be doing for them. Huge time save.&lt;/li&gt;
&lt;li&gt;Masonite's folder structure lends itself to the architecture that I've chosen for this project.&lt;/li&gt;
&lt;li&gt;Masonite's release cycle make's it a safe choice for large companies. Upgrading can usually be automated with a simple script. Huge time save. (IDEA: We should build this into craft somehow.)&lt;/li&gt;
&lt;li&gt;Masonite's flexible middleware allows me to very easily manage the levels of access controls that they want in a modular way.&lt;/li&gt;
&lt;li&gt;Masonite's upload drivers allow me to manage the connections to their various upload services very easily.&lt;/li&gt;
&lt;li&gt;I just wanted to do it because I like Masonite better than others&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When talking about Masonite vs their current work software in Django:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dean Raemaekers [Sep 17th at 11:24 AM]&lt;/strong&gt;&lt;br&gt;
What I've built in Masonite so far can do some things that the actual official software can't do. And that was done in a few days.&lt;/p&gt;

&lt;p&gt;and here are some others:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dean Raemaekers [Sep 14th at 1:42 PM]&lt;/strong&gt;&lt;br&gt;
I still like Django but Masonite just has more of a wow factor for me... It's new but it feels so mature&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dean Raemaekers [Sep 12th at 11:51 AM]&lt;/strong&gt;&lt;br&gt;
Wow. I am finished the first part of the app that I wanted to write. That was really quick. Yes, Masonite makes projects quick to develop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caleb Meyer [Aug 20th at 5:26 PM]&lt;/strong&gt;&lt;br&gt;
I've never written any laravel (PHP makes me shudder), but I've been doing ruby and rails for about 5 years now, and this is the first python framework that's made any sense from that perspective.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tony Hammack [Aug 16th at 9:23 PM]&lt;/strong&gt;&lt;br&gt;
I heard your talk on Podcast.&lt;strong&gt;init&lt;/strong&gt; two days ago. I checked out Masonite yesterday, and I ported my Flask app over in under 30 min. It took me 6 hours of figuring out how to get my flask set up and refactor it to get to a production level.&lt;/p&gt;

&lt;p&gt;Although I have gotten better at python, I have to say that this framework is the easiest I have ever worked with. The documentation is so darn helpful. The amount of useful code comments and docstrings is amazing. I hope other packages adopt this strategy. Great job!&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;Out of the box it has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An active record style ORM&lt;/li&gt;
&lt;li&gt;A companion scaffolding CLI tool&lt;/li&gt;
&lt;li&gt;A very explicit IOC container to manage application dependencies&lt;/li&gt;
&lt;li&gt;Built in support for many of the services we all need like Amazon s3 upload and disk support&lt;/li&gt;
&lt;li&gt;Built in support for websockets / Pusher support&lt;/li&gt;
&lt;li&gt;SMTP and Mailgun email support out of the box&lt;/li&gt;
&lt;li&gt;explicit use cases of design patterns. Most developers who use Masonite learn these design patterns and how they are used which naturally makes them learn design patterns in a practical sense and through example and real world scenarios&lt;/li&gt;
&lt;li&gt;Built in database seeding to very quickly seed data into your table&lt;/li&gt;
&lt;li&gt;Built in Queue support for queuing jobs with RabbitMQ and other queue services&lt;/li&gt;
&lt;li&gt;Nearly &lt;strong&gt;600 pages&lt;/strong&gt; of extensive documentation.&lt;/li&gt;
&lt;li&gt;And a whooole lot more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Masonite had an awesome time with the last 2.0 release in June and gained a bit of a following and some awesome contributing community members.&lt;/p&gt;

&lt;p&gt;Here are the main links to check it out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/masoniteframework/masonite"&gt;Main Repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/masoniteframework/core"&gt;Core Repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/masoniteproject"&gt;Twitter Account&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.podcastinit.com/masonite-with-joe-mancuso-episode-174/"&gt;Podcast.init Episode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.masoniteproject.com/v/v2.1/"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/masonite/masonite-and-django-differences-kni"&gt;Django vs Masonite Differences&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>masonite</category>
      <category>python</category>
      <category>framework</category>
    </item>
    <item>
      <title>Masonite and Django Differences</title>
      <dc:creator>Joseph Mancuso</dc:creator>
      <pubDate>Sat, 01 Dec 2018 12:53:14 +0000</pubDate>
      <link>https://dev.to/masonite/masonite-and-django-differences-kni</link>
      <guid>https://dev.to/masonite/masonite-and-django-differences-kni</guid>
      <description>&lt;h1&gt;
  
  
  Masonite and Django
&lt;/h1&gt;

&lt;p&gt;I always get the question of "how does Masonite compare to Django?" or "Why would I choose Masonite over Django?" In this article I'll try to address the many aspects of Masonite and how they compare with Django. This article will likely be an ongoing process of section additions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;Before I start, I am not saying Django is awful. Django is a great framework and it's been going strong in the Python community for a long time. It is clearly here to stay. I personally like pieces of features from other frameworks and enjoy writing in Python so I grabbed tools and tips and architectural concepts from other frameworks and created something that fit my personal use cases perfectly.&lt;/p&gt;

&lt;p&gt;Masonite does things differently and i'll be the first to admit that it's slightly opinionated in the way me and our maintainers code and our developer practices.&lt;/p&gt;

&lt;p&gt;If you try out Masonite and realize that it's a great framework then I hope you continue using it and contribute to the community. If you do not like Masonite and instead think that Django is much better than more power to you; I hope you keep using Django and create some awesome software, although we'll miss you :'(.&lt;/p&gt;

&lt;p&gt;In each section I'll talk more about Masonite than I do Django because I will assume you understand Django already so it's not that I am purposely being biased or explaining only 1 side in more detail than the other. If i mention things like "Settings" I will assume that you understand how Django settings works.&lt;/p&gt;

&lt;p&gt;I'll explain the behind the scenes stuff slightly for Masonite but add links to the documentation if you wish to read more into it and learn how it actually works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thoughts
&lt;/h2&gt;

&lt;p&gt;Masonite is completely developer centric. We try to get a framework with the developer in mind and how the developer will be interacting with the framework on a day to day basis and strive to tweak that interaction in a way that make sense. We focused an entire release dedicated to polishing the tiny things in the framework.&lt;br&gt;
Masonite is not a framework written for a news corporation (Django) or written as an april fools joke (Flask). Although these two frameworks have strived for a long time and remain the two most dominant Python frameworks, Masonite will be an excellent fit and is a framework written for developers by developers.&lt;/p&gt;

&lt;p&gt;Masonite is for those weekend warrior projects that could become something. It's for that next SaaS idea that you want to write but dread writing all the boiler plate involved in getting it to production or uploading to S3 or integrated with Stripe or getting an API setup to get developers to connect to your service or getting recurring tasks setup with cron or all those annoyances that only take a few minutes to setup but you need to setup 10 different packages just to get where you want to be to start developing.&lt;/p&gt;

&lt;p&gt;You KNOW you're going to need whitenoise for static files, you KNOW you're going to need to accept subscriptions with Stripe, you KNOW you're going to need some websocket requests in order to make your application more responsive. Why worry about getting those setup when you can just use a framework that has those for you?&lt;br&gt;
Masonite is the awesome starter project for your next idea all packaged up and waiting to handle your application logic.&lt;/p&gt;
&lt;h1&gt;
  
  
  Architecture
&lt;/h1&gt;

&lt;p&gt;The architecture between Masonite is completely different than that of Django.&lt;br&gt;
Not only does Masonite follow an MVC architecture and Django follows an MTV architecture.&lt;/p&gt;

&lt;p&gt;No, these are not the same. If these were the same then they would be called the same thing. Yes, they both accomplish the exact same thing but they do so in different ways.&lt;/p&gt;
&lt;h2&gt;
  
  
  Django
&lt;/h2&gt;

&lt;p&gt;Django is designed to break a single application into multiple "apps". This is a good architecture for abstracting a lot of logic away for those developers that require it but many developers don't know which parts of their application need to be in separate apps so they start breaking them up until they realize that it simply created more complexity because now I have to know where I put this specific model in order to play nice.&lt;/p&gt;

&lt;p&gt;Django does not have a true MVC architecture. Their architecture as they put it themselves in MTV which is Model Template View.&lt;/p&gt;
&lt;h2&gt;
  
  
  Masonite
&lt;/h2&gt;

&lt;p&gt;Masonite is very different. Masonite is designed to make a single application like Django but it instead breaks up the logic into multiple controllers which are in their own modules.&lt;/p&gt;

&lt;p&gt;Unlike many other Python frameworks, Masonite has a true MVC architecture. Masonite has controller classes and methods that can be used to really abstract away a lot of the business logic in a clean and pragmatic way.&lt;/p&gt;
&lt;h1&gt;
  
  
  Service Container and Service Providers
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Django
&lt;/h2&gt;

&lt;p&gt;Django's version of Masonite's Service Container is their INSTALLED_APPS. Some third party apps require adding an app to the INSTALLED_APPS list which loads features into the framwork. Django uses strings in order for these apps to be loaded in which are located and add features in the app. Some third party packages don't require this.&lt;/p&gt;
&lt;h2&gt;
  
  
  Masonite
&lt;/h2&gt;

&lt;p&gt;Masonite adopted the concept of a Service Container early on. The Service Container is simply a way to add functionality simply to Masonite which is available throughout the application. This is a form of an IOC container into which objects can be put and retrieved into. Masonite takes it a step further and allows objects to be "resolved" by the container. Simply speaking it will determine what your object needs depending on the parameters and retrieve those objects from the container.&lt;/p&gt;



&lt;p&gt;Read more about the &lt;a href="https://docs.masoniteproject.com/architectural-concepts/service-container"&gt;Service Container here&lt;/a&gt;:&lt;/p&gt;



&lt;p&gt;These features are added to Masonite in the form of Service Providers (because they provide a service).&lt;/p&gt;

&lt;p&gt;Service Providers can add functionality like new drivers, new features, entire packages, new commands and a lot more. For example, adding a service provider for Mail could add support for sending emails etc etc.&lt;/p&gt;

&lt;p&gt;These service providers (from 2.0 onwards) are classes which speeds up the time it takes to serve a request because they do not have to be "found" on the backend.&lt;br&gt;
If you are coming from Django, you can think of Service Providers as a form of "adding a thirdparty app to my application." Although apps and service providers perform very differently under the hood, the very high level concept is similiar.&lt;/p&gt;


&lt;h1&gt;
  
  
  Drivers and Settings
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Django
&lt;/h2&gt;

&lt;p&gt;Django uses a few setting files and abstracts them based on where they should run. For example se may have a settings.py and a settings_local.py. This works and is great but I personally never liked adding all of my settings to a single configuration file. It just seemed messy to me but many developers like it which is fine. I would just prefer another abstraction on a feature level. This can also be done in Django by importing all the settings of individual files into the master setting file if you so choose to do it.&lt;/p&gt;

&lt;p&gt;Django doesn't necessarily have a concept of "Drivers" the same way Masonite does but adding these are fairly straight forward for Django. They usually require a pip install and a handful of configuration options.&lt;/p&gt;
&lt;h2&gt;
  
  
  Masonite
&lt;/h2&gt;

&lt;p&gt;Masonite's setting files are broken down into different features of out the box and is something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
  &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
  &lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
  &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can change settings and allow third party application to create them for you.&lt;br&gt;
Masonite also has a concept of drivers. Because of Masonite's architecture, things can be turned on, turned off and switched around at will. If you need a Postgres database connection then you switch from driver from "mysql" to "postgres" which will switch the inner workings of the application to use the Postgres connection. Everything will remain exactly the same but use the other connection.&lt;/p&gt;

&lt;p&gt;Masonite also has several drivers ready to go out of the box such as an SMTP driver and a Mailgun driver for sending email. Masonite uses drivers for several things such as file uploading. We can simply switch drivers like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Upload&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;Upload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'disk'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(..)&lt;/span&gt; &lt;span class="c1"&gt;# stores in the file system
&lt;/span&gt;    &lt;span class="n"&gt;Upload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'s3'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(..)&lt;/span&gt; &lt;span class="c1"&gt;# stores into Amazon S3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can also set default drivers in the configuration file so you don't have to explicitly declare them in your code.&lt;/p&gt;

&lt;p&gt;Because of the concept of Masonite contracts, we can ensure that all classes of the same type have the same methods so we can switch functionality at the drop of a hat and everything will work just fine.&lt;/p&gt;

&lt;p&gt;If you start off a project uploading everything to a disk and then one of your developers say that we should really move to the cloud then that is fine. Either use the drivers supplied with Masonite or create your own driver.&lt;/p&gt;

&lt;h1&gt;
  
  
  Scaffolding
&lt;/h1&gt;

&lt;p&gt;This section is a little opinionated and may or may not be the accepted option of doing things but it is only an option with Masonite and you can skip this completely.&lt;/p&gt;

&lt;p&gt;The concept of "scaffolding" basically means the ability to add boiler plate directly to your code. Making a model or a controller is extremely repetitive.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;create the file&lt;/li&gt;
&lt;li&gt;create the class&lt;/li&gt;
&lt;li&gt;add the first method to it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We do this 100 times in our application. It doesn't take very long at all but its a mild distraction to the task at hand. It only shaves 15-30 seconds off the development time but if you are doing it 100 times then that could be a considerable amount of time shaved off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Django
&lt;/h2&gt;

&lt;p&gt;Django doesn't have the concept of scaffolding at the class level. Django has a way to scaffold a new app but not the ability to scaffold a new model or view or template.&lt;/p&gt;

&lt;p&gt;Masonite takes this a step further&lt;/p&gt;

&lt;h2&gt;
  
  
  Masonite
&lt;/h2&gt;

&lt;p&gt;Masonite adds the ability to create models, controllers and templates (which Masonite calls views to keep with the MVC architecture).&lt;/p&gt;

&lt;p&gt;We have two options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;find our way to the controller directory&lt;/li&gt;
&lt;li&gt;create the file in the controller directory&lt;/li&gt;
&lt;li&gt;create the DashboardController class in the controller file&lt;/li&gt;
&lt;li&gt;add the first method to it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;or we can just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ craft controller Dashboard
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Which will create the file, the class, the first method (which you can obviously rename) and put it in the correct directory for us. It's just the little things in the framework that make it feel really awesome. I use these craft commands all the time.&lt;/p&gt;

&lt;p&gt;Remember you don't need to use craft commands. These are typically just helper commands that allow you to shave a few seconds to a few minutes off your development time that day.&lt;/p&gt;

&lt;h1&gt;
  
  
  Batteries Included
&lt;/h1&gt;

&lt;p&gt;Django and Masonite have a very similar concept of batteries included in terms of features and they can honestly be pretty equal in what they have out of the box but Django needs just a little bit of tweaking for each added feature.&lt;/p&gt;

&lt;p&gt;In this arena, it's not so much the amount of features that separates Masonite and Django but HOW a Masonite developer interacts with the objects in the application. The features between Masonite and Django are very comparable and I won't waste time explaining every feature of Django and how it each one compares with Masonite but you can read the Masonite docs for any information on features you are looking for.&lt;/p&gt;

&lt;p&gt;Any framework can come with features but it's really how we as developers are interacting with those features that really matters. It's the ways and classes we use to interact with these features that really make or break a framework.&lt;/p&gt;

&lt;p&gt;Where Masonite really shines is how it's built and how the application and controllers interacts with the IOC container. This alone is what should really drive a lot of developers to Masonite but it's a little foreign to how we normally develop.&lt;/p&gt;

&lt;p&gt;Once you start interacting with Masonite you can further understand the architecture behind it.&lt;/p&gt;




&lt;h2&gt;
  
  
  You can read more in depth about the architecture in the docs starting with the &lt;a href="https://docs.masoniteproject.com/architectural-concepts/request-lifecycle"&gt;Request Lifecycle&lt;/a&gt;
&lt;/h2&gt;

&lt;h1&gt;
  
  
  The Little Things
&lt;/h1&gt;

&lt;p&gt;Masonite really focuses on the little things when developing and really keeps a "Separation of Concerns" approach really well. Separation of Concerns says that units of code should be broken up in a way where they only perform 1 job or jobs in similar categories.&lt;/p&gt;

&lt;h2&gt;
  
  
  Abstracting Class Methods
&lt;/h2&gt;

&lt;p&gt;Take this example in Django:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;upload_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Some Logic Here To Upload
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;HttpResponseRedirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/success/url/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'success.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'key'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is Django code that shows the form on a GET request and stores the form on a POST request. In Masonite we break this down further into an &lt;code&gt;UploadController&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UploadController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'upload'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'key'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Form Logic Here
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;According to our routes, the url of upload/ will either point to show or store depending on if its a GET or a POST (these method names can be whatever you want them to be)&lt;/p&gt;

&lt;p&gt;So the separation of logic is an awesome perk of Masonite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input Data
&lt;/h2&gt;

&lt;p&gt;Masonite understands the concept of input data well.&lt;br&gt;
Take this example again from above in Django:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;upload_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;firstname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'firstname'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;HttpResponseRedirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/success/url/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'firstname'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'success.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'key'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Notice that we to specify what type of input we need. This was always a strange concept to me and seemed odd.&lt;/p&gt;

&lt;p&gt;Masonite knows the request method and what you need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UploadController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;firstname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'firstname'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# GET
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'upload'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'key'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;firstname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'firstname'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# POST
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Notice the same code here works whether it is a POST request or a GET request.&lt;/p&gt;

</description>
      <category>django</category>
      <category>masonite</category>
      <category>framework</category>
    </item>
    <item>
      <title>Masonite ORM (Orator)</title>
      <dc:creator>Joseph Mancuso</dc:creator>
      <pubDate>Sun, 25 Nov 2018 19:03:11 +0000</pubDate>
      <link>https://dev.to/masonite/masonite-orm-orator-3bh0</link>
      <guid>https://dev.to/masonite/masonite-orm-orator-3bh0</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Nearly every framework comes with come kind of ORM. An ORM is an Object Relational Mapper and is simply a $10 word for a $1 definition. In laymen terms, an ORM is simply a way to interact with a database in an "object" related way. In Python's case, the "object" related way is to use classes. &lt;/p&gt;

&lt;p&gt;Typically, 1 table maps to 1 class so we can interact with our class which in turn interacts with our table. &lt;/p&gt;

&lt;p&gt;We call these classes "Models."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/masoniteframework/masonite" rel="noopener noreferrer"&gt;Masonite&lt;/a&gt; uses the Orator ORM as it's ORM of choice. This ORM may be different than ORM's in the past. If you are coming from any other Python framework than this will be a bit of a new learning experience for you. If you are coming from a framework like Laravel or Ruby on Rails then this ORM will make a lot of sense right off the bat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before you read
&lt;/h2&gt;

&lt;p&gt;Before you start reading, note that we will go into detail here on how the ORM can be used with the Masonite framework and will not be going into detail on how database migrations work. That will need to be it's own article and you can read more about that at Masonite's &lt;a href="https://docs.masoniteproject.com/orator-orm/database-migrations" rel="noopener noreferrer"&gt;Database Migrations&lt;/a&gt; documentation page.&lt;/p&gt;

&lt;p&gt;Once you have your database, migrations and tables setup you can learn how to interact with it using this article here.&lt;/p&gt;

&lt;h1&gt;
  
  
  Configuration
&lt;/h1&gt;

&lt;p&gt;If you have read the migrations documentation then you likely already have the configuration setup but for those who haven't we can go into it here again.&lt;/p&gt;

&lt;p&gt;Configuration is really simple with Masonite. All database configuration files can be found in your &lt;code&gt;.env&lt;/code&gt; file. In this file you will find something that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_DRIVER=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=masonite
DB_USERNAME=root
DB_PASSWORD=root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go ahead and setup any configuration settings you need.&lt;/p&gt;

&lt;h1&gt;
  
  
  MySQL and Postgres
&lt;/h1&gt;

&lt;p&gt;The configuration settings inside the &lt;code&gt;.env&lt;/code&gt; file are good enough for both MySQL and Postgres but you will also need drivers to support your database connection.&lt;/p&gt;

&lt;p&gt;If you are using MySQL you have 2 options:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pip install PyMySQL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pip install mysqlclient
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are using Postgres then you only have 1 option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pip install psycopg2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  SQLite
&lt;/h1&gt;

&lt;p&gt;If you are using SQLite you have a bit more to do. You don't need any drivers but you need to remove some settings from the &lt;code&gt;config/database.py&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Open up that file and there should be a section that looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;DATABASES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;driver&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DB_DRIVER&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DB_HOST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;database&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DB_DATABASE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DB_USERNAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;prefix&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For SQLite we need to remove the &lt;code&gt;host&lt;/code&gt;, &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; options here and make it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;DATABASES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;driver&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DB_DRIVER&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;database&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DB_DATABASE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;prefix&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is because SQLite does not need those options and will throw an exception if found.&lt;/p&gt;

&lt;h1&gt;
  
  
  Usage
&lt;/h1&gt;

&lt;p&gt;Ok great so if you have made it this far then you know how to make migrations by reading the migrations documentation, you know how to configure MySQL or Postgres. Now we just need to know how to access our data in our database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Data
&lt;/h2&gt;

&lt;p&gt;There are a few different ways we can get data from the table. For the purposes of this article we will be using the &lt;code&gt;User&lt;/code&gt; model to generalize everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting by Key
&lt;/h3&gt;

&lt;p&gt;We can get a specific row by it's primary key by using the &lt;code&gt;find()&lt;/code&gt; method which requires the ID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return the record with the primary key of &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting All Records
&lt;/h3&gt;

&lt;p&gt;Theres going to be a lot of times you want to get all records of a table. You can do so like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return a collection of all the results of the table.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting by Value
&lt;/h3&gt;

&lt;p&gt;We can also get by value of a specific column. If using raw SQL this will be analogous to a &lt;code&gt;WHERE&lt;/code&gt; keyword. Maybe not-so-coincidentally, the method is called &lt;code&gt;where&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user@email.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return a collection of results, even if it's a single result. More than once time per day I usually forget to add that little &lt;code&gt;get()&lt;/code&gt; method at the end so make sure you append that method so you actually fetch the result.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting the first record
&lt;/h3&gt;

&lt;p&gt;We can also get the first record in a result which will return an actual model instead of a collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user@email.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return the first result from the collection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aggregate Where
&lt;/h3&gt;

&lt;p&gt;You can use what are called "aggregate methods" which is simply a way to collect a range of values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Plucking values
&lt;/h3&gt;

&lt;p&gt;You can "pluck" values from a collection. In other words you can return a new collection with only the values from the column you plucked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return a new collection with ONLY the emails of these users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where In
&lt;/h3&gt;

&lt;p&gt;You can use a this method to get values where in a list of other values. For example we can get all records who's emails are inside a list we provide:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return all rows where &lt;code&gt;id&lt;/code&gt; is &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is particularly useful while using the &lt;code&gt;pluck&lt;/code&gt; method from above. We can pluck all &lt;code&gt;id&lt;/code&gt; columns from another model. &lt;/p&gt;

&lt;p&gt;We might want to call all posts that have authors that are active for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;active&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code simply gets all users who are active and plucks their ID which returns a collection of ID's which we can then use to pass into the &lt;code&gt;where_in&lt;/code&gt; method to return a new result with only the posts of users who are active.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where Not In
&lt;/h3&gt;

&lt;p&gt;We can do the same thing as above but have code that shows users are are not active by using a different &lt;code&gt;where_not_in&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where_not_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;active&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simply uses the &lt;code&gt;where_not_in&lt;/code&gt; method instead of the &lt;code&gt;where_in&lt;/code&gt; method.&lt;/p&gt;

&lt;h1&gt;
  
  
  Updating information
&lt;/h1&gt;

&lt;p&gt;Once we fetch the information we have it might be useful if we can update that id. There are a few ways to do that which we will go into in this section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update method
&lt;/h2&gt;

&lt;p&gt;We can use the update method to update a row that we fetched:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;new@email.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or we can pass in a dictionary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user-email&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;new@email.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that when we pass in a dictionary, we can use column names that may not be valid Python keyword arguments. That's really the only difference between the two.&lt;/p&gt;

&lt;p&gt;We can also update properties on the model and call the &lt;code&gt;save()&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;new@email.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Updating several records
&lt;/h3&gt;

&lt;p&gt;You might want to update several records at once like updating all users to an active state after a certain action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will run the update on all records found.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updating Timestamps
&lt;/h3&gt;

&lt;p&gt;Sometimes you only want to update a records timestamps. For example you might want to fetch a user but also update the &lt;code&gt;modified_at&lt;/code&gt; timestamp:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;touch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Creating New Records
&lt;/h1&gt;

&lt;p&gt;Creating new records is also really simple. By simply creating a new model instances we can create new records.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating New Records With Properties
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Joe&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name@email.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new record.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating New Records With &lt;code&gt;create&lt;/code&gt; Method
&lt;/h3&gt;

&lt;p&gt;We can use the &lt;code&gt;create&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Joe&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name@email.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deleting
&lt;/h3&gt;

&lt;p&gt;We can also delete records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Relationships
&lt;/h1&gt;

&lt;p&gt;Relationships are extremely simple with Orator. In other Python frameworks you may have specified the foreign key relationship in a class property or class attribute. With Orator you are doing something similar but slightly different.&lt;/p&gt;

&lt;h2&gt;
  
  
  Has One
&lt;/h2&gt;

&lt;p&gt;Let's say we have a foreign key that matches 1 user to 1 desk.&lt;/p&gt;

&lt;p&gt;We can link this relationship inside our model like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;orator.orm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;has_one&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.Desk&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Desk&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="nd"&gt;@has_one&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;desk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Desk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Orator tries to guess what the foreign key's are and it is based on this logic of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# other_table_key, local_key 
&lt;/span&gt;&lt;span class="nd"&gt;@has_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;other_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;table_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and maps the id's to the table names. For example, this would technically be the default values and be exactly the same as the model code above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;orator.orm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;has_one&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.Desk&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Desk&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="nd"&gt;@has_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;desk_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;desk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Desk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code will act the same as the code above. You will likely have to change this though to something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;orator.orm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;has_one&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.Desk&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Desk&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="nd"&gt;@has_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user_desk&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;desk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Desk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will map the local column of &lt;code&gt;user_desk&lt;/code&gt; to the foreign column of &lt;code&gt;id&lt;/code&gt; in the &lt;code&gt;desk&lt;/code&gt; table.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic Properties
&lt;/h2&gt;

&lt;p&gt;We can use this relationship using "dynamic properties". This simply means that logically, you might think you should use the &lt;code&gt;desk()&lt;/code&gt; method as a method but instead you will call it like a property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;desk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;computer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice here that desk is not called by simply accessed like a property.&lt;/p&gt;

&lt;h2&gt;
  
  
  Belongs To
&lt;/h2&gt;

&lt;p&gt;A belongs to relationship defines the inverse of a &lt;code&gt;has_one&lt;/code&gt; relationship. &lt;em&gt;Because it is the inverse of the relationship, we just need to flip the foreign keys&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;orator.orm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;belongs_to&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.Desk&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Desk&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="nd"&gt;@belongs_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user_desk&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;desk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Desk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now the map would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# local_key, other_table_key
&lt;/span&gt;&lt;span class="nd"&gt;@belongs_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;table_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;other_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Has Many
&lt;/h2&gt;

&lt;p&gt;You can also specify a has many relationship the same way. Any given user may have many tasks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;orator.orm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;has_many&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.Task&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="nd"&gt;@has_many&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user_desk&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;desk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now the map would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# other_table_key, local_key
&lt;/span&gt;&lt;span class="nd"&gt;@has_many&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;other_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;table_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can read more about Model relationships if you need a more advanced relationship or more explanation at the &lt;a href="https://orator-orm.com/docs/0.9/orm.html#insert-update-and-delete" rel="noopener noreferrer"&gt;Orator Documentation&lt;/a&gt; page.&lt;/p&gt;

&lt;h1&gt;
  
  
  Circular Dependency
&lt;/h1&gt;

&lt;p&gt;Circular dependencies are not good in Python because it makes 2 classes rely on each other and importing 1 class may not be able to import another class in time and it will throw an exception of not being able to find the class it requires.&lt;/p&gt;

&lt;p&gt;If two models rely on each other you may have a big issue on your hands when it comes to interacting with your models. If you are importing all your models at the top of each model, after a while you will be hit with these circular dependency issues. To get around that when building relationships, you should always lazy import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;orator.orm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;has_many&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="nd"&gt;@has_many&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user_desk&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;desk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.Task&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will alleviate any possibilities to have circular import issues.&lt;/p&gt;

</description>
      <category>python</category>
      <category>masonite</category>
      <category>tutorial</category>
      <category>framework</category>
    </item>
    <item>
      <title>How-To: Use RabbitMQ with Masonite queues</title>
      <dc:creator>Joseph Mancuso</dc:creator>
      <pubDate>Wed, 17 Oct 2018 20:32:11 +0000</pubDate>
      <link>https://dev.to/masonite/how-to-use-rabbitmq-with-masonite-20-queues-4105</link>
      <guid>https://dev.to/masonite/how-to-use-rabbitmq-with-masonite-20-queues-4105</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;This feature requires &lt;a href="https://github.com/MasoniteFramework/masonite" rel="noopener noreferrer"&gt;Masonite&lt;/a&gt; &lt;code&gt;2.0.30 +&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Queues are a fantastic way to keep your application quick and snappy. Anything that does not require a return value and/or is time intensive can be placed in a queue and ran at a later date. Using queues can decrease the time it takes to load pages and increase the user experience. There are many situations where using a queue is beneficial. These include but not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updating arbitrary values in the database when a user signs up (like account login information)&lt;/li&gt;
&lt;li&gt;Sending a welcome or promotion email&lt;/li&gt;
&lt;li&gt;Firing API calls to kick off certain action chains like firing external web-hooks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are many reasons to use message queues. Masonite comes with the default &lt;code&gt;async&lt;/code&gt; queue driver which simply takes a Job and runs it asynchronously. This is beneficial for doing small things like firing an API but still not good for larger tasks that may take several seconds simply because these tasks are simply just using a separate thread and don't have the power and flexibility of a full message queue.&lt;/p&gt;

&lt;p&gt;Alternatively, &lt;a href="https://github.com/MasoniteFramework/masonite" rel="noopener noreferrer"&gt;Masonite&lt;/a&gt; also supports an &lt;code&gt;amqp&lt;/code&gt; driver which is a protocol used by several message queues including the popular RabbitMQ.&lt;/p&gt;

&lt;p&gt;We will go into how to setup RabbitMQ with &lt;a href="https://github.com/MasoniteFramework/masonite" rel="noopener noreferrer"&gt;Masonite&lt;/a&gt; and create some Jobs we can pass to our queue which will process through RabbitMQ&lt;/p&gt;

&lt;h1&gt;
  
  
  Installation
&lt;/h1&gt;

&lt;p&gt;First we will need RabbitMQ locally. In order to do this we will head over to the &lt;a href="https://www.rabbitmq.com/download.html" rel="noopener noreferrer"&gt;installation page and download RabbitMQ&lt;/a&gt; depending on your operating system. Windows will require the installer on that page but if you are using Mac OSX you can simply use &lt;code&gt;brew&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;rabbitmq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Running RabbitMQ
&lt;/h1&gt;

&lt;p&gt;Once installed you can then run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ rabbitmq-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you get something like a command not found then &lt;a href="https://stackoverflow.com/questions/23050120/rabbitmq-command-doesnt-exist" rel="noopener noreferrer"&gt;take a look at this StackOverflow answer&lt;/a&gt;. You may need to add it to your PATH.&lt;/p&gt;

&lt;h1&gt;
  
  
  Configuration
&lt;/h1&gt;

&lt;h2&gt;
  
  
  pip install
&lt;/h2&gt;

&lt;p&gt;First in order to use the &lt;code&gt;amqp&lt;/code&gt; driver successfully you will need to install &lt;code&gt;pika&lt;/code&gt;. This is a lower level &lt;code&gt;amqp&lt;/code&gt; library that Masonite uses to connect to RabbitMQ using the worker and publisher.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Config file
&lt;/h2&gt;

&lt;p&gt;Masonite configuration is simple. In &lt;code&gt;config/queue.py&lt;/code&gt; you will need to set the DRIVER to be &lt;code&gt;amqp&lt;/code&gt; and set some default configuration options in the &lt;code&gt;DRIVERS&lt;/code&gt; constant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;DRIVER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amqp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;DRIVERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amqp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;guest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;guest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;5672&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;channel&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the default setting you need to connect to RabbitMQ locally. RabbitMQ will use the username and password of &lt;code&gt;guest&lt;/code&gt; by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Configuration:
&lt;/h2&gt;

&lt;p&gt;Some RabbitMQ instances, if you are using RabbitMQ with a third party service or in production, may require a &lt;code&gt;vhost&lt;/code&gt; and no port. In this instance our configuration will be a little more advanced:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;DRIVERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amqp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;guest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;vhost&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;guest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;channel&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that &lt;code&gt;port&lt;/code&gt; accepts a value of &lt;code&gt;None&lt;/code&gt; and &lt;code&gt;vhost&lt;/code&gt; can be either left out completely or kept in. &lt;code&gt;/&lt;/code&gt; is the default &lt;code&gt;vhost&lt;/code&gt; but in production systems it may be the same as your username.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the worker
&lt;/h2&gt;

&lt;p&gt;The worker is what sits between your Masonite application and RabbitMQ. This worker will sit and listen for Masonite Jobs and will run them. You should do this in a new terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;craft queue:work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This worker always needs to be running for the duration of your Masonite application in order to process jobs. If this worker is not running then jobs will not be processed. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's important to note that if the worker is not running and Masonite receives a job, it will cache that job and run when the worker starts back up again. This is known as a "durable" queue.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once ran successfully you should see something like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9qk5gxvqadyxk3a7pntr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9qk5gxvqadyxk3a7pntr.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that we are listening on the &lt;code&gt;default&lt;/code&gt; channel. We can specify which channel to listen on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;craft queue:work &lt;span class="nt"&gt;--channel&lt;/span&gt; rabbit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will now listen on the &lt;code&gt;rabbit&lt;/code&gt; channel. Whichever channel we use needs to be the same inside our config file. If we are listening to &lt;code&gt;rabbit&lt;/code&gt;, our channel in our config file needs to be &lt;code&gt;rabbit&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;DRIVERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amqp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;guest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;vhost&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;guest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;channel&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rabbit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating Jobs
&lt;/h2&gt;

&lt;p&gt;Ok great! Now we have RabbitMQ setup and we are listening to jobs that are coming in, Now let's go ahead and make a job. For this we can use craft to scaffold one for us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;craft job HelloWorld
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new job in &lt;code&gt;app/jobs/HelloWorld.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt; A HelloWorld Queue Job &lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;masonite.queues.Queueable&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Queueable&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HelloWorld&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Queueable&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now we have a &lt;code&gt;handle&lt;/code&gt; method which we will put our logic into. We want to pass in a message into our &lt;code&gt;handle&lt;/code&gt; method and print it to the terminal. So we should set this up like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HelloWorld&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Queueable&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="bp"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Seems easy enough. Now let's send this job to the queue!&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending Jobs
&lt;/h2&gt;

&lt;p&gt;First make sure our queue is running. If it is not then run again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;craft&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;work&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to send a job to the queue from our controller, we can use the Queue from the IOC container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.jobs.HelloWorld&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HelloWorld&lt;/span&gt;
&lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HelloWorld&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;world&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;args&lt;/code&gt; will pass in whatever we pass whatever iterable we pass in to the &lt;code&gt;handle&lt;/code&gt; method. We should see inside the terminal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmamr5qb37co7e4k6ozu8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmamr5qb37co7e4k6ozu8.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! You just processed your first Masonite job inside RabbitMQ!&lt;/p&gt;

&lt;h1&gt;
  
  
  Advanced
&lt;/h1&gt;

&lt;p&gt;This section will go a little more in depth into things you may need to know:&lt;/p&gt;

&lt;h2&gt;
  
  
  Constructors
&lt;/h2&gt;

&lt;p&gt;Job constructors are resolved via the container. So we could have put anything we need to in the constructor and it will be resolved from the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;masonite.request&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HelloWorld&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Queueable&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now whenever we push this job it will be resolved:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.jobs.HelloWorld&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HelloWorld&lt;/span&gt;
&lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HelloWorld&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optionally we can also pass in what we need into the constructor. In this case it will &lt;strong&gt;NOT&lt;/strong&gt; be resolved:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.jobs.HelloWorld&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HelloWorld&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;masonite.request&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;
&lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HelloWorld&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Multiple Jobs.
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Queue.push()&lt;/code&gt; accepts multiple jobs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.jobs&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SomeJob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AnotherJob&lt;/span&gt;
&lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# do your normal logic
&lt;/span&gt;    &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SomeJob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;AnotherJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;passing in &lt;code&gt;args&lt;/code&gt; here will pass them into BOTH jobs &lt;code&gt;handle&lt;/code&gt; methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# do your normal logic
&lt;/span&gt;    &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SomeJob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;AnotherJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;var1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;var2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is only useful if both jobs &lt;code&gt;handle&lt;/code&gt; method definitions are the same. If one job requires a different amount of parameters then you will need to send them in 2 different pushes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# do your normal logic
&lt;/span&gt;    &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SomeJob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;var1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;var2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AnotherJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;var1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;var2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;var3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>masonite20</category>
      <category>python</category>
      <category>framework</category>
      <category>masonite</category>
    </item>
  </channel>
</rss>
