<?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: Masonite </title>
    <description>The latest articles on DEV Community by Masonite  (@masonite).</description>
    <link>https://dev.to/masonite</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%2Forganization%2Fprofile_image%2F311%2F96638e0e-efd6-4552-b102-771cbb106978.jpg</url>
      <title>DEV Community: Masonite </title>
      <link>https://dev.to/masonite</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/masonite"/>
    <language>en</language>
    <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>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>Sending automated emails with Masonite Framework</title>
      <dc:creator>Junior Gantin</dc:creator>
      <pubDate>Fri, 02 Nov 2018 12:11:45 +0000</pubDate>
      <link>https://dev.to/masonite/sending-automated-emails-with-masonite-framework-13cc</link>
      <guid>https://dev.to/masonite/sending-automated-emails-with-masonite-framework-13cc</guid>
      <description>&lt;p&gt;Imagine a scenario where you want to send a weekly email to your customers (maybe a newsletter 💌). So you need to send that email at a specific day and time. &lt;/p&gt;

&lt;p&gt;This post will walk through creating and sending automated emails with &lt;a href="https://github.com/MasoniteFramework/masonite" rel="noopener noreferrer"&gt;Masonite Framework&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  What you’ll need
&lt;/h1&gt;

&lt;p&gt;To code along with this post, you’ll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python (I’m using Python 3.6.5);&lt;/li&gt;
&lt;li&gt;Pipenv: Python Development Workflow for Humans;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/MasoniteFramework/masonite" rel="noopener noreferrer"&gt;Masonite&lt;/a&gt;: The Modern And Developer Centric Python Web Framework&lt;/li&gt;
&lt;li&gt;Mailtrap.io: Email testing for dev teams;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Setting up your application
&lt;/h1&gt;

&lt;p&gt;First, create a new directory and a Python virtualenv:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;masonite-weekly-email
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;masonite-weekly-email
&lt;span class="nv"&gt;$ &lt;/span&gt;pipenv &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--three&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;pipenv shell
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, you'll need to install &lt;code&gt;masonite-cli&lt;/code&gt; package and crafting a new &lt;br&gt;
&lt;a href="https://github.com/MasoniteFramework/masonite" rel="noopener noreferrer"&gt;Masonite&lt;/a&gt; application.&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;pipenv &lt;span class="nb"&gt;install &lt;/span&gt;masonite-cli
&lt;span class="nv"&gt;$ &lt;/span&gt;craft new masonite_weekly_email &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;craft &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new Masonite application inside your current directory (the use of &lt;code&gt;.&lt;/code&gt; at the end of &lt;code&gt;craft new&lt;/code&gt; command).&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating and sending an Email
&lt;/h1&gt;

&lt;p&gt;Masonite comes with email support out of the box 🎉. So you can easily send an email 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="n"&gt;Mail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;hello@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;template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mail/welcome&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Task Scheduling
&lt;/h1&gt;

&lt;p&gt;Now that we are done with sending email, let's schedule it. &lt;br&gt;
Masonite provides a package called &lt;a href="https://docs.masoniteproject.com/useful-features/task-scheduling" rel="noopener noreferrer"&gt;&lt;code&gt;masonite-scheduler&lt;/code&gt;&lt;/a&gt;. It enables your app to schedule cron tasks. First, you need to run a command to install the package:&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;pipenv &lt;span class="nb"&gt;install &lt;/span&gt;masonite-scheduler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second command is a &lt;code&gt;craft task&lt;/code&gt; command which will create a new task under the &lt;code&gt;app/tasks&lt;/code&gt; directory.&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 task WeeklyEmail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before running our task weekly, let's run it every 1 minute.&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;scheduler.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;WeeklyEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;run_every&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1 minute&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__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;Mail&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;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="n"&gt;self&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;mail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Build your next SaaS with Masonite 🚀&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;\
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;hello@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;template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mail/weekly&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;\
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Above, you send a email with a template located under &lt;code&gt;mail&lt;/code&gt; folder. Create a file called &lt;code&gt;weekly.html&lt;/code&gt; and put a random text inside.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Hello world!&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://github.com/MasoniteFramework/masonite"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Masonite&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt; is magic. ✨ &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    There are many benefits Masonite brings to your next SaaS project.
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://media.giphy.com/media/3o6Ztqh4JSlVqi2Z20/giphy.gif"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"just do it"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's test this before setting up a cron job. Put your &lt;a href="https://mailtrap.io/" rel="noopener noreferrer"&gt;Mailtrap&lt;/a&gt; credentials into your &lt;code&gt;.env&lt;/code&gt; file and run this command.&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="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;craft&lt;/span&gt; &lt;span class="n"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's Masonite fetch and run your task!&lt;/p&gt;

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

&lt;p&gt;Let's put the right parameters and tell the task when it should run (remember a weekly email).&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;WeeklyEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;run_every&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;7 days&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;run_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;17:00&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Cron Jobs
&lt;/h1&gt;

&lt;p&gt;You need to set up the Cron Jobs to run automatically our tasks. Each crontab line must start with a time at which the command should be run and then the command:&lt;br&gt;
So, to run &lt;code&gt;command&lt;/code&gt; at 17:00 every monday, you'd do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;00 17 * * 1 command
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to append &lt;code&gt;&amp;amp;&amp;amp; craft schedule:run&lt;/code&gt; to run your run the scheduled task.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.masoniteproject.com/useful-features/task-scheduling" rel="noopener noreferrer"&gt;Masonite Task Scheduling&lt;/a&gt; documentation page can provide further information. Just read it ✊!&lt;/p&gt;

&lt;p&gt;If you want to contribute or interested in the development of &lt;a href="https://github.com/MasoniteFramework/masonite" rel="noopener noreferrer"&gt;Masonite&lt;/a&gt; then be sure to join the &lt;a href="http://slack.masoniteproject.com/" rel="noopener noreferrer"&gt;Slack&lt;/a&gt; channel or star the repo on &lt;a href="https://github.com/MasoniteFramework/masonite" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>framework</category>
      <category>masonite</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>
    <item>
      <title>Deploying Masonite to PythonAnywhere</title>
      <dc:creator>Joseph Mancuso</dc:creator>
      <pubDate>Tue, 21 Aug 2018 03:10:31 +0000</pubDate>
      <link>https://dev.to/masonite/deploying-masonite-to-pythonanywhere-26lj</link>
      <guid>https://dev.to/masonite/deploying-masonite-to-pythonanywhere-26lj</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://pythonanywhere.com" rel="noopener noreferrer"&gt;PythonAnywhere&lt;/a&gt; is a way to develop and host your website or any other code directly from your browser without having to install software or manage your own server. It's a very good option if you want to deploy a WSGI application and it has support for Django and Flask right from the start.&lt;/p&gt;

&lt;p&gt;In this article I'll walk through how to get your application setup on an instance of PythonAnywhere.&lt;/p&gt;

&lt;h1&gt;
  
  
  Create an account
&lt;/h1&gt;

&lt;p&gt;This one is simple :). Head over to &lt;a href="https://pythonanywhere.com" rel="noopener noreferrer"&gt;PythonAnywhere&lt;/a&gt; and create a free or paid account. Whichever you want.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Dashboard
&lt;/h1&gt;

&lt;p&gt;Once you login you'll be presented with a dashboard. In the bottom left corner of it you will see a section that looks like this:&lt;/p&gt;

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

&lt;p&gt;Go ahead and click the &lt;code&gt;$bash&lt;/code&gt; link. You'll be presented with a new bash terminal. From here you should pip install the masonite-cli so we can start using craft commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pip3 install masonite-cli --user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure you use the &lt;code&gt;--user&lt;/code&gt; flag because you won't have sudo privileges inside this bash shell.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting Up The Directory
&lt;/h1&gt;

&lt;p&gt;Let's go ahead and create some directories we'll be using for this project. We might want our PythonAnywhere instance be able to serve multiple applications so let's make a "sites" directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /var/www/sites
~ &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /var/www/sites
/var/www/sites &lt;span class="nv"&gt;$ &lt;/span&gt;&amp;lt;we should now be here&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We make a sites directory because this might contain a structure where we can put multiple websites like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/sites
  masonite/
  tutorial/
  blog/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Installing Masonite
&lt;/h1&gt;

&lt;p&gt;If you just want to install a fresh application then you can go ahead and follow the normal &lt;a href="https://masoniteproject.com" rel="noopener noreferrer"&gt;documentation for installing a new application&lt;/a&gt;. But for this tutorial we will talk about how to install an application directly from github.&lt;/p&gt;

&lt;p&gt;For the convenience, we'll actually be installing a new application for Masonite but via the github repository and not the &lt;code&gt;craft new&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;So head over to your github account and copy the github link. In this case we will be using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://github.com/MasoniteFramework/masonite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure you are in the sites directory and git clone your repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/var/www/sites &lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://github.com/MasoniteFramework/masonite
Cloning into &lt;span class="s1"&gt;'masonite'&lt;/span&gt;...
remote: Counting objects: 1898, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Compressing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;57/57&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
...
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! So now our repository is cloned. Doing a quick &lt;code&gt;ls&lt;/code&gt; command should return a new file with our new repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/var/www/sites &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls
&lt;/span&gt;masonite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Virtual Environment
&lt;/h1&gt;

&lt;p&gt;PythonAnywhere promotes the idea of putting your dependencies in a virtual environment (which is good practice). So let's get our virtual environment setup which is really easy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/var/www/sites &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;masonite
/var/www/sites/masonite &lt;span class="nv"&gt;$ &lt;/span&gt;virtualenv &lt;span class="nt"&gt;-p&lt;/span&gt; python3 venv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice we did a &lt;code&gt;cd&lt;/code&gt; into our freshly created masonite project and created a virtual environment. This command is using &lt;code&gt;python3&lt;/code&gt; (the &lt;code&gt;virtualenv&lt;/code&gt; defaults to Python 2.7 and Masonite requires 3.4+). The &lt;code&gt;venv&lt;/code&gt; at the end is the name of our virtual environment. Name that whatever you want.&lt;/p&gt;

&lt;h1&gt;
  
  
  Installing dependencies
&lt;/h1&gt;

&lt;p&gt;Great. So now let's install our dependencies. First we will need to activate our virtual environment and then run the &lt;code&gt;craft install&lt;/code&gt; command like we normally do.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/var/www/sites/masonite &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
&lt;span class="o"&gt;(&lt;/span&gt;venv&lt;span class="o"&gt;)&lt;/span&gt; /var/www/sites/masonite &lt;span class="nv"&gt;$ &lt;/span&gt;craft &lt;span class="nb"&gt;install
&lt;/span&gt;Collecting &lt;span class="nv"&gt;waitress&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;1.1.0 &lt;span class="o"&gt;(&lt;/span&gt;from &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt &lt;span class="o"&gt;(&lt;/span&gt;line 1&lt;span class="o"&gt;))&lt;/span&gt;
  Using cached https://files.pythonhosted.org/packages/ee/af/ac32a716d64e56561ee9c23ce45ee2865d7ac4e0678b737d2f5ee49b5fd6/waitress-1.1.0-py2.py3-non
e-any.whl
Collecting masonite&amp;lt;&lt;span class="o"&gt;=&lt;/span&gt;2.0.99,&amp;gt;&lt;span class="o"&gt;=&lt;/span&gt;2.0 &lt;span class="o"&gt;(&lt;/span&gt;from &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt &lt;span class="o"&gt;(&lt;/span&gt;line 2&lt;span class="o"&gt;))&lt;/span&gt;
Collecting python-dotenv&lt;span class="o"&gt;==&lt;/span&gt;0.8.2 &lt;span class="o"&gt;(&lt;/span&gt;from masonite&amp;lt;&lt;span class="o"&gt;=&lt;/span&gt;2.0.99,&amp;gt;&lt;span class="o"&gt;=&lt;/span&gt;2.0-&amp;gt;-r requirements.txt &lt;span class="o"&gt;(&lt;/span&gt;line 2&lt;span class="o"&gt;))&lt;/span&gt;
  Using cached https://files.pythonhosted.org/packages/85/9f/b76a51bb851fa25f7a162a16297f4473c67ec42dd55e4f7fc5b43913a606/python_dotenv-0.8.2-py2.py
3-none-any.whl
...
...
Key added to your .env file: &lt;span class="nv"&gt;1KmdwFryf71PGKYm6NBoFXRHHlqqE0&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let those dependencies install. If installed successfully you will get a green message saying a key was appended to your &lt;code&gt;.env&lt;/code&gt; file. Great. Now let's get out of this bash shell and on to adding our application to the PythonAnywhere dashboard.&lt;/p&gt;

&lt;h1&gt;
  
  
  Adding Our Web App
&lt;/h1&gt;

&lt;p&gt;Go back to the dashboard and in the upper right hand side we will see a tab called "Web" like this:&lt;/p&gt;

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

&lt;p&gt;Click on that and click on "Add New Web App":&lt;/p&gt;

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

&lt;p&gt;You'll want to click on "Manual Configuration" at the bottom of the list.&lt;/p&gt;

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

&lt;p&gt;and then click on "Python 3.6":&lt;/p&gt;

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

&lt;p&gt;Once that is done click "Next" and you should be presented with a new dashboard specific to your app.&lt;/p&gt;

&lt;h1&gt;
  
  
  Configuring Your Web App
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Code Section
&lt;/h2&gt;

&lt;p&gt;If you scroll down on this new web app dashboard you'll see a "Code" section:&lt;/p&gt;

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

&lt;p&gt;Remember that we put our app in a &lt;code&gt;/var/www/sites/&amp;lt;your_project&amp;gt;&lt;/code&gt; directory so let's add that to both the source code and working directory like this image above.&lt;/p&gt;

&lt;p&gt;Now we need to edit the &lt;code&gt;wsgi.py&lt;/code&gt; file. I'm not entirely sure why they don't just default to the one in the source code but oh well. Click on that "Wsgi configuration file" link which will open up an editor.&lt;/p&gt;

&lt;p&gt;We'll have to copy and paste our &lt;code&gt;wsgi.py&lt;/code&gt; file into this code. Since we're using git we can grab it right from our GitHub repo. If you made no modifications to your &lt;code&gt;wsgi.py&lt;/code&gt; file you can use the default one here: &lt;a href="https://github.com/MasoniteFramework/masonite/blob/master/wsgi.py" rel="noopener noreferrer"&gt;https://github.com/MasoniteFramework/masonite/blob/master/wsgi.py&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The final product should look something like this:&lt;/p&gt;

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

&lt;p&gt;&lt;em&gt;Make sure you click save in the upper right hand corner&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Virtualenv Section
&lt;/h2&gt;

&lt;p&gt;Scroll down a bit on the web app dashboard and you should see a new section for virtual environments. We just need to tell PythonAnywhere where we created our virtual environment. Remember we just made a &lt;code&gt;venv&lt;/code&gt; directory in our project directory. So let's just append on a &lt;code&gt;venv&lt;/code&gt; to the directory we've been adding:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Success!
&lt;/h2&gt;

&lt;p&gt;That's it! Now let's just go up to the top of the page and reload the application:&lt;/p&gt;

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

&lt;p&gt;Once that's done we can view it using the link right above it that looks something like ".pythonanywhere.com". This will open up our web app!&lt;/p&gt;

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