<?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>Forem: Ivan Neto</title>
    <description>The latest articles on Forem by Ivan Neto (@ivancrneto).</description>
    <link>https://forem.com/ivancrneto</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F5798%2F0946a96b-3942-49d1-88e5-97369b5a2527.jpeg</url>
      <title>Forem: Ivan Neto</title>
      <link>https://forem.com/ivancrneto</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ivancrneto"/>
    <language>en</language>
    <item>
      <title>Eastern European Developers: Which Country to Choose for Your Project</title>
      <dc:creator>Ivan Neto</dc:creator>
      <pubDate>Thu, 27 Feb 2020 21:59:55 +0000</pubDate>
      <link>https://forem.com/ivancrneto/eastern-european-developers-which-country-to-choose-for-your-project-bga</link>
      <guid>https://forem.com/ivancrneto/eastern-european-developers-which-country-to-choose-for-your-project-bga</guid>
      <description>&lt;p&gt;Over the last decades, Eastern Europe has managed to become one of the top offshore destinations in the world. It all started with tech giants such as Microsoft, IBM, Apple, and Google, who opened their branches in Eastern European countries. Their example inspired the other tech companies, who saw the benefits of outsourcing to Central and Eastern Europe (CEE).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://clutch.co/developers/eastern-europe"&gt;According to Clutch&lt;/a&gt;, there are almost 2,000 offshore software development companies in this region as of January 2020. Almost 700 firms thereof are based in Ukraine, more than 600 – in Poland, and 274 – in Romania. In this article, we are going to give an overview of these top 3 locations and compare them according to various criteria. We will also find out why clients from the US and Western European countries prefer Eastern Europe as the number one offshore destination.&lt;/p&gt;

&lt;h2&gt;
  
  
  Top Destinations for Software Development in Eastern Europe
&lt;/h2&gt;

&lt;p&gt;As we've already mentioned, the most popular Eastern European countries to outsource software development are Ukraine, Poland, and Romania. Now we'll give an overview of the IT industry in each of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Poland
&lt;/h3&gt;

&lt;p&gt;Poland is an EU country with a rapidly growing economy. IT services in Poland generate over 29% jobs in the Polish labor market, as per the "&lt;a href="https://absl.pl/storage/app/uploads/public/5d0/7a1/406/5d07a140668f0191663458.pdf"&gt;Business Services Sector in Poland 2019&lt;/a&gt;" report by ABSL. This fact makes Poland one of the most favorable offshore destinations in Eastern Europe, together with other facts and statistics, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Polish IT industry grows by 5-10% a year.&lt;/li&gt;
&lt;li&gt;According to &lt;a href="https://community.topcoder.com/stat?c=country_avg_rating"&gt;Top Coder ranking&lt;/a&gt;, Poland now occupies the 5th place in the world as per software development skills.&lt;/li&gt;
&lt;li&gt;In 2018, the number of IT professionals employed at outsourcing companies was &lt;a href="https://itsg-global.com/it-industry-in-poland/"&gt;about 45,000&lt;/a&gt; as related to the total talent pool size of over 250,000.&lt;/li&gt;
&lt;li&gt;In 2019, the &lt;a href="https://www.statista.com/forecasts/961402/it-revenue-in-poland"&gt;IT market revenue in Poland&lt;/a&gt; amounted to $11.79 billion. According to predictions, the revenue will grow up to $12.1 billion in 2020 and $12.1 billion in 2021.&lt;/li&gt;
&lt;li&gt;By 2022, sales of IT services in the country are expected to reach $15 billion.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Romania
&lt;/h2&gt;

&lt;p&gt;Being also a member of the EU, Romania features one of the fastest growing IT markets in Central and Eastern Europe. The country is sixth in the world according to the number of certified IT specialists, specifically, about 100,000. Here are some more facts about this offshore destination:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In 2003, &lt;a href="https://www.networkworld.com/article/2334189/microsoft-to-buy-romanian-antivirus-company.html"&gt;Microsoft acquired Romanian antivirus technology&lt;/a&gt; by GeCAD Software.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The IT market in Romania grows at about 40–60% a year.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The most rapidly growing segment of the IT market is offshore software development, with up to $4.2 billion in total revenues.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HackerRank challenges showed that Romania is the 20th country in the world having the best developers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;185,00 professionals are employed in the IT industry.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ukraine
&lt;/h3&gt;

&lt;p&gt;Here are some of the &lt;a href="https://ain.ua/en/2019/08/30/ukrainian-it-industry-2019-2020/"&gt;recent statistics&lt;/a&gt; about the state of the IT industry in Ukraine.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Currently, about 4,000 IT companies operate on the market.&lt;/li&gt;
&lt;li&gt;As of 2019, there were about 160,000 IT professionals in Ukraine, over 60% of which work for outsourcing companies, mainly from the United States. It is predicted that in 2020, the number of &lt;a href="https://youteam.co.uk/blog/software-developers-in-ukraine-their-location-mentalities-and-personalities/"&gt;software developers in Ukraine&lt;/a&gt; will increase by 20,000.&lt;/li&gt;
&lt;li&gt;Ukrainian IT industry grows by about 26% a year.&lt;/li&gt;
&lt;li&gt;As per forecasts by experts, revenues in the Ukrainian IT industry amounted to $5 billion in 2019.&lt;/li&gt;
&lt;li&gt;Ukraine is 20th in the &lt;a href="https://www.kearney.com/digital-transformation/gsli?utm_source=PRNewswire&amp;amp;utm_medium=pr&amp;amp;utm_term=DT&amp;amp;utm_campaign=2019GSLI&amp;amp;utm_content="&gt;T. Kearney's 2019 Global Services Location Index&lt;/a&gt; (GSLI). The country has moved up 4 positions as compared with 2017.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The average score across all HackerRank challenges as of 2018 showed that Ukraine is &lt;a href="https://blog.hackerrank.com/wp-content/uploads/2016/08/Screen-Shot-2016-08-23-at-8.42.39-AM.png"&gt;the world's 11th country having the best developers&lt;/a&gt;. According to this data, Ukrainian developers had an average score of 88.7% across all challenges.&lt;/li&gt;
&lt;li&gt;In 2017, Ukraine was awarded the "Outsourcing Destination of the Year" by the Global Sourcing Association.&lt;/li&gt;
&lt;li&gt;Grammarly, Preply, and Petcube come from Ukraine.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Software Developers in Eastern Europe: Comparison
&lt;/h2&gt;

&lt;p&gt;Now let's compare the software development potential in the top 3 CEE countries by using criteria such as English skills, tech ranks, hourly rates, size of the talent pool, industry focus, and core technologies.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;English skills. In general, IT professionals in all three countries are fluent in English. According to a &lt;a href="https://www.daxx.com/blog/outsourcing-ukraine/why-ukraine-best-it-outsourcing-destination"&gt;survey by Daxx&lt;/a&gt;, 80% of Ukrainian developers speak English. 33% of them have the upper-intermediate level whereas 35% have the intermediate level. As per &lt;a href="https://www.ef.com/wwen/epi/regions/europe/poland/"&gt;EF English Proficiency Index&lt;/a&gt;, Poland is #11 of 100 countries/regions and #9 in Europe in terms of English proficiency, being ranked as "very high proficiency". The same index shows that Romania occupies the 16th and 14th places, accordingly, being ranked as "high proficiency."&lt;/li&gt;
&lt;li&gt;Tech ranks. Among the three countries, Poland has the best tech rank both on HackerRank (3rd place) and TopCoder (5th place).&lt;/li&gt;
&lt;li&gt;Hourly rates. According to PayScale, average hourly rates for the three countries are roughly the same - $16 per hour. It is greater than in India or the Philippines, but still much lower than in the US or Western Europe.&lt;/li&gt;
&lt;li&gt;Size of the talent pool. Poland remains the leader in terms of the talent pool size of over 250,000, which amounts to &lt;a href="https://youteam.co.uk/blog/offshore-software-development-in-poland-developer-s-perspective/"&gt;ne fourth&lt;/a&gt; of the total population of programmers in the CEE.&lt;/li&gt;
&lt;li&gt;Industry focus. Each country has its own IT industry focus, which makes it easier for clients to choose the preferred destination. Ukrainian IT companies specialize in startups, custom software development, and eCommerce. Polish developers tend to focus on enterprise projects whereas Romanian ones – on fintech projects.&lt;/li&gt;
&lt;li&gt;Core technologies. The annual survey of Ukrainian software engineers by DOU, a local online community for IT professionals, shows that Java is the most popular programming language in Ukraine, followed by JavaScript, C#, PHP, and Python. A similar rating by &lt;a href="https://bulldogjob.com/it_report_2019"&gt;Bulldogjob&lt;/a&gt; in Poland shows that the top 5 most popular technologies are JavaScript, Java, C++, SQL, and C#. As for &lt;a href="https://hostadvice.com/marketshare/language/ro/"&gt;Romania&lt;/a&gt;, the leaders are PHP, ASP.NET, Python, Java, and Perl. As we can see, Java is popular in all three countries whereas PHP is popular in Ukraine and Romania. Apart from this, the set of core languages and technologies is quite diverse.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Outsource Software Development to Eastern Europe?
&lt;/h2&gt;

&lt;p&gt;The final section of our article is dedicated to the advantages of &lt;a href="https://youteam.co.uk/blog/developers-in-eastern-europe-which-country-suits-your-project/"&gt;offshore software development in Eastern Europe&lt;/a&gt;, which are also the reasons why clients choose this destination.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technology Stack
&lt;/h3&gt;

&lt;p&gt;Technical education has been important in Eastern Europe ever since the times of the Soviet Union. However, during those times, the universities focused mostly on hardware than on software. Today, the focus has been shifted from hardware to software in response to modern market requirements, thus gradually turning Eastern Europe into one of the world's most popular offshore software development hubs. Tens of thousands of certified IT specialists graduate from Eastern European universities every year, expanding the vast talent pool of this outsourcing destination.&lt;/p&gt;

&lt;h3&gt;
  
  
  Foreign Language Proficiency
&lt;/h3&gt;

&lt;p&gt;Fluent English is one of the key requirements for work in the outsourcing IT industry. It is the preferred language for communication between international teams and successful cooperation with clients. Many Eastern European IT companies offer free English courses for co-workers on their premises, thus contributing to the improvement of this important skill. Additionally, Polish developers speak fluent German and Romanian developers – fluent French. Clients from the United States and Western Europe enjoy working with teams from these countries because there's no language barrier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Self-Education
&lt;/h3&gt;

&lt;p&gt;With the lightning-fast development of modern technology, self-education is crucial for IT professionals so they can always stay up to date with the latest trends. With this purpose, Eastern European developers constantly attend various conferences, both internal and external, and listen to online courses and webinars. All expenses are typically covered by employers. And these efforts are worth it -developers from Poland, Ukraine, and Romania rank highly on both HackerRank and TopCoder.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Eastern European developers offer quite affordable rates as compared to their Western peers. The highest rates are in Poland — $50-$99/hour, but it is still lower than in Western Europe. The lowest prices are in Moldova — $20-$24/hour.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cultural Value Set
&lt;/h3&gt;

&lt;p&gt;Despite once belonging to the former Soviet Union, the culture of software developers in the CEE countries can be defined as western and progressive. Most developers are young people with an open mindset.  Ukrainian and Polish developers have decades of experience working with global technology companies in Europe and other countries. At the same time, Romanians can sometimes lack an innovative approach because they may be reluctant to take risks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Size of Talent Pool
&lt;/h3&gt;

&lt;p&gt;The main reason why tech companies from the United States and Western Europe choose outsourcing is the lack of talent pool in their area. High-speed Internet and modern technologies allow employing people from all over the world even on a remote basis. The abundance of highly skilled, open minded, English speaking professionals at fair prices makes Eastern Europe an IT outsourcing paradise.&lt;/p&gt;

&lt;p&gt;The total number of IT professionals in the region is 700,000 people employed at 2,000 companies, and this number is growing because of 60,000 IT graduates appearing every year. Each country focuses on specific technologies, offering potential clients a diverse set of various technologies to choose from. For example, Romanian developers are well versed in fintech, Poland focuses on enterprise solutions, and Ukrainian developers work with the most cutting-edge technologies, such as artificial intelligence or blockchain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which Country Is the Best for You?
&lt;/h2&gt;

&lt;p&gt;Every client has their own project requirements, but each CEE country has its own specifics. Therefore, the best recommendation here is to choose a country based on those requirements. You may find Poland or Romania more reliable because of EU membership, but these countries may lack specialists in the technology stack that you need for your project. So, here are our recommendations on making the right choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Know your budget. Average hourly rates in CEE countries can be roughly the same, but they can vary for senior-level developers. Therefore, we recommend that you look up the rates of software engineers per country and choose the one that is best for your budget.&lt;/li&gt;
&lt;li&gt;Have a clear understanding of the tech stack needed for your project. Each Eastern European country has its own strengths regarding the tech skills of local software engineers. For example, HackerRank reports that Polish engineers are the first in Java whereas Ukrainian developers are the first in security.&lt;/li&gt;
&lt;li&gt;Choose according to the type of your company. If you're a startup, you can reach out to Ukrainian developers. If you're a large enterprise, Poland would be your choice, and so on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And remember: it doesn't matter which country you choose for outsourcing software development. Companies in those countries can also be different, so we advise that you thoroughly pre-screen the company of your choice, preferably with the help of local specialists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Eastern Europe is an attractive outsourcing destination due to several reasons such as broad technology stack, English language proficiency, affordable rates, size of the talent pool, and cultural value set. The most popular outsourcing destinations in CEE are Ukraine, Poland, and Romania. It is possible to not only open an offshore development center in one of those countries but also build a remote team.&lt;/p&gt;

&lt;h3&gt;
  
  
  Find remote developers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youteam.io/"&gt;YouTeam&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.toptal.com#book-tested-programmers"&gt;Toptal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>remote</category>
      <category>market</category>
      <category>offshore</category>
    </item>
    <item>
      <title>YouTube API Integration: Uploading Videos with Django</title>
      <dc:creator>Ivan Neto</dc:creator>
      <pubDate>Thu, 27 Sep 2018 16:02:30 +0000</pubDate>
      <link>https://forem.com/ivancrneto/youtube-api-integration-uploading-videos-with-django-53c5</link>
      <guid>https://forem.com/ivancrneto/youtube-api-integration-uploading-videos-with-django-53c5</guid>
      <description>&lt;p&gt;A short while ago, I was working for a client, integrating video reviews in their website. Like any motivated developer solving a novel problem, the first thing I did was Google it, and I found a plethora of unhelpful or misguided answers on how to achieve something entirely different, or outdated and unmaintained Python packages. Eventually, I bit the bullet and the team and I built everything from scratch: we created the views, learned about Google’s API, created the API client, and eventually succeeded in programmatically uploading videos from Django.&lt;/p&gt;

&lt;p&gt;In this post, I’ll try to guide you step by step in how to post YouTube videos from your Django app. This will require a bit of playing around with Google API credentials—first with the web interface, then with the code. The YouTube part itself is very straightforward. We need to understand how Google stuff works because sometimes it’s tricky and the information is spread through many places.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;I recommend familiarizing yourself with the following before we begin working:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/youtube/v3/quickstart/python" rel="noopener noreferrer"&gt;YouTube Data API: Python Quickstart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/youtube/v3/docs/" rel="noopener noreferrer"&gt;YouTube Data API: API Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/youtube/v3/code_samples/" rel="noopener noreferrer"&gt;YouTube Data API: Code Samples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/api-client-library/python/" rel="noopener noreferrer"&gt;Google Python API Client Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/api-client-library/python/reference/pydoc" rel="noopener noreferrer"&gt;Google Python API Client Library: Reference Doc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/google/google-api-python-client/blob/master/samples/README.md" rel="noopener noreferrer"&gt;Google Python API Client Library: Code Samples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/youtube/api-samples/tree/master/python" rel="noopener noreferrer"&gt;YouTube API: Python Code Samples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An interesting bit of code to note is the following Python Snippet from the &lt;a href="https://developers.google.com/youtube/v3/docs/videos/insert" rel="noopener noreferrer"&gt;Google YouTube API Docs&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# Sample python code for videos.insert
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;videos_insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;media_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# See full sample for function
&lt;/span&gt;  &lt;span class="n"&gt;kwargs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;remove_empty_kwargs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# See full sample for function
&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;videos&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;media_body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;MediaFileUpload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;media_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunksize&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                               &lt;span class="n"&gt;resumable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# See full sample for function
&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;resumable_upload&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;video&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;insert&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;media_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sample_video.flv&lt;/span&gt;&lt;span class="sh"&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;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;media_file&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Please specify a valid file location.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;videos_insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&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;snippet.categoryId&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;22&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;snippet.defaultLanguage&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;snippet.description&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;Description of uploaded video.&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;snippet.tags[]&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;snippet.title&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;Test video upload&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;status.embeddable&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status.license&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status.privacyStatus&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;private&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;status.publicStatsViewable&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="n"&gt;media_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;snippet,status&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;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;After you’ve read the prerequisites, it’s time to get started. Let’s see what we need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Toolbelt
&lt;/h3&gt;

&lt;p&gt;Basically, let’s create a virtual environment. I personally prefer &lt;a href="https://github.com/pyenv/pyenv" rel="noopener noreferrer"&gt;pyenv&lt;/a&gt;. Setting up both is out of the scope of this post, so I’m going to post some pyenv commands below and, if your preference is &lt;code&gt;virtualenv&lt;/code&gt;, feel free to replace the commands accordingly.&lt;/p&gt;

&lt;p&gt;I’m going to use Python 3.7 and Django 2.1 in this post.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜  ~/projects &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;django-youtube
➜  ~/projects &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;django-youtube
➜  ~/projects/django-youtube &lt;span class="nv"&gt;$ &lt;/span&gt;pyenv virtualenv 3.7.0 djangoyt
➜  ~/projects/django-youtube &lt;span class="nv"&gt;$ &lt;/span&gt;vim .python-version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        djangoyt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Installing dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜  ~/projects/django-youtube &lt;span class="nv"&gt;$ &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;google-api-python-client google-auth&lt;span class="se"&gt;\&lt;/span&gt;
 google-auth-oauthlib google-auth-httplib2 oauth2client Django unipath jsonpickle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now time to start our django project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜  ~/projects/django-youtube &lt;span class="nv"&gt;$ &lt;/span&gt;django-admin startproject django_youtube &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pause for some Google Config.
&lt;/h2&gt;

&lt;p&gt;Let’s config our project credentials now so we are able to use the Google APIs.&lt;/p&gt;

&lt;p&gt;Step 1. Go to the following URL: &lt;a href="https://console.developers.google.com/apis/library/youtube.googleapis.com" rel="noopener noreferrer"&gt;https://console.developers.google.com/apis/library/youtube.googleapis.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 2. Create a New Project.&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%2Fqia5363b26v9tqgyz09e.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%2Fqia5363b26v9tqgyz09e.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step3. Click "Enable APIs and Services."&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%2F2nw39v3h767r1t8ch76q.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%2F2nw39v3h767r1t8ch76q.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step4. Look for Youtube Data API v3, click "Enable."&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%2Fuol2oo9s5gqpuufn8uf3.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%2Fuol2oo9s5gqpuufn8uf3.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 5. You should get a message about credentials.&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%2Fc3ghsorvh53ej95kfgv0.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%2Fc3ghsorvh53ej95kfgv0.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 6. Click on the "Create credentials" blue button on the right side, and you should get the following screen:&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%2Fketgq0ubfrijjx0tgq2v.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%2Fketgq0ubfrijjx0tgq2v.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 7. Choose Web server, User Data&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%2Fxrjljcb8caj2gsa2u4ka.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%2Fxrjljcb8caj2gsa2u4ka.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 8. Add authorized JS origins and redirect URIs. Continue to the end.&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%2Fe6hpsl8jd6jqznbvo66m.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%2Fe6hpsl8jd6jqznbvo66m.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OK we are done with our credentials set up. You can either download the credentials in a JSON format or copy the &lt;em&gt;Client ID&lt;/em&gt; and &lt;em&gt;Client Secret&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to Django
&lt;/h2&gt;

&lt;p&gt;Let’s start our very first Django app. I usually name it “core”:&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="o"&gt;(&lt;/span&gt;djangoyt&lt;span class="o"&gt;)&lt;/span&gt; ➜  ~/projects/django-youtube &lt;span class="nv"&gt;$ &lt;/span&gt;python manage.py startapp core

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

&lt;/div&gt;



&lt;p&gt;Now, let’s add the following to our root urls.py file to route the homepage requests to our core app:&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;# urls.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;include&lt;/span&gt;


    &lt;span class="nf"&gt;path&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="nf"&gt;include&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;core.urls&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;core&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;core&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;In the core app, let’s have another urls.py file, with some config also:&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;# core/urls.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.conf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.conf.urls.static&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.views&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HomePageView&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&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="n"&gt;HomePageView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;home&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STATIC_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;document_root&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STATIC_ROOT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MEDIA_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;document_root&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MEDIA_ROOT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See there is an empty path pointing to &lt;code&gt;HomePageView&lt;/code&gt;. Time to add some code.&lt;/p&gt;

&lt;p&gt;Let’s do now a simple &lt;code&gt;TemplateView&lt;/code&gt; just to see it running.&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;# core/views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.shortcuts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.views.generic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TemplateView&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HomePageView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TemplateView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;template_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;core/home.html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And of course we need a basic template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;# core/templates/core/home.html
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;My First Heading&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My first paragraph.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to do some settings tweaks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# settings.py
&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;unipath&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="c1"&gt;# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
&lt;/span&gt;&lt;span class="n"&gt;BASE_DIR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;


&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;# [...]
&lt;/span&gt;    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;core&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="n"&gt;STATIC_ROOT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BASE_DIR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;staticfiles&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;STATIC_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/static/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;


&lt;span class="n"&gt;MEDIA_ROOT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BASE_DIR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;uploads&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;MEDIA_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/media/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's create now a &lt;code&gt;YoutubeForm&lt;/code&gt; and add as &lt;code&gt;form_class&lt;/code&gt; to the view:&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;django&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;forms&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.views.generic.edit&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FormView&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;YouTubeForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Form&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;class&lt;/span&gt; &lt;span class="nc"&gt;HomePageView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FormView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;template_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;core/home.html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;form_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;YouTubeForm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try to run your application now, and the page will look like this:&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%2Fdjpzc0k4joac4vb9lrcs.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%2Fdjpzc0k4joac4vb9lrcs.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pause to do Authorization
&lt;/h3&gt;

&lt;p&gt;First of all, you have to create a model to store your credentials. You could to through a file, cache system, or any other storage solution, but a database seems reasonable and scalable, and also you can store credentials per users if you want.&lt;/p&gt;

&lt;p&gt;Before proceeding, an adjustment needs to be made—there is fork of oauth2client that supports Django 2.1 that we have to use. Soon, we’ll have official support, but in the meantime, you can inspect the fork changes. They are very simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; git://github.com/Schweigi/oauth2client.git@v4.1.3#egg&lt;span class="o"&gt;=&lt;/span&gt;oauth2client
&lt;span class="c"&gt;# Because of compatibility with Django 2.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go to your &lt;code&gt;settings.py&lt;/code&gt; and place the &lt;em&gt;Client ID&lt;/em&gt; and &lt;em&gt;Client Secret&lt;/em&gt; you got from Google in previous steps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# settings.py
&lt;/span&gt;
&lt;span class="n"&gt;GOOGLE_OAUTH2_CLIENT_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;your client id&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;GOOGLE_OAUTH2_CLIENT_SECRET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;your client secret&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Caution:&lt;/em&gt; storing secrets in your code is not recommended. I’m doing this simply as a demonstration. I recommend using environment variables in your production app, and not hardcoding secrets in application files. Alternatively, if you downloaded the JSON from Google, you can also specify its path instead of the settings 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="n"&gt;GOOGLE_OAUTH2_CLIENT_SECRETS_JSON&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/path/to/client_id.json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The oauth2client package already provides plenty of functionality, with a CredentialsField already done that we can use. It’s possible to add more fields, like a foreign key and created/modified dates so we get more robust, but let’s stay simple.&lt;/p&gt;

&lt;p&gt;Simple model to store credentials:&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;# core/models.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;oauth2client.contrib.django_util.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CredentialsField&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CredentialsModel&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;credential&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CredentialsField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Time to create migrations and migrate:&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="o"&gt;(&lt;/span&gt;djangoyt&lt;span class="o"&gt;)&lt;/span&gt; ➜  ~/projects/django-youtube &lt;span class="nv"&gt;$ &lt;/span&gt;./manage.py makemigrations core
&lt;span class="o"&gt;(&lt;/span&gt;djangoyt&lt;span class="o"&gt;)&lt;/span&gt; ➜  ~/projects/django-youtube &lt;span class="nv"&gt;$ &lt;/span&gt;./manage.py migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s change our API views to be able to authorize our application:&lt;/p&gt;

&lt;p&gt;In our &lt;code&gt;core/urls.py&lt;/code&gt; file, let’s add another entry for the first authorization view:&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;# core/urls.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.views&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AuthorizeView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HomePageView&lt;/span&gt;


&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;# [...]
&lt;/span&gt;    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;authorize/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AuthorizeView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;authorize&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;So first part of the AuthorizeView will 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;# core/views.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.conf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.shortcuts&lt;/span&gt; &lt;span class="kn"&gt;import&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;redirect&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.views.generic.base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;View&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;oauth2client.client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;flow_from_clientsecrets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OAuth2WebServerFlow&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;oauth2client.contrib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;xsrfutil&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;oauth2client.contrib.django_util.storage&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DjangoORMStorage&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CredentialsModel&lt;/span&gt;

&lt;span class="c1"&gt;# [...]
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthorizeView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;View&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DjangoORMStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;CredentialsModel&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;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="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;credential&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;credential&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;storage&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="n"&gt;flow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OAuth2WebServerFlow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;client_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GOOGLE_OAUTH2_CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;client_secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GOOGLE_OAUTH2_CLIENT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://www.googleapis.com/auth/youtube&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;redirect_uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8888/oauth2callback/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# or if you downloaded the client_secrets file
&lt;/span&gt;        &lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;flow = flow_from_clientsecrets(
            settings.GOOGLE_OAUTH2_CLIENT_SECRETS_JSON,
            scope=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://www.googleapis.com/auth/youtube&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;,
            redirect_uri=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8888/oauth2callback/&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then second part:&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;if&lt;/span&gt; &lt;span class="n"&gt;credential&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;invalid&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;flow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xsrfutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SECRET_KEY&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="n"&gt;authorize_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step1_get_authorize_url&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authorize_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So if there is no credential or the credential is invalid, generate one and then redirect it to the authorize URL. Otherwise, just go to the homepage so we can upload a video!&lt;/p&gt;

&lt;p&gt;Let’s access the view now and see what happens:&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%2F1pfxeq50chhxh3a0hebh.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%2F1pfxeq50chhxh3a0hebh.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s create a user then, before going to that page.&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="o"&gt;(&lt;/span&gt;djangoyt&lt;span class="o"&gt;)&lt;/span&gt; ➜  ~/projects/django-youtube &lt;span class="nv"&gt;$ &lt;/span&gt;python manage.py createsuperuser

Username &lt;span class="o"&gt;(&lt;/span&gt;leave blank to use &lt;span class="s1"&gt;'ivan'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;: ivan
Email address: ivan&lt;span class="k"&gt;***&lt;/span&gt;@mail.com
Password:
Password &lt;span class="o"&gt;(&lt;/span&gt;again&lt;span class="o"&gt;)&lt;/span&gt;:
This password is too short. It must contain at least 8 characters.
Bypass password validation and create user anyway? &lt;span class="o"&gt;[&lt;/span&gt;y/N]: y
Superuser created successfully.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s also log in with it via &lt;code&gt;/admin&lt;/code&gt;. After, let’s access our &lt;code&gt;/authorize/&lt;/code&gt; view again.&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%2F38by08tj2pngg47d00tu.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%2F38by08tj2pngg47d00tu.png"&gt;&lt;/a&gt;&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%2F2hftmrnqwcyr8ryjpi1u.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%2F2hftmrnqwcyr8ryjpi1u.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then,&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%2F0fguhm74sffrebd81nmf.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%2F0fguhm74sffrebd81nmf.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OK, it tried to redirect to the callback URL we configured long ago with Google. Now we need to implement the callback view.&lt;/p&gt;

&lt;p&gt;Let’s add one more entry to our &lt;code&gt;core/urls.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# core/urls.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.views&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AuthorizeView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HomePageView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Oauth2CallbackView&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;# [...]
&lt;/span&gt;    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;oauth2callback/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Oauth2CallbackView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
         &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;oauth2callback&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;And another view:&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;# core/views.py
&lt;/span&gt;

&lt;span class="c1"&gt;# the following variable stays as global for now
&lt;/span&gt;&lt;span class="n"&gt;flow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OAuth2WebServerFlow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;client_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GOOGLE_OAUTH2_CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;client_secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GOOGLE_OAUTH2_CLIENT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://www.googleapis.com/auth/youtube&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;redirect_uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8888/oauth2callback/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# or if you downloaded the client_secrets file
&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;flow = flow_from_clientsecrets(
    settings.GOOGLE_OAUTH2_CLIENT_SECRETS_JSON,
    scope=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://www.googleapis.com/auth/youtube&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;,
    redirect_uri=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8888/oauth2callback/&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="c1"&gt;# [...]
&lt;/span&gt;

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

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;xsrfutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SECRET_KEY&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="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;state&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;encode&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="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;HttpResponseBadRequest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;credential&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step2_exchange&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;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DjangoORMStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;CredentialsModel&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;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="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;credential&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: The flow was moved to outside of the &lt;code&gt;AuthorizeView&lt;/code&gt;, becoming global. Ideally, you should create it under the &lt;code&gt;AuthorizeView&lt;/code&gt; and save in a cache, then retrieve it in the callback. But that is out of the scope of this post.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The get method of AuthorizeView is now:&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;get&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DjangoORMStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;CredentialsModel&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;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="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;credential&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;credential&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;storage&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;credential&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;invalid&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;flow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xsrfutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SECRET_KEY&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="n"&gt;authorize_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step1_get_authorize_url&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authorize_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can take a look at similar implementations here. The &lt;code&gt;oauth2clien&lt;/code&gt; package itself provides views but I particularly prefer to implement my custom Oauth view.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/google/google-api-python-client/blob/master/samples/django_sample/plus/views.py" rel="noopener noreferrer"&gt;https://github.com/google/google-api-python-client/blob/master/samples/django_sample/plus/views.py&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/google/oauth2client/blob/master/oauth2client/contrib/django_util/views.py" rel="noopener noreferrer"&gt;https://github.com/google/oauth2client/blob/master/oauth2client/contrib/django_util/views.py&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now if you try the &lt;code&gt;/authorize/&lt;/code&gt; URL again, the OAuth flow should work. Time to see if this work is worth it and upload our video! The HomePageView will first check for credentials and if it’s all good, we are ready for uploading our video.&lt;/p&gt;

&lt;p&gt;Let’s check how our new code for the &lt;code&gt;HomePageView&lt;/code&gt; will look:&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;import&lt;/span&gt; &lt;span class="n"&gt;tempfile&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.http&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HttpResponseBadRequest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;googleapiclient.discovery&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;googleapiclient.http&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MediaFileUpload&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HomePageView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FormView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;template_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;core/home.html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;form_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;YouTubeForm&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;form_valid&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;form&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;fname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cleaned_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;video&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;temporary_file_path&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DjangoORMStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;CredentialsModel&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;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="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;credential&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;credentials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;storage&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="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;youtube&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;v3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;credentials&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;body&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;snippet&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;title&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;My Django Youtube Video&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;description&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;My Django Youtube Video Description&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;tags&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;django,howto,video,api&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;categoryId&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;27&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;status&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;privacyStatus&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;unlisted&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="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NamedTemporaryFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;wb&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;suffix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;yt-django&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;tmpfile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fileobj&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;tmpfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileobj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                &lt;span class="n"&gt;insert_request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;videos&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="o"&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="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
                    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;media_body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;MediaFileUpload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;tmpfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunksize&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resumable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;insert_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;It worked!&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 the template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;# core/templates/core/home.html

        &lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Upload your video&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Here is the form:&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"."&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt; &lt;span class="na"&gt;enctype=&lt;/span&gt;&lt;span class="s"&gt;"multipart/form-data"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        { csrf_token }
        \{\{ form.as_p \}\}
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to add the video field to YouTubeForm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class YouTubeForm(forms.Form):
    video = forms.FileField()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we go!&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%2F9w7nlkyfmawiy64oe7a8.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%2F9w7nlkyfmawiy64oe7a8.png"&gt;&lt;/a&gt;&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%2Fhjm9q0z1gmnybcc0kyyg.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%2Fhjm9q0z1gmnybcc0kyyg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Voila!&lt;/p&gt;

&lt;h3&gt;
  
  
  Closing Notes
&lt;/h3&gt;

&lt;p&gt;The code needs some improvement, but it’s a good starting point. I hope it helped with most of the Google’s YouTube API Integration problems. Here are a few more important things to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For authorization, it’s important to require login and extra permissions for the user that will authorize your application to be uploading videos.&lt;/li&gt;
&lt;li&gt;The flow variable needs to be moved out from being global. It isn’t safe in a production environment. It’s better to cache based on the user ID or session who accessed the first view, for instance.&lt;/li&gt;
&lt;li&gt;Google only provides a refresh token when you do the first authorization. So after some time, mostly one hour, your token will expire and if you didn’t interact with their API you will start receiving invalid_grant responses. Reauthorizing the same user who already authorized a client will not guarantee your refresh token. * You have to revoke the application in your Google Accounts page and then do the authorization process again. In some cases, you might need to run a task to keep refreshing the token.&lt;/li&gt;
&lt;li&gt;We need to require login in our view since we are using a user credential directly related to the request.&lt;/li&gt;
&lt;li&gt;There is a work in progress based on this experience and this post. Of course there is a lot to be added, but it’s a good starting point: &lt;a href="https://github.com/ivancrneto/youtube-django" rel="noopener noreferrer"&gt;https://github.com/ivancrneto/youtube-django&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&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%2Fs1r6istovdehyhzn2hd2.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%2Fs1r6istovdehyhzn2hd2.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Uploading takes a lot of time, and doing it in your main application process can cause the entire application to block while the upload happens. The right way would be to move it into its own process and handle uploads asynchronously.&lt;/p&gt;

&lt;p&gt;The code needs some improvement, but it's a good starting point. I hope it helped with most of the Google's API handling and of course uploading your video to YouTube!&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>showdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What I have learned from eight years of being a remote developer</title>
      <dc:creator>Ivan Neto</dc:creator>
      <pubDate>Sun, 10 Jun 2018 19:04:51 +0000</pubDate>
      <link>https://forem.com/ivancrneto/what-i-have-learned-from-eight-years-of-being-a-remote-developer-3eob</link>
      <guid>https://forem.com/ivancrneto/what-i-have-learned-from-eight-years-of-being-a-remote-developer-3eob</guid>
      <description>&lt;p&gt;I enjoy working remotely. There are many advantages such as not having to commute to an office; having more time with my family and myself; being in a reserved workspace which helps with concentration and boosts productivity; being able to travel more often, having flexible work hours and the list grows.&lt;/p&gt;

&lt;p&gt;For people who don't work remotely or have a home office (&lt;a href="https://www.quora.com/What-is-the-difference-between-remote-work-telecommuting-and-a-home-office"&gt;https://www.quora.com/What-is-the-difference-between-remote-work-telecommuting-and-a-home-office&lt;/a&gt;), it sounds like we are privileged. Most of my friends' jobs are not suitable to be remote one day and many consider remote jobs as dream jobs. &lt;/p&gt;

&lt;p&gt;It's often difficult to see the hitches related to remote work. What I want with this post is not to give tips on how to handle to work properly, how to find remote work or how to purchase the proper equipment for that, but to show through my experience one face of it that is not easily perceptible. Only after some time you are capable to note details that make remote work amazing and are surprised by others that are extremely hard to anticipate when starting.&lt;/p&gt;

&lt;p&gt;Let's see...&lt;/p&gt;

&lt;h3&gt;
  
  
  No perfection
&lt;/h3&gt;

&lt;p&gt;“Do you work remotely? Do you work at home? Oh, that must be perfect!”&lt;/p&gt;

&lt;p&gt;No, it's not perfect. Everything has advantages and disadvantages.&lt;/p&gt;

&lt;p&gt;“Working remotely is bad, you don't have anyone to talk, you are mostly alone.”&lt;/p&gt;

&lt;p&gt;Every choice you make has the good and the bad side. During the working hours, you are probably isolated (and this is not 100% true), but it's a matter of choice to not be when not working.&lt;/p&gt;

&lt;h3&gt;
  
  
  No dogs
&lt;/h3&gt;

&lt;p&gt;This is a joke, of course. What I mean is, make sure you are in a peaceful environment, mainly if you have to do many video calls. Ensure there are zero chances of a neighbor dog barking in your background while you have to talk. I had this experience and someone complained, it's frustrating.&lt;/p&gt;

&lt;h3&gt;
  
  
  Really, no dogs
&lt;/h3&gt;

&lt;p&gt;If you need to move, do. Maybe a soundproofing office? I'm not kidding. When you are working remotely, you have to take it seriously. Once I had to talk in a meeting and I couldn't. I missed a golden opportunity. Having to keep muting yourself because of some random unexpected noise hurts and might determine your next career step.&lt;/p&gt;

&lt;p&gt;This means you need to choose carefully the place you live, the people around you, to guarantee you are able to work when you need to be in a silent place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Split the office if possible
&lt;/h3&gt;

&lt;p&gt;If you live in a house, it's not a bad idea to consider a small garden between it and the room you use for the office. That induces a psychological state of “leaving home” and “entering the office” and the opposite. For me, it works to perfection.&lt;/p&gt;

&lt;p&gt;One of the big problems remote workers have is not setting boundaries between work and home and mixing everything.&lt;/p&gt;

&lt;p&gt;I'd say the same for the office format. I don't like making my bedroom as an office or my office as a bedroom. No beds. Just office furniture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Family
&lt;/h3&gt;

&lt;p&gt;Many think you are not working! You are at home, aren't you? They knock the door, make random requests, the phone rings, as does the bell, the postman arrives, and they request you to receive the package, they shout “food is ready” when you are in a meeting.&lt;/p&gt;

&lt;p&gt;They need to learn, as well as you do. You need to have a conversation with them a couple of times to make them understand. Or they do, or you'll end up renting a room or going to a co-working space every day.&lt;/p&gt;

&lt;p&gt;The most difficult thing is teaching them are not at home. You are only at home after you leave the office room. That's the hardest.&lt;/p&gt;

&lt;h3&gt;
  
  
  Internet
&lt;/h3&gt;

&lt;p&gt;When you start working by yourself, you start simple, of course. Then after a couple of years, you see yourself charging three times more, leading teams, working on big projects.&lt;/p&gt;

&lt;p&gt;How do you feel about saying something like “hey, I'm not working today because I have no internet connection?” A contract with two ISPs and also a mobile 4G/5G connection as a backup is mandatory for me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Equipment
&lt;/h3&gt;

&lt;p&gt;So I have a &lt;em&gt;Nobreak&lt;/em&gt;. Because if I have no power, I can stay up for eight hours and still work. I checked to make sure my two ISPs used different links and even if there was a general power outage, my mobile provider would stay up (because it's a national one) then I could keep working.&lt;/p&gt;

&lt;p&gt;Once, we had the experience of losing the first 30 min of an hourly meeting to set up a microphone. It's bad when you have to do the same for another one. Don't ever allow that to happen twice!&lt;/p&gt;

&lt;p&gt;I have backup headphones. Once, I had the experience of not having an extra pair, my main ones broke and my sound naturally had a lot of echoes. It was very difficult for anyone to understand me. People complained, of course.&lt;/p&gt;

&lt;p&gt;Another essential topic is your furniture. If you do videos, it's crucial to have good furniture, to show you are in an office or at least show some professionalism. Additionally, they add to your physical (ergonomic means fewer doctors and medicine in the future) and psychological (work/home split) states.&lt;/p&gt;

&lt;h3&gt;
  
  
  Computers
&lt;/h3&gt;

&lt;p&gt;Two computers as well are also good to have. One to keep at home, one for traveling, or going to events, or to keep safe until the first one breaks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bed is not for working, pajamas neither
&lt;/h3&gt;

&lt;p&gt;I don't like to work when in my bed. It activates me. I have problems trying to sleep later. There is a similar situation if I try to work when wearing pajamas. I'm still trying to get up and don't make progress fast enough. That's the same splitting problem. I need clothes to work and clothes to stay at home. They don't need to be better, just slightly different. Tell your brain when you are in your bed, it's not working time. And when you are using pajamas, it's still not working time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dropbox
&lt;/h3&gt;

&lt;p&gt;A Dropbox (or similar) account. What if you go on vacation, don't bring your computer and there is a critical bug in production? Only Dropbox and any PC saves you. Or be terribly sad with your early trip back home to fix that bug.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clients
&lt;/h3&gt;

&lt;p&gt;Regarding clients, I have observed a curious behavior. As they don't see you, some think you are a robot 24/7 living inside the chat app. Of course (and I keep saying that, because it's important to emphasize), everything depends on your relation to them, and whether you work alone and deliver your stuff later or work with a team and need to be online for a couple of hours.&lt;/p&gt;

&lt;p&gt;It's fundamental to work with good clients, be very selective as the time goes, and make sure they have experience with remote work. There are many situations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It's a one-to-one relationship, where you work on a project for a single person;&lt;/li&gt;
&lt;li&gt;A company with many remote contractors;&lt;/li&gt;
&lt;li&gt;A company with everyone on-site and you are the only one remote;&lt;/li&gt;
&lt;li&gt;You are an employee and works partially remotely and partially on-site;&lt;/li&gt;
&lt;li&gt;You own a company and have many people and companies as clients.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No matter what situation you are, some clients want to reach out anytime. Many do not realize there is a real person outside of the chat platform and you should not allow them to ask you to do long demanding tasks when you are about to leave or at non-sense times like after 8, 9 pm or before 6 am. Of course, downtime and critical bugs happen. But we need to set boundaries and say “no, it's after 5 pm” (or 6 pm or whatever the time you stop), let's continue tomorrow. That's totally fine. Once agreed beforehand, mostly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Still Clients
&lt;/h3&gt;

&lt;p&gt;You miss the day-to-day of your client. So... you don't take the pressure the on-site guys take. You need to have a way to know something is important, so it's important to be constantly pairing with your on-site peer.&lt;/p&gt;

&lt;p&gt;Another thing is off and on if the company has an on-site team and a remote team, they tend to not give the right value the remote team deserves. They don't see the remotes working, so you have to find another way to build up trust. Again, over communicate and keep mentioning what you are doing, one or two times a day doesn't hurt. Another idea is to improve a bit the company's process to use documents because it's easier to just people talk to each other in the office and not pass the information to the remote folks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Organization
&lt;/h3&gt;

&lt;p&gt;One of the most fundamental problems of working remotely is organization. It's OK to not be much organized at the beginning. But after some time your own body starts to ask for that.&lt;/p&gt;

&lt;p&gt;Not only your body, actually, but your family, friends, and every other aspect of your life. You need a routine, the proper times for eating, waking up, starting and stopping working. The more you so the same activities at the same time every day the better.&lt;/p&gt;

&lt;p&gt;We tend to forget we are working and don't stop. Or procrastinate, play PS4 too much and don't work. Another very essential point, at least to me, is clothes. As I said above, I need wearing “work” clothes and “home” clothes. This tells my brain I'm in a working or home state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Track time
&lt;/h3&gt;

&lt;p&gt;Tracking time is the best way to help with organization, and also will help with estimating future features. The tracking tools can provide fascinating reports about the time spent in a feature, talking to a person, etc. Besides allowing you to not lose when you should stop working and take some rest, this is a valuable information that can help you in the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  Health
&lt;/h3&gt;

&lt;p&gt;Following the previous topic, there is a constant need for equilibrium, so let me mention here doing something without a computer is very important. Every remarkable person we know implements that.&lt;/p&gt;

&lt;p&gt;If we found it boring, we should keep searching until we encounter something fun. I always hated the gym. Bought a bike, a guitar, and Muay Thai gloves and those are working for me.&lt;/p&gt;

&lt;p&gt;Family time, friends, contact with nature, everything helps.&lt;/p&gt;

&lt;p&gt;Why am I saying all that? Remember we are working remotely, most of the time alone, so it's straightforward to lose track of the world and just stay at home all over the month. A plan of action of how to stay in balance is required, so we can perform our best in our job and also give the deserved attention to family and friends, our body, mind, and health in general.&lt;/p&gt;

&lt;h3&gt;
  
  
  Communication
&lt;/h3&gt;

&lt;p&gt;Overcommunication is the key, IMHO. If you have a productivity app like Slack to talk to other devs or members of the project, make sure to explicitly say when you start, leave for lunch or do other things and stop.&lt;/p&gt;

&lt;p&gt;If you work isolated and the communication is typically after some days and/or via email, make sure to keep sending emails, following up, asking for answers, send information in advance before being asked, etc.&lt;/p&gt;

&lt;p&gt;If you are between asking or not, ask. Never assume someone knows about something. Most of the conflicts that happen in a remote environment are due to the lack of communication.&lt;/p&gt;

&lt;p&gt;I'm still working on this, that's the part, after eight years, I'm not so good at. If I have to rate my communication, I'd say it's 85 out of 100. I need it to be 110 or 120, then I am sure I will be over communicating enough to avoid any problems or confusion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final words
&lt;/h3&gt;

&lt;p&gt;Of course, many situations here really depend on the kind of job you have. If you merely perform your tasks and work mostly alone or asynchronously, it's OK to be in noisy environments for instance. If you are an employee working at home, that's completely different. When you participate in meetings, pair programming, lots of planning and video with coworkers, you need a different setup.&lt;/p&gt;

&lt;p&gt;I hope this post could help not only the ones that want to start working remotely, but also everyone involved in the remote world, and if you have any question or disagree with anything, I'm happy to talk :)&lt;/p&gt;

&lt;p&gt;Thanks so much.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Thanks &lt;a href="https://twitter.com/rtimoshenko"&gt;Ron Timoshenko&lt;/a&gt; and &lt;a href="https://jadehopper.com/about/"&gt;Niqui Merret&lt;/a&gt; for their opinions and experiences about remote work, which contributed to making this post better.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;p&gt;Over here are some valuable resources about remote work:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.toptal.com/freelance/how-to-work-remotely-and-still-be-the-best/#book-tested-programmers"&gt;https://www.toptal.com/freelance/how-to-work-remotely-and-still-be-the-best/#book-tested-programmers&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.toptal.com/remote/staying-healthy-while-working-remotely/#book-tested-programmers"&gt;https://www.toptal.com/remote/staying-healthy-while-working-remotely/#book-tested-programmers&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.paymoapp.com/blog/working-remotely/"&gt;https://www.paymoapp.com/blog/working-remotely/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://youteam.io/blog/remote-development-team-guide/"&gt;https://youteam.io/blog/remote-development-team-guide/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://youteam.io/blog/guide-to-hiring-remote-team-of-software-developers/"&gt;https://youteam.io/blog/guide-to-hiring-remote-team-of-software-developers/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://x-team.com/blog/10-secrets-to-becoming-a-great-remote-developer/"&gt;https://x-team.com/blog/10-secrets-to-becoming-a-great-remote-developer/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://auth0.com/blog/21-tips-for-remote-working/"&gt;https://auth0.com/blog/21-tips-for-remote-working/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://blog.codinghorror.com/on-working-remotely/"&gt;https://blog.codinghorror.com/on-working-remotely/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/lefebvre/what-ive-learned-after-working-remotely-for-10-years-384j"&gt;https://dev.to/lefebvre/what-ive-learned-after-working-remotely-for-10-years-384j&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.codementor.io/learn-programming/8-tips-to-become-an-effective-remote-developer"&gt;https://www.codementor.io/learn-programming/8-tips-to-become-an-effective-remote-developer&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.deekit.com/11-things-about-remote-work/"&gt;https://www.deekit.com/11-things-about-remote-work/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://medium.com/swlh/effective-tips-for-working-remotely-23cc290a8c08"&gt;https://medium.com/swlh/effective-tips-for-working-remotely-23cc290a8c08&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.wordstream.com/blog/ws/2017/06/16/working-remotely"&gt;https://www.wordstream.com/blog/ws/2017/06/16/working-remotely&lt;/a&gt;&lt;br&gt;
&lt;a href="https://skillcrush.com/2017/06/05/remote-work-from-home-skills/"&gt;https://skillcrush.com/2017/06/05/remote-work-from-home-skills/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://skillcrush.com/2016/10/10/working-remotely-tips/"&gt;https://skillcrush.com/2016/10/10/working-remotely-tips/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://blog.trello.com/company-remote-work-myths"&gt;https://blog.trello.com/company-remote-work-myths&lt;/a&gt;&lt;br&gt;
&lt;a href="https://news.ycombinator.com/item?id=16482351"&gt;https://news.ycombinator.com/item?id=16482351&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Finding remote work
&lt;/h3&gt;

&lt;p&gt;Below is a list of places to find remote work:&lt;/p&gt;

&lt;p&gt;Toptal - &lt;a href="https://www.toptal.com/#book-tested-programmers"&gt;https://www.toptal.com/#book-tested-programmers&lt;/a&gt;&lt;br&gt;
Hackhands - &lt;a href="https://hackhands.com/"&gt;https://hackhands.com/&lt;/a&gt;&lt;br&gt;
Remote OK - &lt;a href="https://remoteok.io/"&gt;https://remoteok.io/&lt;/a&gt;&lt;br&gt;
Upwork - &lt;a href="https://www.upwork.com/"&gt;https://www.upwork.com/&lt;/a&gt;&lt;br&gt;
BairesDev - &lt;a href="https://www.bairesdev.com/"&gt;https://www.bairesdev.com/&lt;/a&gt;&lt;br&gt;
AngelList - &lt;a href="https://angel.co/"&gt;https://angel.co/&lt;/a&gt;&lt;br&gt;
Remote.com - &lt;a href="https://remote.com/"&gt;https://remote.com/&lt;/a&gt;&lt;br&gt;
Codementor - &lt;a href="https://www.codementor.io/"&gt;https://www.codementor.io/&lt;/a&gt;&lt;br&gt;
Indeed - &lt;a href="https://www.indeed.com/jobs?q=developer&amp;amp;l=remote"&gt;https://www.indeed.com/jobs?q=developer&amp;amp;l=remote&lt;/a&gt;&lt;br&gt;
Dice - &lt;a href="https://www.dice.com/jobs?q=&amp;amp;l=remote"&gt;https://www.dice.com/jobs?q=&amp;amp;l=remote&lt;/a&gt;&lt;br&gt;
Vibbra (PT-BR) - &lt;a href="http://www.vibbra.com.br/"&gt;http://www.vibbra.com.br/&lt;/a&gt;&lt;br&gt;
Torre Jobs - &lt;a href="https://torre.jobs"&gt;https://torre.jobs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>remote</category>
      <category>beginners</category>
      <category>remotelife</category>
    </item>
    <item>
      <title>Hi, I'm Ivan. I grew my career while working remotely since 2010, I love knowledge sharing and helping starters. AMA!</title>
      <dc:creator>Ivan Neto</dc:creator>
      <pubDate>Fri, 18 May 2018 14:53:25 +0000</pubDate>
      <link>https://forem.com/ivancrneto/hi-im-ivan-i-could-grow-my-career-while-working-remotely-since-2010-i-love-knowledge-sharing-and-helping-starters-ama-21ne</link>
      <guid>https://forem.com/ivancrneto/hi-im-ivan-i-could-grow-my-career-while-working-remotely-since-2010-i-love-knowledge-sharing-and-helping-starters-ama-21ne</guid>
      <description></description>
      <category>ama</category>
    </item>
    <item>
      <title>What I'd like to hear from an experienced developer when I was a beginner</title>
      <dc:creator>Ivan Neto</dc:creator>
      <pubDate>Fri, 04 May 2018 05:53:09 +0000</pubDate>
      <link>https://forem.com/ivancrneto/what-id-like-to-hear-from-an-experienced-developer-when-i-was-a-beginner-438g</link>
      <guid>https://forem.com/ivancrneto/what-id-like-to-hear-from-an-experienced-developer-when-i-was-a-beginner-438g</guid>
      <description>&lt;p&gt;When we are just students, getting our first jobs, many questions come to mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What programming language should I learn?&lt;/li&gt;
&lt;li&gt;Should I pursue a more scientific oriented career?&lt;/li&gt;
&lt;li&gt;What are the types of jobs related to the technology I want to work on?&lt;/li&gt;
&lt;li&gt;Where to work? What kind of company? &lt;/li&gt;
&lt;li&gt;What has changed recently?&lt;/li&gt;
&lt;li&gt;And many others...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Such questions are normal and healthy at that time. We have to make a lot of personal and professional decisions during life. In this post, I will show decisions I made, my opinion about key issues and share some interesting cases that happened to me. Things I'd like to hear when I started.&lt;/p&gt;

&lt;h3&gt;
  
  
  Programming Languages
&lt;/h3&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%2Fiij1oh3kmlsgc7vpz0ha.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiij1oh3kmlsgc7vpz0ha.png" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is indeed one of the most asked questions. Should I learn Java? Python? C? Ruby? JavaScript? XYZ? Should I learn all languages in the world?&lt;/p&gt;

&lt;h4&gt;
  
  
  Do languages matter?
&lt;/h4&gt;

&lt;p&gt;Short answer: No.&lt;/p&gt;

&lt;p&gt;Fair answer: Yes and no. They matter to learn their differences, paradigms, how they implement object orientation, design patterns, how they deal with memory and the OS. After some time, they are merely tools that you learn how to use in one day or two. You'll probably stick with one, work a bit with another, and have fun with two more. In the end, it's just a matter of choosing the right one for the appropriate job.&lt;/p&gt;

&lt;p&gt;A couple of years ago I learned Python and a friend of mine, Java. He got a job quickly, and I didn't. I genuinely liked Python and he chose Java in order to find jobs. I could get a very good job and enjoyed it. If I had quit, it would have been difficult to find another one, though. His job wasn't that good, but he could quickly find another job. There is an inevitable trade-off.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technologies
&lt;/h3&gt;

&lt;p&gt;What I'd say about technologies is about the same, but as soon as you narrow down your knowledge to some area, there are categories we could easily fit each of the ones we'd want to learn. They represent essentially technologies that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We work with;&lt;/li&gt;
&lt;li&gt;are related to the ones we work with;&lt;/li&gt;
&lt;li&gt;complement it;&lt;/li&gt;
&lt;li&gt;we just want to play around with them;&lt;/li&gt;
&lt;li&gt;we find an opportunity to learn them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As a web developer, I worked with Python language, Django framework as related technology, MySQL, PostgreSQL, Redis, JavaScript to complement my work. That was typically my stack. I played around with Swift because I wanted to learn iOS development and I had an outstanding opportunity with Pyramid.&lt;br&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%2Fu81t95ao861fdwqx45zs.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu81t95ao861fdwqx45zs.png" width="255" height="72"&gt;&lt;/a&gt;&lt;br&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%2Fsl1e6mzp5g7lcocm34by.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsl1e6mzp5g7lcocm34by.png" width="510" height="198"&gt;&lt;/a&gt;&lt;br&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%2Ffcbmxsvke10d50q06dtc.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffcbmxsvke10d50q06dtc.png" width="256" height="104"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Opportunities
&lt;/h3&gt;

&lt;p&gt;One of the most significant things about a professional is its rarity. Technologies play a critical role regarding the transition between keeping looking for jobs and being disputed by companies.&lt;/p&gt;

&lt;p&gt;There are many Python developers around. Not so many with experience in OpenCV and OCR related technologies. In a certain company, there was a chance to work on a modest project to detect dirty and broken walls in a room. The dev chose to work on it so now she remains as part of this group.&lt;/p&gt;

&lt;p&gt;Whenever I have the chance to grasp something new or do things others devs refuse to, I'm very inclined to do so. The consequences of accomplishing that are often extraordinary. Once I learned a legacy system only one guy maintained and when he went on vacation I could take over. Bit by bit, I took the "legacy system maintenance" role from him so he was finally released to do more important stuff and I became essential as well. When we had to remodel it, I knew most of the company's business rules.&lt;/p&gt;

&lt;p&gt;Another primary thing that assists the process of learning faster is code reviews. Even if you are a Jr dev, go ahead and review a Sr dev code. Just ask questions about implementation, approach or business rules. Next run the code locally and play with the changes. Inspect modules, classes, function returns. This improves considerably with your growth anywhere.&lt;/p&gt;
&lt;h3&gt;
  
  
  Market
&lt;/h3&gt;

&lt;p&gt;Keeping an eye on what's going on with the market is also a very good step towards increasing the chances of getting more opportunities and being a rare professional. The company and the job request from you, but the market also does.&lt;/p&gt;

&lt;p&gt;If we go from 2000's until now, it's possible to follow the evolution of the web, for instance, and the arising of many jobs related to adding rich apps, audio, and video. We saw the advent of the smartphones and we could specialize in mobile apps development. We also had a front-end boom, with many possibilities of JavaScript frameworks, chat and home automation, big data, data science, and more recently, we have progressive web apps, cryptocurrencies, and blockchain.&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%2Fcxp2r0qr9zwmk0rjolsd.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcxp2r0qr9zwmk0rjolsd.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Additional Questions
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Should I try a more scientific career?
&lt;/h4&gt;

&lt;p&gt;It really depends on your background. If you already had the experience of working on a paper and submitting it to a journal or similar, that makes things easy. Or if you like data analysis, it's possible to find hybrid jobs.&lt;/p&gt;
&lt;h4&gt;
  
  
  What are the developers "rank"?
&lt;/h4&gt;

&lt;p&gt;That's not well defined. The following posts may help:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/lpasqualis" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F29859%2Ff32e4ab0-0542-434d-ad71-d3561017895b.jpg" alt="lpasqualis"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/lpasqualis/7-ranks-of-coderhood-coder-programmer-computer-scientist-developer-engineer-architect-eca" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;7 Ranks of Coderhood: Coder, Programmer, Computer Scientist, Developer, Engineer, Architect&lt;/h2&gt;
      &lt;h3&gt;Lorenzo Pasqualis ・ Nov 30 '17&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#career&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#code&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#skills&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;div class="ltag__link"&gt;
  &lt;a href="/lpasqualis" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F29859%2Ff32e4ab0-0542-434d-ad71-d3561017895b.jpg" alt="lpasqualis"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/lpasqualis/19-types-of-developers-explained-1lj" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;19 Types of Developers Explained&lt;/h2&gt;
      &lt;h3&gt;Lorenzo Pasqualis ・ Oct 19 '17&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#career&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#industry&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;h4&gt;
  
  
  Corporate or Startup?
&lt;/h4&gt;

&lt;p&gt;You should try both and see which one is the best fit for you. I tried startup first because I could have more freedom and work in different areas I wouldn't have the opportunity to work in a big company. I talked to clients, gave presentations, gathered requirements, implemented solutions, deployed, worked even at the financial part of the company.&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%2Fb0w9ic55w7jpz2win76q.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0w9ic55w7jpz2win76q.png" width="800" height="744"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Should I consider a remote job?
&lt;/h4&gt;

&lt;p&gt;For sure. I have been working remotely for seven years, and part of &lt;a href="https://www.toptal.com/#book-tested-programmers" rel="noopener noreferrer"&gt;Toptal&lt;/a&gt; for four years, and I say it's really straightforward to find a remote job. Even non-tech companies are starting to allow remote employees, and it's working well. Some hire remote for a period of time, some have a remote and an on-site team, and some are constituted by only remote people. Even the CEO!&lt;/p&gt;

&lt;p&gt;If you want to pursue a remote career, be sure to follow &lt;a href="https://www.toptal.com/freelance/how-to-work-remotely-and-still-be-the-best#book-tested-programmers" rel="noopener noreferrer"&gt;this&lt;/a&gt;.&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%2F6dhmfyss4dm84qdaur71.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6dhmfyss4dm84qdaur71.png" width="800" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below is a list of places to find remote work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Toptal - &lt;a href="https://www.toptal.com/#book-tested-programmers" rel="noopener noreferrer"&gt;https://www.toptal.com/#book-tested-programmers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Hackhands - &lt;a href="https://hackhands.com/" rel="noopener noreferrer"&gt;https://hackhands.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Vanhack - &lt;a href="http://www.vanhack.com/" rel="noopener noreferrer"&gt;http://www.vanhack.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Remote OK - &lt;a href="https://remoteok.io/" rel="noopener noreferrer"&gt;https://remoteok.io/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Upwork - &lt;a href="https://www.upwork.com/" rel="noopener noreferrer"&gt;https://www.upwork.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;BairesDev - &lt;a href="https://www.bairesdev.com/" rel="noopener noreferrer"&gt;https://www.bairesdev.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;AngelList - &lt;a href="https://angel.co/" rel="noopener noreferrer"&gt;https://angel.co/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Remote.com - &lt;a href="https://remote.com/" rel="noopener noreferrer"&gt;https://remote.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Codementor - &lt;a href="https://www.codementor.io/" rel="noopener noreferrer"&gt;https://www.codementor.io/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Indeed - &lt;a href="https://www.indeed.com/jobs?q=developer&amp;amp;l=remote" rel="noopener noreferrer"&gt;https://www.indeed.com/jobs?q=developer&amp;amp;l=remote&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Dice - &lt;a href="https://www.dice.com/jobs?q=&amp;amp;l=remote" rel="noopener noreferrer"&gt;https://www.dice.com/jobs?q=&amp;amp;l=remote&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  That's it
&lt;/h3&gt;

&lt;p&gt;This post has a lot of my opinion and past experiences, but I hope it helped in some way. If you disagree or would like to discuss any specific topic, just comment and I'm happy to talk. Thanks. :)&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Delivering in time is a matter of observing the details</title>
      <dc:creator>Ivan Neto</dc:creator>
      <pubDate>Sat, 23 Dec 2017 08:45:24 +0000</pubDate>
      <link>https://forem.com/ivancrneto/delivering-in-time-is-a-matter-of-observing-the-details-i98</link>
      <guid>https://forem.com/ivancrneto/delivering-in-time-is-a-matter-of-observing-the-details-i98</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zaAIpR01--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e64isyfgiabbptifj3aw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zaAIpR01--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e64isyfgiabbptifj3aw.jpg" alt="https://thepracticaldev.s3.amazonaws.com/i/e64isyfgiabbptifj3aw.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After seven years of experience with software development, different companies and technologies, having as consequence experimented many methodologies to manage work and teams, I could see that regardless of the process your team has, you'll find yourself with problems to deliver.&lt;/p&gt;

&lt;p&gt;One big contributor to the failure of most of the software planning is the waste of time. We tend to spend more time than we should in many situations and the total time lost is big enough to affect the project.&lt;/p&gt;

&lt;p&gt;From my experience, the situations are mostly related to communication and represent a big bottleneck:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;People waiting for answers or decisions regarding a changed spec;&lt;/li&gt;
&lt;li&gt;Tasks being blocked by other tasks;&lt;/li&gt;
&lt;li&gt;Lack or slow communication.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This week I was working on an important task that had a requirement change one day before the deadline. A small change, but with two text options and we had to wait for the Project Manager to decide.&lt;/p&gt;

&lt;p&gt;The waiting time wasn't so big, but enough to create a &lt;a href="https://en.wikipedia.org/wiki/Butterfly_effect"&gt;Butterfly Effect&lt;/a&gt; and delay the task in one day (conflicts, new bugs in other tasks, QA started later, new deploy in another system being queued before, etc). We could have solved the issue by simply creating a flag or A/B test based solution where we could just deploy and then enable the first or the second text based on the PM's answer. The cleanup would certainly take less than the waiting time.&lt;/p&gt;

&lt;p&gt;Here are some examples that may improve your team ticket and processes' flow:&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 1 - Slow communication
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Developer finishes a task, submits a PR (Pull Request) and doesn't tell people there is a new review to be done.&lt;/li&gt;
&lt;li&gt;Reviewer finishes a review and doesn't ping back the developer to perform the fixes.&lt;/li&gt;
&lt;li&gt;Reviewer approves a PR and doesn't ping the QA person to start the testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes people think the others will get notifications and will act promptly. This doesn't happen. They will do only after three, four hours or even one day after.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; create a culture of always communicate to all involved whenever there is a change to the task state, using the team's main communication channel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 2 - Waiting for a decision
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;There is a decision to be done and the developer is waiting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution 1:&lt;/strong&gt; try to imagine what would be the most appropriate choice, choose it and work on it.&lt;br&gt;
&lt;strong&gt;Solution 2:&lt;/strong&gt; make both work behind an ON/OFF switch.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; The solutions above highly depend on the scope of the decision .&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 3 - Waiting for another system
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;There is an API endpoint for another system that needs to be finished before the developer can complete the task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Split the task in two. The first task will log instead of calling the API. The second task will replace the log with the API call.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 4 - Waiting for ticket
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;There are no new tickets to work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Code review, pair with another dev.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 5 - Developer is taking too much time in a ticket
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Sometimes there are tickets bad specified and we end up with one developer working alone for a long period of time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution 1:&lt;/strong&gt; Split the ticket into non-technical subtasks as much as possible, so other developers can pick each of the subtasks.&lt;br&gt;
&lt;strong&gt;Solution 2:&lt;/strong&gt; Split the ticket into technical subtasks containing deployable pieces. The feature can then be activated after the last piece is pushed (For instance, we can have a task to perform a database change, another to add a new HTML template, and finally, one including one URL with some app logic, showing the page and using the new database updates).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; in this particular case solution 1 and 2 can be perfectly done together. Instead of one big ticket, for instance, we could have three subtasks, each one with three technical parts, and many developers could work on it instead of just one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 6 - QA is holding some part of the process
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;QA has to test everything and is slowing down the process&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution 1:&lt;/strong&gt; Some pieces can be pushed and skip the QA process, like a template file that will not be used until the final feature is done.&lt;br&gt;
&lt;strong&gt;Solution 2:&lt;/strong&gt; Even business logic pieces can make use of A/B test flags, and if they are pushed turned off by default, QA can do a small test just to verify nothing is broken and the real test can be done later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 7 - Bugs found in pre-releases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A bug is found in a pre-release and a fix is needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution 1:&lt;/strong&gt; Fix the bug, of course.&lt;br&gt;
&lt;strong&gt;Solution 2:&lt;/strong&gt; If the bug only happens when a flag is inactive, deactivate the flag, so you unblock the push and then you can work on the fix and do a second push.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; solution 2 can only be done if the flag is new and is going to the next release.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 8 - Work depending on a still open PR
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The developer has to work on a new task, but it depends on a PR still under review.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Create a branch on top of the branch under review. Most developers here tend to say he/she is blocked and waits. There is no reason to wait. Work on top of the previous work, that's it. When the PR is approved, rebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 9 - Someone is blocked. You are blocked
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Ask yourself: what do I need to do to unblock her/him? What do I need to do to unblock me?&lt;br&gt;
People like to say "I'm blocked" or "I'm blocked by someone/something" and do nothing about it. It's comfortable. There is an excuse. You have to be able to say "hey you can do X, Y, Z, done, you are unblocked".&lt;/p&gt;

&lt;p&gt;Starting to change is hard but it pays off. In the beginning, you really have to keep monitoring everybody, detecting when every "time waste" situation happens, and work hard to unblock people.&lt;/p&gt;

&lt;p&gt;When you start to feel they are doing by themselves, i.e., it is becoming a habit, you can certainly expect more successful deliveries anytime soon. Remember: your job as a developer is not only writing code, but deliver value.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>productivity</category>
      <category>culture</category>
      <category>process</category>
    </item>
  </channel>
</rss>
