Python Django Tutorial: Deploying Your Application (Option #1) - Deploy to a Linux Server
1:22:00

Python Django Tutorial: Deploying Your Application (Option #1) - Deploy to a Linux Server

Corey Schafer 13.12.2018 447 204 просмотров 6 715 лайков

Machine-readable: Markdown · JSON API · Site index

Поделиться Telegram VK Бот
Транскрипт Скачать .md
Анализ с AI
Описание видео
In this Python Django Tutorial, we will be learning how to deploy our application to a Linux Server from scratch using Linode. If you would like $20 of free credit towards a Linode account, then you can use my link here to sign up: https://linode.com/coreyschafer We will be covering the entire deployment of a Django application. This includes spinning up a new Linux Server and tightening its security with SSH keys and firewalls. Then we will install Apache and Mod_WSGI so that we can get our Django App running. Let's get started... To skip the server setup, jump to 29:11 How to Run Linux/Bash on Windows: https://youtu.be/xzgwDbe7foQ SSH Key-Based Authentication Tutorial: https://youtu.be/vpk_1gldOAE SSH Keys on Windows: https://www.linode.com/docs/security/authentication/use-public-key-authentication-with-ssh/#windows Apache config used in this video: https://github.com/CoreyMSchafer/code_snippets/blob/master/Django_Blog/snippets/django_project.conf ✅ Support My Channel Through Patreon: https://www.patreon.com/coreyms ✅ Become a Channel Member: https://www.youtube.com/channel/UCCezIgC97PvUuR4_gbFUs5g/join ✅ One-Time Contribution Through PayPal: https://goo.gl/649HFY ✅ Cryptocurrency Donations: Bitcoin Wallet - 3MPH8oY2EAgbLVy7RBMinwcBntggi7qeG3 Ethereum Wallet - 0x151649418616068fB46C3598083817101d3bCD33 Litecoin Wallet - MPvEBY5fxGkmPQgocfJbxP6EmTo5UUXMot ✅ Corey's Public Amazon Wishlist http://a.co/inIyro1 ✅ Equipment I Use and Books I Recommend: https://www.amazon.com/shop/coreyschafer ▶️ You Can Find Me On: My Website - http://coreyms.com/ My Second Channel - https://www.youtube.com/c/coreymschafer Facebook - https://www.facebook.com/CoreyMSchafer Twitter - https://twitter.com/CoreyMSchafer Instagram - https://www.instagram.com/coreymschafer/ #Python #Django

Оглавление (29 сегментов)

Intro

hey there how's it going everybody in this video we're going to be continuing the Django series and learning how to deploy our django application to a web server so that anyone with internet access can use it within a browser so far we've created this application with some good functionality but the site still only lives on our local machine right now this is just running in my browser on my local machine but no one else can access this so the point of building these sites is to deploy them so that they're accessible over the Internet now look I'm not gonna lie to you deploying is a bit tricky you can find a lot of Django tutorials online but not many of those covered deployments and that's because they can be difficult it can be overwhelming because there's a lot of different ways to deploy an application and it's hard to know what's best for your specific application so we're going to look at several deployment options in this series so we'll look at how to deploy to your own Linux server Heroku how to deploy to Python anywhere and possibly some others in this video we'll be learning how to deploy our application to our own Linux server so when you deploy to a Linux server you're most likely going to be deploying to a virtual machine that is hosted by a company so that's going to be a company like Leno door digitalocean or AWS I personally use lenôtre my own web applications so that's what we're going to be using in this video and lenôtre was actually kind enough to sponsor this video and has provided me with a link where you can get $20 of free credit towards an account so if you want to follow along with this video then I'll leave that link in the description section below where you can sign up for an account and get enough credit to follow along so I've been using their services from my own personal website for years so I was really happy when they contacted me about sponsoring a video so with that said let's go ahead and get started ok so like I said we're going to be deploying to a Linux server so this method of deployment actually takes the most effort to setup but is also the most flexible in terms of what control you're gonna have over your application and web server so in future videos we'll look at deployment options that offer some free tiers but they usually only offer basic services so for example if you want to use your own domain name such as my Django blog. com or something like that then you'll have to upgrade to a paid service on those free options in order to set that up and even then you won't have the freedom or possibilities that you get with having your own virtual private server so the way that we're doing it in this video will give you a lot of freedom and room for your application to grow but it's not as simple as some other methods so there's definitely some trade-offs there okay so first things first for those of you have been following along with this Jango series I need to make one correction to the actual Jango code before we deploy this it worked in development but when I tried to deploy the application it gave me some issues so the correction that needs to be made is in our users models dot py file so I'm going to open that up really quick and make a quick change so I have my application open here in sublime text and this was in let me maximize this here this was then our users app here and this was in models dot py and the mistake that I made was down here in our save method so when we were calling the save method on our parent class this super dot SAV we need to accept any other arguments that our parent class might be expecting so in this case we need to pass in args which are positional arguments and kwargs keyword arguments into that save method so to do this I will just accept positional and keyword arguments here by doing stark wargs and star args and star clogs and we also want to pass those in to our save method whenever we call that on our parent class so again what that does is if you've watched my video on functions before then you'll know that the convention of passing argh and kwargs to your function allows you to accept any arbitrary number of positional or keyword arguments okay so with that correction in place let's now deploy our application so like I said I'm going to be using lenôtre play this application to a linux server that's my personal preference but you can do this same deployment with any Linux server that can that you can access via SSH now I already have an account with one node so let me go ahead and pull that up here

Creating a Linux Server

in my browser so I have a tab open here and I'll refresh this page so if you create an account with them then you should be able to access a page like this as well this is their new cloud manager and that's at cloud dot Llano dot-com now there's also a lonoa and at manage node comm but that's older and I believe they're now steering people towards using this instead so this page gives me access to all of my currently node servers so you can see I already have one it created for my personal website here called core EMS - server but we're going to create a new one from scratch to deploy our django application so let's go ahead and see what this process is like so first I'm going to come up here to create and we're going to click on create and we want to create a new 'la note is there name for there you can see here it says high-performance SSD Linux servers for all your infrastructure needs so we're going to click on that to create a new Linux server and now we need to select what image we want to create with this server so I'm going to use a bun - server in this video but depending on what your preference is you can use any of these CentOS might be another option or Fedora but I'm gonna choose Ubuntu so for the region I'm going to come down here I'm just going to pick Dallas Texas it's a nice midpoint in the United States you can see that they also have some regions in Europe and Asia as well so depending on where people are going to be accessing your application you might want the server to be served up to them from a closed location so for this application here I'm just going to choose Dallas Texas that's fine so down here for the low note plan this is where you pick how much performance you want in your machine and you can see the prices are attached here so this one is $10 a month this one is $20 a month now this is their standard plan here they also have something called an anode here and if we click on that you can see that this is a pretty low performance machine it's just got one CPU 25 gigs of storage and a one gig of ram but it's only $5 a month and our application especially if you're just testing most likely isn't going to be very intensive so I'm just going to pick their cheapest option for deploying our django application now you can always resize these later so I just suggest going small at first and if you want to bump it up to something bigger depending on you know how much traffic you're getting then you can do that at a later time okay so down here at the label I'm just going to call this Django - server okay so for the tags I'm just gonna leave that empty there so now we need to choose a root password so this is going to be the root password on the server so you're going to want to pick something secure for me I'm just going to put in a password of this is a test now I'm going to delete this server after this video so you know you're not going to be able to log into my server as a root or anything like that now whatever password you choose here be sure that you remember this because this is a root password on your server and you're definitely going to need to know it whenever you first log into your computer so you know definitely remember this for later because we are going to be using that so now that we have that I'm just going to go over here and click create and now it's going to create our server for us so you can see here that our Django server it says that it is provisioning the server and now it is booting up so I'm going to go ahead and fast forward to where this machine is fully created but it shouldn't take too long just a couple of minutes ok so once our server has completed booting up we can see our server here within our list of Leno's we can also go to our dashboard and see it here now if we click on our 'la node then it will give us more options with this so click on that django server that you just created whatever you named it and now go to the networking tab so we can see that we have a lot of tabs here summary volumes networking settings everything like that let's click on networking and down here we see access and the first thing it says here is SSH access so let's copy this because we're going to SSH into this machine so you're going to want to copy that SSH command and paste it into your command line to SSH into your newly created server now if you're on Windows then you won't have access to the SSH command in the command line there are other tools that you can use that allow you to SSH into a server so one of the more popular ones is called putty and I have it here on I have their website pulled up here it's at putty org and they have documentation in here of how you can SSH into a server but personally what I would recommend on Windows if you're on a newer version of Windows is to simply install the Linux back she´ll on windows and you're able to use ssh through that that's what I personally do on my Windows laptop anytime I need to connect to a server now I'm not going to show that process of installing the Linux bash shell on Windows in this video because I already have a separate video detailing that whole process so I'll put a link to that in the description section below if anyone wants to watch that so once you're running bash then you should be able to use SSH and again if you don't want to use bash for any reason then you should install the software called putty that allows you to use SSH on Windows here at putty org but I will say that if you're using a Linux bash shell then it'll allow you to more easily follow along with all of the commands in this video okay so if you're using bash then we'll want to copy this SSH command here for from our networking tab inland ode and let's paste this into our command line now I have two different terminals pulled up here right now one of these I'm going to use to run commands on my local machine and one our remote Linode server now you don't have to do it this way but if you only use one terminal window then you'll have to go back and forth between your local machine and your server so I think it's easier to simply have two windows open and let me actually minimize our browser here in the background so that we only have our terminal windows open here okay so now I'm going to paste that ssh command into my terminal on the left side here so on the left i'm gonna have our remote server and on the right i'm gonna have our local machine so i'm going to paste in that command and hit enter and this is going to ask you if you're sure that you want to continue connecting this is only going to ask you this the first time so i'll just say yes and now it's asking for that root password this is what we created when we created our lenôtre so for mine I had that as this is a test so if I insert that password then we can see that worked we are now SSH into what is going to be our web server so you can see that we are root at localhost so local host this is our low note server so we were actually in the terminal of that machine so first let me clear the output there first let's install some software updates this is just something that you're going to want to do for the first time that you get on to your Linux machine now I'm actually going to minimize this right side here and expand

Updating the Linux Server

this over so that we have more room to work with here on our server so to do this now remember I'm on a bun too so I'll say apt-get update and then I will also type in these two ampersands and then apt-get upgrade and let me make sure I spelled that right and this is just going to go through and update our machine and make sure that we have all the latest security patches and things like that it might ask you occasionally if you want to continue so you might have to hit yes a couple of times through this and this could also take a little bit of time so I'm just going to fast forward it in to where this is done okay so after a couple minutes those software updates should complete so now I'm going

Setting the Hostname

to clear my screen here so now what we want to do is we want to set the hostname of this new machine so on Ubuntu we can do that by saying a hostname CTL set - hostname and now let's put in whatever we want the hostname to be so I'm just going to say Django - server here for this machine and we can check that worked by typing in hostname and we should get Django server there now remember I did use a boon - for the operating system for this example but if you are using something like CentOS or Red Hat then some of these commands are going to be different so you're gonna have to map the differences between those if you're using a different operating system than what I'm using here in this tutorial okay so now we also need to set the hostname in the host file so to do this I'm just gonna use Nano because Nano is a simple editor that most people know how to use so I'm going to say Neto Nano and this is in the e. t. c directory and this file called host so I'm going to nano on that and underneath this 127 0 0. 1 I am going to put in the IP address of our server now you're going to need that IP address alot so it would probably be a good idea just to write it down now this is the IP a dress that we used in our SSH command now I think that I still have that command pasted in or copied into my clipboard here and I do so I'm just going to get rid of that first part and there is the IP address that we want to put in there so that IP address and then hit tab and now we want to put in what we had as our host name so that was Jango - server so if I now hit control X and then yes to save and then just hit enter to keep the same file name and that should finish up setting the hostname okay so now we want

Adding a Limited User

to add a limited user so right now we are logged in as the root user has unlimited privileges and can execute any command now that might sound nice but it's best practice to add a new user that has limited privileges that you can use as your main account and you'll still be able to run admin commands using the sudo command so let's add this limited user so I'm going to say add user and the user that I'm going to create is going to be Corey MS now you can put whatever username you want here so I will hit enter there and now it's asking us to put in a password so again I'm just gonna say this is a test with a few capitalizations in there same password again and now it's going to ask you to fill out a little bit of information like your full name and stuff like that this is actually optional you don't have to do this so I'm gonna put in my full name but for the others here I'm just going to leave blank and hit enter and then it's going to ask if that information is correct I'll just accept the default of yes and that created a new user for us now we want that new user to be able to run you know route commands so we want them to be able to use sudo so way the way we can do that then I'm going to clear the screen here the way we can do that is to simply say add user Cori MS and then just put sudo after that and that will it says here adding user Cori MS to the group sudo okay so now we have created a new user on this Linux server and now we can just log in as that user it's not good practice to log in as root because there's a lot of things that you can mess up that way so let's exit out of our server so I'm going to exit and now let's log back in but so I just hit up arrow there to log back into our server but instead of logging in as root I'm going to log in as Cori MS as the user that we just created so you want to fill in whatever user you created here so when we hit enter it's going to ask for that users password and that's what we put in whenever we created the user it looks like I mistyped that let me try one more time okay so now we can see that we logged in as our new user so I'm going to clear our screen here and we

SSH Key Based Authentication

can see that we also have our host name there so now it's saying that is the name of our server okay so now that we have a user created now we're going to want to setup SSH key based authentication so that we can login to our server without a password okay so at this point I know that you might be thinking to yourself like why do I have to do all of this stuff I just want to deploy my django application well the reason that we're doing all of this is because I want to show you what it's like to deploy a real-world application and to put the proper precautions in place on your server from scratch so that includes best practices like setting up SSH keys and firewalls and things like that you're going to want to do that on any real-world application that you deploy so I may as well include it in this tutorial instead of just showing you the bare minimum so right now the next best practice that we're going to put in place is using SSH key based authentication to login instead of passwords so by default we're using a password to login to our web server we instead want to use key-based authentication and that's more secure and more convenient because it uses keys that can't be brute force and also allows us to log in without putting in a password every single time and that's great for you know running remote scripts that connect to your web server or anything like that now I have a separate video on SSH key based authentication as well so I'm not gonna go into a lot of detail of these commands but we're going to run through all of them here anyway if you want to know more details as to what these commands are doing then you can watch that video and I'll put a link to that in the description section below now there's actually an easier way to do this by using a command called SSH copy ID but it's not available on all operating systems so instead we're just going to do this the slightly longer way okay so we are logged in to our webserver as our user that we just created and we are in the home folder if I do a PWD that will print the working directory and we are currently in our home folder here so we're going to want to make a directory called dot SSH so I'm going to say m'kay der - P that means it's going to make the entire tree of the directory and we want to create that in our home folder and that's what that tilde is so home folder and that is going to be dot SSH so let's make that and if you do an LS - la then we can see that we do now have that SSH folder so now I'm going to clear my screen there and now we want to go back to our local machine so if you don't have two windows pulled up then you can simply exit out to get back to your local machine but I am just going to use this other window terminal here so here I'm on my local computer now again I'm doing this in bash in this tutorial but if you're using a program like putty on Windows that we talked about before then you'll have to do this differently to create and copy your SSH keys to your webserver so I found documentation and lenôtre putty users on how you can do this through putty and I'll put a link to that in the description section below as well so that you can see how to do that using that software but here in bash we can simply say SSH - keygen and I'm going to do a - B and then 409 6 that just makes it a little more secure now remember we're on our local machine here and now it says generating public private RSA key pair enter the file in which you wish to save that key and this is in my home folder on my local machine in an SH 8 SSH directory with an ID RSA file I'm just gonna leave that as the default there and it's saying that I have one that already exists so I'm just going to overwrite that with yes and enter a passphrase so you can also have a passphrase for this key as well I'm going to leave that empty but you can add one if you'd like to make it even more secure okay so what that did for us is it created two keys so we can see that it says your identification has been saved as ID RSA and then your public key dot pub now what we're going to want to do is put our public key on the server so that then we can log in without a password it's going to be able to recognize us because these two keys are going to match so let me go ahead

Copy Public Key to Server

and clear the screen here so now we need to get that public key to our server now if you're on Windows and you're not using bash then you can use you know FTP or FileZilla or something like that where you can drag and drop since we're using bash we can just simply use an SCP command so I'm going to say SCP and that was created in my home folder and this dot SSH directory and that was called our ID underscore RSA dot pub and we want to copy that file up to our server so now I'm gonna say clorium s but at this point you're gonna want to put in the user that you created but I'm using koream s and also now we want to put that IP address so like I said you're going to be using that IP address to your server a lot so it's probably best to write it down so I wrote mine down here mine is one night 8. 5 8. 11 9. 1 8 3 so after we specify where we want to copy that public key to the server now we want to put an exact location in that server so I'm going to put a colon here and now we can specify the location on this server that we want to save that public key so that is within the home directory of this user here so a tilde there for the home directory and then dot ssh directory and let's save this as a file called authorized underscore keys now you don't need file extensions on Linux so we can just call that authorized keys and leave it at that so I'm going to run that and it's going to ask us for our password because we don't have this set up to use without a password yet okay and we can see that was copied over so now I'm going to

Update SSH Permissions

go back to our server here so now if I do an LS 1 our dot SSH directory then we can see that now we have that authorized key file ok so now just to finish this ssh stuff up we now need to update some permissions and again I can't go into deep detail as to what every command is doing in this video or else it would just run on for a long time but basically what we're going to be doing here is setting the permissions for the SSH directory to where the owner of the directory has read write and execute permissions on that directory and the owner of the files in the directory will have read and write permissions on those files so to do that we can say sudo chmod and that's how we change permissions in Linux and we're gonna do 700 permissions and we're going to do 700 permissions on that SSH directory so I will run that and now it's going to ask for a sudo password so we can put in that password oh it looks like I may have mistyped and now I'm gonna run at that same command but I'm going to do 600 permissions and I'm gonna do a 600 permissions on all of the files within that directory so I'll run that and if you use sudo a good bit then you don't have to put in the password every time it'll remember it for some time now again I'm not going to go into a lot of detail here as to what these permissions mean but basically on Linux the way that the permissions work is this first number here is the permissions for the owner of either the directory or the file the second number here is the permissions for the group and the third one here is the permissions for everyone else so what we were saying here with seven is read write and execute and with six here it's just read and write and those are just zero permissions for everybody else okay so now we should be able to log in without a password so again I'm going to exit my machine just to test this so now we're back on our local machine so I'm gonna hit the up arrow to where we logged in SSH in as our user and I'm gonna hit enter and you can see that it just

Change SSH Permissions

logged us in without a password there so our SSH keys are now working and that is also more secure than using a password as well okay so we're just about finished up with the SSH stuff but there's a couple more things that are best practices to change here before we finish this out so first of all we want to not allow root logins we just want to be able to log in as our users and we also don't want to allow password authentication because we just want to be able to log in with key-based authentication and somebody needs a password then it means that they don't have the keys that they need so let's just disallow that altogether and we can do that within the SSH config file so that is in the location and you have to use sudo here so we'll do sudo nano and this was within this et Cie directory SSH and that file is sshd underscore config so we need to put in our sudo password again so we're gonna change two things in this configuration file so first we are going to change the permit root login so if you scroll down a little bit then you can see that this is the first one uncommented here and right now it's set to yes we're gonna set that equal to no and let's scroll down a little further here and there should be a commented one that says password authentication so we can see here this one is commented out password authentication so let's uncomment that and it's already set to yes let's instead set that to no okay so now let's save that so in Nano you hit control X and then a Y to save and then enter just to keep the same file name and now we need to restart the SSH service so we can do that with sudo system CTL restart sshd so let's run that and that should have restarted our sh service okay so we're almost ready to push our django application there's just one more thing that we're gonna do and that is setting up a firewall but this is going to be very quick so first we

Install UFW

need to install something so I'm going to clear my screen so let's say sudo apt-get and we're going to install something called ufw and UFW stands for uncomplicated firewall this is a lot easier than using like IP tables or something like that okay so now we're just going to set up a few basic rules so first we're gonna say sudo ufw default and we're going to allow outgoing and hit enter there and now I'm gonna hit the up arrow and I'm gonna put in another rule and this is gonna be deny incoming let me spell that correctly deny incoming now configuring a default deny rule that denies all incoming traffic can lock you out of your server unless you explicitly allow SSH so be sure that you've configured these next allow rules for SSH and HTTP before applying our changes so to allow SSH you need to say sudo ufw allow and we can just allow SSH okay so that's good now I'm not gonna allow HTTP right now instead since we're going to test our site before we actually make it live I'm just going to allow a certain port now if you remember our Django development server runs on port 8000 so let's just allow that port for now and that's how we'll test it on this Linode server and if it's all working then we'll allow HTTP over port 80 so I'm going to allow 8000 there and we can see that these rules were updated and now we need to enable these we're

Enable UFW

getting a little far down here so let me clear my screen okay so now we need to enable these so I'll say sudo ufw I'm sorry enable not allow so sudo ufw enable I'll run that and it says command may disrupt existing SSH connections so hopefully you remembered to allow those SSH connections so I'm gonna say yes and now if we do a sudo UFW status then we can see everything that is being allowed here so port 22 is ssh and port 8000 here is what we're going to use to test our django application before we make it live on port 80 so i'm going to clear

Deploy to Web Server

the screen okay so that's going to finish up all of the new linux server setup type of stuff so now we're ready to actually deploy our django application so first we want to put our application on the web server now there are multiple ways that you can get this application to your web server so if you have it checked into a git repository then you can simply use git to do a git clone to our server here you can use an FTP client like filezilla to push it to the server since we're already in the command line on our local machine we can just use the terminal command to do this so I'm gonna pull up my other terminal window here where I'm on my local machine and let's clear the screen now before you push your django application if you're using a virtual environment for your application then you're gonna want to create a requirements txt file that captures everything that we need to install for our django application to work now I was using a virtual environment for this series so I'm going to activate that and then create a requirements that txt file from that environment so I am going to activate my virtual environment so I'm going to say source and that environment lives on my desktop and this is called Django env and then I have to run I have to source the activate file so - been - activate so now we can see in our prompt here

Dependencies

that Django environment is now activated now if we want to see all of the dependencies that we have for our application then we can simply run pip freeze and if we run this then we can see it displays everything that we're using in this project so we have django Krispies forms pillow and some of these are dependencies on others so PI TZ is a dependency that Django uses and you can see that this also provides all of the versions the exact versions that we were using in development as well so saving all of these and then installing those on our server should make sure that you know no updates or anything are going to break our application because we're installing exactly what we were running in development now if you're on Windows then you can create a requirements txt file and then just paste all of this here into it but if you're on Mac or Linux or using bash then we can simply

pipfreeze

say let me clear my screen here we can simply say pip freeze and then we can feed that into a requirements that txt file and that'll work that will create a requirements that txt file with the contents with the output of that pip freeze command so I will run that and now we want to put this requirements txt file into our Django application so I am going to open up finder here and I have two windows opened up so this is my desktop here now let me open up my Django project so this is my Gengo project and this is my desktop I'm going to well I thought I created the requirements that txt file on my desktop but actually I'm within my home folder instead sorry about that so let me go to my home folder so here's that requirements txt file and I'm just going to drag this over and it dropped that into my Django project so now that requirements dot txt file is inside of our Django projects and I'm going to close down those Finder windows okay so now we need to put our application on to our web server now since I'm using bash I'm going to use the same SCP command that we used earlier to copy our SSH keys but if you're not using bash then again you can use something like FileZilla or get to get your project folder onto the server okay so to do

copy to server

this first I'm going to navigate to my desktop because that is where my Django project currently lives and that project is called at django underscore project so now I'm going to say SCP which will copy and we need a dash are here to do a recursive copy that means that we can copy a directory so now I will do ooh django underscore project that's what we want to copy to our server and this to query ms at now you want to use whatever user you created there and now the IP address so again I wrote this down you want to use your IP address mine is one 98. 5 8. 11 9. 1 8 3 and again to specify an exact location on that server we can put a colon and I'm just going to put this in the home folder on for this core EMS user so after the colon I'm just going to put a tilde and a forged slash and that should put it in the home folder on that server so I'm going to run that okay and that copied everything from our Django project and one to our server so now let me minimize our local machine here and go back to our server that we

LS on home directory

still have opened in this terminal window and now let me do an LS on the home directory to make sure that copied over and we can see that it did we have our Django project here and if we do an LS on Django project then we can see that it has all of our applications so it's got the main Django project here the users the blog and our sequel Lite file everything okay so now that we have our Django application on our web server now we're ready to actually get it running on here so first of all let's create a virtual environment that is going to run our

Install Python

application so to do this we're going to need to install a couple of things so I'm going to say sudo apt-get install and we want to install so first I'll install Python 3 - pip now you want to do the Python 3 - pip because if you don't put the 3 there it'll do Python version 2 so we'll do a sudo install of Python 3 - pip now some of those installations can take a bit so instead of watching the entire installation throughout these videos I'm just fast-forwarding to where these are complete so if you're following along and yours is still installing then you can just pause the video until yours is done as well okay so I'm going to clear

Install Python Virtual Environment

my screen here and now let's install Python threes virtual environment so I'll say sudo apt-get install and this is going to be Python 3 - ve in V and I'll say yes there ok so once that is finished installing now I'm going to create a new virtual environment now you can create this

Create Python Virtual Environment

virtual environment anywhere that you want but I'm going to put this inside of our Django project folder so to create a virtual environment we can simply say Python 3 - M V E + V and I'm going to put this within our Django project folder and I'm going to call this virtual environment just simply V E + V so now if I do an LS on our Django project then we can see that we have a virtual environment right here so now let's activate that virtual environment so that we can install all of our dependencies so I'm going to CD into our Django project directory and within here I'm going to say source the env bin activate and that should activate our virtual environment we can see here at the beginning of our prompt we now it now says V in V so that's a good sign that our virtual environment is activated okay so now I'm going to

Install Python Dependencies

install all of those dependencies from our requirements txt file and remember we just put that here within our Django project so we can simply say pip install and if we do a - our on pip install then it'll expect at requirements txt file so we can say requirements txt and run that and it's going to go through and install everything in that requirements file so it's going to install Django and PI T C and crispy forms and all of that now if you didn't create a requirements txt file then at that step you still want to create the virtual environment but you're just going to install those manually so you just install the version of Django that you used in the series and then pillow and crispy forms and all of the other packages that we use throughout the series okay so now that we have all of that installed let me clear my screen here now let's change

Change Django Settings

some settings in Django so that we can test this on our lamode server so first I'm going to open up our settings dot py file now that is located so I'm going to do a sudo nano that is located inside of Django project settings dot py so I will run that and there are a couple of things that we need to change here so I'm gonna go down here a little bit and we should see something called a loud host now a loud host we need to put in our IP address of our server now if you have a domain name then you can use the domain name as well but for now we just have the IP address now this is going to be a string so I wrote my IP address down you would insert yours here but mine was one 98. 5 8. 11 9. 1 8 3 now you have to have that in a loud host because for security reasons Jango isn't going to allow traffic anywhere that it doesn't recognize the host ok so now with that in place now let's scroll down towards the bottom here where we put ok so here at the bottom I want to scroll up just a little bit to our static URL so if you remember earlier in the series I said that static files were handled differently in development than they are in production so in production we have to put in a place where these static files are going to exist and that's going to be the static route so right above the static URL here I'm going to put static underscore route and I'm going to set this equal to that for me I'm just going to put OS dot path dot join and I'm going to put this in the base directory so base dur it's actually going to be very similar to our media folder here so it's going to be in the base directory of our project and instead of media we will do static so once we've made those changes to our settings let's save those so I'll hit control X and then Y to save and then enter to keep that same filename so now to get our static files working here on the server we need to run a command called collect static so I'm gonna say Python managed up py and that is collect static so if we run that then we can see that it says 120 static files copied to this static directory here within our Django project so if I do an LS now then we can see that now we have a static folder here within our Django project okay so now let's test this so let's run our development server but we're going to open it up on our lenôtre server here to where we can access it from the outside so I'm going to say Python manage py run server now don't hit enter yet we want to do the address of 0 0 and then: port 8000 remember that we opened up port 8000 on this server sorry this is going to the next line here now but hopefully you can read that alright so if I hit enter there then it says that our server is running and since we specified this as 0 0 that should allow us to go to our IP address on port 8000 and see this development server running so I'm going to open Chrome back up and see if we can access this so my IP address was 1 98. 5 8. 1 19. 1 8 3 and you go to port 8000 we can put in a colon and then 8000 so if I run that then we can see that our blog is now available through our browser so this should be accessible to anybody so you could send somebody your IP address and that port and they should be able to go to your blog and interact with it so let's test the site so if I go here to create a new user let's try so I'll do test four and an email of test for at test comm a random password and let's sign up and we can see that our user has been created let's try to login with that user so test four and then the password that we used so we can see that we can login it gives us a default profile here where it has all the information that we entered so let's test that we can create a new post so test post test content if we post that then it looks like our post was created let's try to update a post so I will do test updated post and that seems to work let's try to delete a as well let's try to update our profile picture you want to be sure that you test a good bit of functionality just to make sure that it all seems to be working properly now so let's update a profile picture and that seems to work as well let's test the logout okay and the logout works and lastly let's test the admin page so I'm going to go to forge slash admin and then put in the user I created with admin access is Cori MS and I will log in here okay and it looks like our admin page works as well so now I'm going to log out of there okay so it seems like most of our functionality is working on our server now so that is a really good sign now one bit of functionality that isn't going to work yet is our forgot password functionality so if I go to forgot password and try to reset my password then it's going to give me an error and the reason is because we haven't copied over our environment variables from our local machine that contain our email service username and password so that's one bit of functionality that's not going to work right now but we will get that set up here in just a bit okay so our site is working but you don't want to actually leave it like this so I'm going to go back to our terminal here now we don't actually want to run this using the Django server like we've done here this was just for testing that everything worked so far but now let's kill that server that we were just running and now we want to run a server that's more reliable so you know something like Apache or nginx or something like that now in this video I'm going to use Apache but there's different options available to you and let me actually minimize our browser

Install Apache

there okay so there are a couple of things that we need to install here first Apache which is going to be our webserver and then we're gonna install something called a mod whiskey now whiskey which is WSGI stands for web service gateway interface and that's what allows our web server in this case Apache it to talk to Python and to talk to our web application which in this case is Django so we need to install and configure both of those so first I'll install Apache so I'll say actually let me go back to my root directory here by typing CD so that we have some more space here so now I'm going to say sudo

Install Apache 2

apt-get install and this is going to be Apache too so let's run that okay and once that's installed I'm gonna

Install modwhiskey

clear my screen here and now let's install mod whiskey so to do that is sudo apt-get install and this is Lib Apache - mod - whiskey - pi/3 I always have to look that up I can never remember these long package names so I think that should work let me run that and hit yes okay so it looks like that was installed successfully so now we need to configure our Apache web server so I'm going to clear my screen so now let's CD into a directory here in etc' Apache - sites available and this directory here is where the Apache configuration files live so if I do an LS in this directory here then we can see that there are some default configuration files here now I'm going to use one of these configuration files as the starting point for our projects configuration so I'm just going to copy one of these so I'll say sudo CP and I will copy that first one so 0 0 default and I will copy that into a file called Django underscore project. com and again sorry for the text scrolling on to multiple lines here I know that can make it a little bit more difficult to read but I have to make a trade-off between having the text large enough to where you can read it but you know sometimes that makes it harder to read when it goes onto multiple lines like that ok so now we've created this Django project. com configuration file that is a copy of the default configuration file so now let's edit it to where it meets the needs for our project so I'm going to do sudo nano and change that Django project comm file ok so what we have here is a default configuration file for Apache now where it says virtual host 80 right here this 80 it means port 80 so this is what's going to show up on HT P port so whenever we go to our IP address in the browser it's going to follow these rules so I'm gonna scroll down here towards the bottom all of this stuff is just default standard stuff so right here before the closing virtual

Alias Directory Permissions

host tag I'm gonna add in a few of our own rules so first of all we're gonna use an alias to tell Apache to map requests starting with static to our apps static folder and remember in our project settings we put this in our projects base directory so to do this I'm going to say alias and we want to alias anything that references static and we want that to go to our projects static directory now on my machine this is located in my home directory and my user is corey MS you're going to want to put your user there my project is called django underscore project you're going to put a want to put your project there and I put that static folder in my Django project directory so that is where mine is located you want to put where you put your static directory there so now we want to give some permissions here so we're gonna say for that directory sorry that needs to be capitalized so we'll say directory and the directory is going to be the same thing that we put here so I will just try to copy that and paste it and within that directory tag we are going to say require all granted and now we can close out the directory tag so we will put a forward slash there and directory and now we want to create another one of these for the media folder as well so I'm just going to copy that big whole section there and paste that in and up here where we had static we want to change these to be media so I will change this one here to be media and then here at the end I will change that to be media as well and one more place right there okay and now that we have the and media directories taken care of next we need to grant access to the WSGI dot pi file within our project this ensures that Apache can access our whiskey dot PI file which is how our app is actually going to talk to our webserver so to do

Create File Tags

this I'm going to scroll down here just a little bit so to do this I am going to copy up until this point of this line here and paste this in but for the directory here I also want to go one more level deep and I want to go into the Django project directory within our Django project and that's because that's where that whiskey dot 5 PI file lives so now within there and I'm just going to go ahead and close this off right now so I don't forget later so within here we want to create some file tags so I will say files and that is WSGI pi and i'll also close off that files tag there as well and within here we also want to say require all granted ok so we're just about finished up here just a couple of more things to add so next we're going to add the part that actually handles the WSGI part so we're going to use the demon mode for this and this is recommended in Django's official documentation so to do this let me scroll down here just a little bit so we can see this a little better so to do this I'm going to put in a tag here called WSGI script alias and then we are just going to put a forward slash and then we will do a ford slash home core EMS you're going to want to put your user in there Jango underscore project ford slash Jango underscore project forge last WSGI dot pi so the first bit here is the base URL path where we want to serve our application and in this case it indicates the root URL so basically that means going to the base of our IP address without any extra routes will take us to our django application and the second part here is the full path to that WSGI dot PI file so once we have that done now we can specify the daemon process so I'll say WSGI da e mo n is how you spell that daemon process and now we can just call this whatever we want it's just going to be the process so we'll just call it Django app and now I can say Python path open I don't want any spaces there so Python path equal to this is going to be the path to our project directory so on my machine that's ford slash home forge / square EMS forge / Django project again you put in the path to your Django project there and now we also need to specify Python - home and for python home I'm going to say that equals and this is going to be the location to our virtual environment so I'm in on my machine that is fork slash home forge / core EMS forge / django underscore project forge / ve in V now I know that this is a lot of typing and it might be easy to mess something up here or miss type something so I'm going to take this configuration file once we're done with this video and I'll put this in my github page so that you can compare it to yours to see you know if you've made any mistakes ok so with that said we only have one more line here to finish up this configuration so this is going to be WSGI process group and we want this process group to be equal to this process here that we specified in this daemon process so I'm just going to type in the same thing there so Django app is what we name that process ok so hopefully we didn't make any typos there and got everything correct so I will save this file so within Nano it's ctrl X a Y for yes to save and then just hit enter to keep the same my own name so now I am going to clear

Enable Site

my screen and I'm going to see the back to my home directory here so that we have a little bit more typing room so now let's enable that site through Apache so to do that we can say sudo and this is a to e in site to enable the site so that's Apache to enable site and then we want to specify that Django project and I will hit enter there and you can see that it's telling us that to activate the new configuration we need to restart Apache we'll do that in just a minute now I'm also going to disable the default site so I'm gonna say sue do a two for Apache to this for disabled and then site and we will disable that zero-zero-zero default dot kampf okay so now that default site is disabled and our Django project is enabled okay so now let's finish up with doing some file permissions here so there are still a

Change Permissions

couple of things that we need to change so right now we have to give Apache access to things like our database because we are right now we're using sequel Lite in a future video we're going to use Postgres but right now we're still using sequel Lite so Apache has to be able to read and write from that sequel Lite file and the same goes for our media folder so if somebody is uploading a picture then Django has to be able to write to that media folder so let's do a few different permission updates here so I'm gonna say sudo CH owned which changes the owner of a directory or a file and I'm gonna do a colon WWD des that is the Apache user there and we want to change the permission and Django project DB SQL Lite 3 is the name of our database file so what this is going to do is it's going to make Apache the group on that file so if I run that then now Apache is the group owner of that file and now I'm going to change the permissions so I'll say sudo chmod and the permissions that we want here are 6 4 so again that's a 6 for the owner group and a 4 for everybody else a 4 is read permissions and I want to give permissions to Django project DB SQL Lite 3 okay so I also want that WWD group to own the Django project folder itself as well so I'm gonna say sudo CH own and we will put in a colon WWD de and we will change the ownership of the Django project itself so I will run that now if we do an LS - la then we'll be able to see these permissions so if we see Django project here we can see that now quarry ms is the owner but it is now w WD is the group owner so that's what that CH own command is doing ok so now

Change Media Permissions

I'm going to clear the screen here now let's do those same things for the media folder so I'm gonna say sudo CH o W in and now we're going to do a dash R for recursive and again we're gonna do a colon WWD des and we want to give permissions here on the media folder so I'll say for Django project forge / media so I'll run that and that will allow Apache to actually write uploaded media to that media folder and now let's change the permissions here so I'm gonna do a sudo chmod - R and we will do a 7 5 Django project media again and run that okay so I know that this has been a long video so far but we are just about finished up with the final deployment of our Django application there are just some final changes that we need to make before we go live with our website so the first thing is that we need to move sensitive information to a config file now I was using environment variables in the development of this application but in Apache environment variables can be a little tricky to work with and you have to change the WSGI Python file and things like that since this video has already been long enough and we've done so much configurations I think it would be a lot easier to just do a config file for the sensitive information instead of doing environment variables so the sensitive information that I'm talking about is going to be like our secret key for our application and our email username and our email password that we use to reset our password in the application and in the future this is also where we are going to add our database username and database password and things like that when we use Postgres so I'm just going to create a config dot JSON file on our system that holds that secret information so I'm gonna put this in so I'll do a pseudo touch which will create a file and I'm gonna put this in the e. t. c directory and I'm just going to call this config dot JSON now if you have you know multiple applications on the same server then you can have the name of your application - config dot JSON or something like that to differentiate between their different applications so I'm going to run that to create that file and now I'm going to grab our secret key from our application so to get the secret key I'm gonna say sudo nano and that is within Django project settings dot py if I run that and scroll down just a little bit here then it is close to the top of our settings dot py file and you can see here it says security warning keep the secret key used in production secret so if you're using something like git then you don't want to you know have this pushed up to github or something like that you want to either use an environment variable or load it in from a cake fig file like we're going to do here so I'm going to copy this secret key copy and I will now erase this here and we will add this back in just a second but for now I'm going to save that settings file and now let's open up that config dot JSON file that we just created so I'm gonna say sudo nano and we put that in - et Cie config JSON now this is empty right now but to create this JSON file I'm going to put in opening and closing braces there and now I will put in a key for the secret key and I will give that a value and this is going to be within quotes here now we're going to paste in that secret key that we copied from before now we're also going to put other secret or sensitive information in here as well so our email user that we use to send emails through our email service we can put that email address in here and we also need our email password so I'll say email underscore pass is what we called it in our application and I will put that in here as well now you're gonna want to put your email username and your email password that we used in this series now I'm gonna use my own I'm not gonna show you my email username and password here for obvious reasons I don't want you to be able to log into my email but so I'm gonna exit out of this file now but before I actually run this live I'll fill this in off of the recording so that we can see that it works properly so now I'm going to save this file so ctrl X Y to save and then enter and now we want to update our settings not py file and pass in the values from that config file so I'm going to run that same command that we ran earlier sudo nano and we want to run Nano on our settings dot py file so I will run that now here at the top of our settings dot py file I'm just going to import JSON now I used JSON for my configuration but if you're more comfortable using gamal or something like that then you can definitely use that as well so now here at the top I'm just going to load in this config file so I'm going to say with open and we are going to open that file so that was in /e TC config dot JSON and we will open that as config underscore file and within here I will say config is equal to json dot load and we will load in that config file make sure that i spell that correctly we will load in that config file and I think that Nano is putting in more spaces here than what I'm used to when I hit tab so instead I'm just gonna use spaces so I'll put in four spaces there instead okay so with that config file loaded these should be the last changes that we need to make in our settings dot py file so here for our secret key remember we load it in that JSON file and JSON whenever you load something in and use JSON load it loads that in as a dictionary so now our config variable should be a dictionary with all of our sensitive information so for our secret key here I'll just say config and access that secret key of that config dictionary and that config variable that we are using there let me show you just one more time that is what we set right here that is that variable that is the JSON that we loaded in so let me go back down to our secret key and now that we've set the secret key to that sensitive information now we also need to set debug equal to false you don't want debug equal to true on your production machine because anytime there's an error it's going to give way too much information to people and it could you know expose other flaws in your system to people who could hack into your system or something like that so you always want debug turned to false in production and you can see that Django says that here - they say security warning don't run with debug turned on in production ok and we are almost done let me scroll down to the very bottom here where I set my email username and email password information so that's at the very bottom of the settings that py file and you can see here we were using environment variables that's what we used earlier in the series whenever we added this functionality but now I'm using that config file instead so instead of OS dot environment I'm just gonna say config dot get and we will keep that as email user and instead of OS dot environed I get that is config dot git and now I will save our settings not py file by hitting ctrl X Y to save and enter ok so now that we've updated our settings not py file let me clear my screen here now at this point I'm going to pause the video and I'm going to go back into my configuration JSON file and I'm going to put in my email username and my email password and then I'm going to start the video back up so that whenever we actually test this in production and we can see that the emails actually work when we try to reset our password so I'm going to go ahead and do that now ok so I went back into my configuration file and I put in my information for my email username and password you'll have to go in and do your information there but now that should be it like we should be ready to go it should be fully deployed at this point so now all we need to do is a couple more commands here so we want to disallow the port 8000 that we were using to test earlier with our firewall so what I'm going to do is a sudo ufw delete that allow so delete allow on port 8000 and so we can see that the rule was deleted and now we want to allow HTTP traffic so I'm gonna say sudo ufw allow HTTP forge slash TCP so I'll run that ok and with that done now we can restart our Apache server and it should be good to go so I will say sudo service Apache to restart so let's restart that and I'll clear my screen okay so at this point if we did everything correctly then our site should now be live so if we pull back up our browser and here before we were at port 8000 if I try to reload that page at port 8000 now it shouldn't give me anything so we can see up here it's spinning there's stuff on the screen here but that's just from before if we let this wait long enough it'll say the site can't be reached but if we take off that port 8000 hopefully we didn't have any typos and our configurations or settings and it should work okay so we can see that this looks promising we kind of have our website here so now let's test the functionality so let's try to first create a user so I'm going to create a user called deployed user and I'll do an email at deployed user at test com put in a sample password here and confirm that so sign up okay so we got an error here when we tried to create that user so that means that somewhere along the lines we either forgot a step or we made a typo somewhere now if debug was set to true in our settings then there would be a lot more information here as to what exactly went wrong but since debug is set to false we can see that this is a very vague err it just says server error 500 now like I said before you never want debug set to true when you're working with a live website because if you have an error like this you don't want just any random person to see all that detailed error information because it can give a lot of information about your back-end server and leave you more vulnerable to future attacks but if we have an error like this then how do we go about debugging this well if you're on a live server or working on a live website then I would recommend setting up a test server and testing everything there where you can set debug equal to true that's not open to the public now since our website here isn't you know available for everyone just yet and we don't even have a domain name I'm just going to go back to our site and set debug equal to true so that we can see what this is doing but if I was actually working on a real website then I would probably setup a completely different test server or maybe just open this up on a specific port and then set debug equal to true but since this isn't completely live yet then it's okay to do it this way so I'm going to say sudo nano and we will open back up our settings here so settings dot py and I will scroll down here and set debug equal to true that has to be capitalized there and I will save that file and now let's restart our Apache server so to do that we can say sudo service Apache to restart so now if we go back to our page and try this again so I'll fill out everything that I just did so deployed user at test comm and then put in a password so let's sign up and now we have more detailed error information so we can see here that it says attempt to write read only database so that leads me to believe that it is a permissions err with our database so if we go back to our server then let me clear this out if I do an LS - la then we can see the permissions here so I'm going to do that on our project so our DB dot sequel Lite this is our database file so this is the apache group here and the group can write to that a base so that doesn't seem to be the problem if I do an LS - LA and my current directory then we can see that we have the apache group owns this directory but it doesn't have write permissions so the parent directory also has to have write permissions for that database so that is most likely the problem there so if instead I say sudo chmod 775 on Django project remember this is the user here this is the group so this will give the group read write and execute permissions there with that seven in the second spot so if I run that and now again let me restart the Apache server and now let's try testing our website again so hopefully this will work and we don't have to make any more changes so deployed user employed user at test comm fill out password there and sign up okay and it looks like that worked ok so now let's also test all of the other functionality as well so let's log in with that deployed user that we just created okay so we can log in so that's good we can go to our profile and let's try to create a post so I'll say test post ok so that works let's try to update a post test update post that works let's delete one that works as well let's go to our profile and try to upload a new picture ok so that is working for us let's try to log out ok so that is working lastly let's try the admin page let's see query MS is my admin user okay so my admin page is working as well so lastly I'm going to go back to the site and I'm going to logout now the one thing that wasn't working before was the password reset but like I said if you went in and you put your email username and password into that configuration file that we loaded into our settings then this should now work so I'm going to try this out I'm going to send a reset password to my email address and we can see here that it looks like it worked it said an email has been sent with instructions to reset your password and I actually have my email opened up in another browser over here if I reload my email then we can see that we have an email that says password reset on and right now we just have the IP address if we had a domain name here then that would be the domain name so let's click on that password reset link and we can see that looks like it works so I'm going to put in a new password here and then try to sign in with that new password so that was core EMS as the username and then I'll put in a new password okay so all of that functionality seems to be working so now we have a fully deployed fully functional Django application that we deployed to a Linux server now if you are deploying your own Django application then I would also recommend going to Google and typing in Django deployment checklist and the first result should be from their website they have a deployment checklist on their web site here of things that you can go down through and check so if we just kind of scroll through here then we can see a couple of things so like critical settings secret key the secret key should be either an environment variable or from a file and we put it in a file so that's good you should have you should never enable debug and production we have had that turned off actually that's good that I thought of that because we actually need to go back and disable that so I won't do it right now just to wind this video down but definitely go back in and set debug equal to false once you're done debugging your application and you can see that there's just all kinds of different checks that we can make so here's the aloud host there's some stuff about caches and databases so it says database connection parameters should be exactly like your secret key either put them in environment variables or in a configuration file just like we did so things like that this checklist will give you a good bit of things to go through and check and make sure that you did everything properly for deploying your application to production okay so let me go back to the blog here and go back here to the main page okay so now we've deployed our django application to our server and it's accessible through the IP address of our server now there's still a lot more that we could do with this in the future if you're interested so right now we only have an IP address but if you want then I can also walk through the process of buying a domain name and how to get the domain name to go to this server that we've set up we could also see how to add SSL certificates so that we can have an HTTP domain that's actually something that I still need to do for my personal website as well now after I record this video I'm going to delete the lenôtre server so if you go to this IP address that I have here then you probably won't see this website that we just deployed and that is why it's because I deleted it I'll spin up another server with these same parameters whenever we're ready to record future videos on this blog actually let me go ahead and delete that server right now that way you can see how to do it if you were following along and using the node as well and you want to delete the server also so that you're not charged for it so what we can do is I'll just log in here using my account it logged me out because of how much time we were away now here is the server that we created in this tutorial this django server now to delete this it's just as simple as clicking on your linen and going to settings and then in settings we can come down here to delete the node and if we click delete now it gives you a warning here that deleting a Linode server will result in permanent data loss so everything that we did to our server is going to be lost so I will click delete and then it'll ask us if we're sure click delete and that server is gone so it's no longer charging us money for that Linode server now like I said at the beginning of this video one owed was actually kind enough to sponsor this tutorial and I've used the node for many years and have recommended them to people long before I ever had any sponsors so if you get a chance I would highly recommend giving them a shot so like we saw in this video they have this really nice new cloud manager that makes spinning up a server fast and easy you can also choose from available images or you can even upload your own custom image if that's something that you'd like to do and if you're doing something that is fairly common then they even have stacks scripts that allow you to spin up a server with all of the relevant software ready to go so for example if you're making a wordpress site or something like that then you can simply choose their WordPress stack script that spins up a server with WordPress ready to go so if you were to do something like that you would come in here and go to create one node we could go to create from stack script go to the node stats stack scripts and we can see that they have a WordPress server here that would already have all of that ready to go as soon as it spins up so it's things like that make this a really nice platform to work on they also have nine data centers around the world so far and they have two more set to open in 2019 so no matter where you are you should be able to spin up a server close to your audience so if you want to check them out then feel free to use my referral link in the description section below and you can get twenty dollars of credit applied to your account to try them out okay so with that said that is going to do it for this video hopefully now you have a pretty good idea for how you can deploy a django application to your own linux server like I said before this option takes a little more effort than some other options out there but having your own private server gives you so much more flexibility and room for growth with your application doing it this way also provides terrific knowledge for learning more about back in Linux systems which is really sought after with a lot of people in the industry and it's one of those things where if you have it on a job application it's really going to look good but if anyone has any questions about what we covered in this video then feel free to ask in the comment section below and I'll do my best to answer those and if you enjoy these tutorials and would like to support them then there are several ways you can do that the easiest ways to simply like the video and give it a thumbs up and also it's a huge help to share these videos with anyone who you think would find them useful and if you have the means you can contribute through patreon and there's a link to that page in the description section below be sure to subscribe for future videos and thank you all for watching

Другие видео автора — Corey Schafer

Ctrl+V

Экстракт Знаний в Telegram

Экстракты и дистилляты из лучших YouTube-каналов — сразу после публикации.

Подписаться

Дайджест Экстрактов

Лучшие методички за неделю — каждый понедельник