Moving Forward - Lesson 2
Tags: django, python, beginners
Published: 2019-06-19 07:04:23

1. [Get Familiar](#familiarize)
2. [Database](#database)
3. [Apps](#apps)
4. [Homepage](#homepage)

## Get Familiar<a name="familiarize"></a>
I believe you either have a Python IDE or a code editor. I use Pycharm. Many people like VS Code. If you don't, go and download one before moving on.

Hoping you have a Code Editor now, open your project in your editor. You might want to get familiar with the files and folders in your project. 

![files and folders in the project](https://thepracticaldev.s3.amazonaws.com/i/fyasui07xytrxvrj5gf7.png)<figcaption>Some really random files and stuff</figcaption>
You might recognize the ***'manage.py'*** file, as it was the one we used when we wanted to run the server. You should have a file named ***'db.sqlite3'***. This is the database file. It was automatically generated when we run the server. Other database services could be used - like Postgres, MySQL. However, we'd be working with the default. Later on, we could discuss setting up a Postgres Database.

There is the ***'\_\_init\_\_.py'*** which just identifies the ***'awesome'*** directory as a group of python files, or what we can call a module. The ***'settings.py'*** file contains the settings for our Django project. We'd be diving into it as we move on.

![Database settings in settings.py](https://thepracticaldev.s3.amazonaws.com/i/fgjcb0x1vm1wl8buk2ge.png)<figcaption>A section of settings.py showing Database settings</figcaption>
Then, we have ***'urls.py'*** which contains the URLs that our site would make use of. If you view it now, you see some comment and then one ***'urlpattern'***, which is: 

    urlpatterns = [
        path('admin/', admin.site.urls),
    ]

If you run your server now, make sure your virtual environment is active. Remember, to run the server:

    /awesome$ python manage.py runserver
And then visit 127.0.0.1:8000/admin, you should see a sign in page that looks like:

![Django admin page](https://thepracticaldev.s3.amazonaws.com/i/y8vg39qcts24wllcpajc.png)<figcaption>Eat an apple for getting this far 🍏</figcaption>
Lastly, we have the ***'wsgi.py'*** file. 

>The Web Server Gateway Interface (WSGI) is a simple calling convention for web servers to forward requests to web applications or frameworks written in the Python programming language. [From Wikipedia](https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface)

In case you're curious, you would find extra information online. However, we won't be toying with this file much. I doubt we'd ever touch it.

Before moving forward, we'd be renaming the folder up-top to ***'awesome-project'*** so as to differentiate it from the one that contains the ***'urls.py'*** and other files.

![folder name changed](https://thepracticaldev.s3.amazonaws.com/i/1mhviylwtqsnsff3manx.png)<figcaption>Renaming the wrong one would break everything😭</figcaption>

## Database<a name="database"></a>
The database is, well the database. Stores information, data and a whole bunch of things. The first task we would be performing with the database is creating a ***'superuser'***. A superuser has 'ultimate level access' to the entire project. Make sure you're careful with your superuser account. To create one, run:

    /awesome-project$ python manage.py createsuperuser
If you do this at this point, you would get a bunch of errors. Well, that's because the database hasn't been prepared to receive the information. Django has a nice way of managing the databases with its ***migrations***. If a change that should be reflected in the database is performed, Django requests you to ***'makemigrations'*** and then ***'migrate'***. Unapplied migrations always show up. Similar to:

    You have 17 unapplied migration(s). Your project may not work 
    properly 
    until you apply the migrations for app(s): admin, auth, contenttypes, 
    sessions.
    Run 'python manage.py migrate' to apply them.

To makemigrations, run:

    /awesome-project$ python manage.py makemigrations
If changes are detected, it prepares it for migration.

To apply the migrations, run:

    /awesome-project$ python manage.py migrate
You get something like:

    Operations to perform:
      Apply all migrations: admin, auth, contenttypes, sessions
    Running migrations:
      Applying contenttypes.0001_initial... OK
      Applying auth.0001_initial... OK
      Applying admin.0001_initial... OK
      Applying admin.0002_logentry_remove_auto_add... OK
      Applying admin.0003_logentry_add_action_flag_choices... OK
      Applying contenttypes.0002_remove_content_type_name... OK
      Applying auth.0002_alter_permission_name_max_length... OK
      Applying auth.0003_alter_user_email_max_length... OK
      Applying auth.0004_alter_user_username_opts... OK
      Applying auth.0005_alter_user_last_login_null... OK
      Applying auth.0006_require_contenttypes_0002... OK
      Applying auth.0007_alter_validators_add_error_messages... OK
      Applying auth.0008_alter_user_username_max_length... OK
      Applying auth.0009_alter_user_last_name_max_length... OK
      Applying auth.0010_alter_group_name_max_length... OK
      Applying auth.0011_update_proxy_permissions... OK
      Applying sessions.0001_initial... OK
This means you have successfully migrated your changes.
Now, try creating your superuser again

    /awesome-project$ python manage.py createsuperuser
    Username: we-awesome    
    Email address: hello@awesome.us
    Password: DjangoPass
    Password (again): DjangoPass
    Superuser created successfully.
> Note: I strongly advise you set a strong password. I'm only using this because it's for a tutorial. In real life projects. A strong password and a real email address are essential.

Now run your server again, visit the admin page via 127.0.0.1:8000/admin and login with your details.

![Django's admin page](https://thepracticaldev.s3.amazonaws.com/i/2k99awm4f17bi7cppr34.png)
<figcaption>Another apple for you, or maybe an orange🍊</figcaption>

One thing you should know is, you can change the link to the admin page. so if you want to change it from ***127.0.0.1:8000/admin*** to ***127.0.0.1:8000/some-random-text***, just go the ***urls.py*** file and change it. 

![Changed url to admin page](https://thepracticaldev.s3.amazonaws.com/i/1d4f7drxkezy8670h8sd.png)
<figcaption>Previous and current line 20</figcaption>
>Visiting ***127.0.0.1:8000/some-random-text*** opens the admin page; Visiting ***127.0.0.1:8000/admin*** gives a 404 error

## Apps<a name="apps"></a>
So what's the difference between a project and an app 🤔? Imagine a company with different teams. A ***marketing*** team, to well, market. A ***design team***, you're on the ***development*** team. Your best friend is on the ***administration*** team and so on. Apps could be likened to the individual teams, while the project is like the company. We could create a ***'blog'*** app to manage blogging issues. We could have a ***'profile'*** app to manage user profiles and so on.

Let us create a ***'blog'*** app.
To create an app. Open your terminal in the ***awesome-project*** directory. Make sure your virtual environment is active, then run:

    /awesome-project$ django-admin startapp blog
> As usual, you can give it another name.

I'm quite sure it worked✨✨! If not, 😟 review what you did and kindly tell me what went wrong. 

Creating the app also creates a bunch of files that we haven't seen before.

![blog app directory and content](https://thepracticaldev.s3.amazonaws.com/i/ncmnvdk9vxhuzf39jlxl.png)
<figcaption>That's a lot of strange stuff😕</figcaption>
As we move forward and encounter them, we'd discuss what they are.

We also need not forget to register the app in the ***settings.py*** file. (Actually, I forgot to register it as at the time of writing😬) To do this, open the ***apps.py*** file inside your ***'blogs'*** directory and copy the name of the class. In my case, it is ***BlogConfig***. Now go to ***settings.py***. Scroll till you see ***INSTALLED_APPS***. A number of apps are there by default, however, we want to add a new one which is ***BlogConfig***. Add a Comma after the last line before the ']', move to the next line, and add:
    40. 'blog.apps.BlogConfig'

>***blog*** - the name of the folder/app; ***apps*** - the name of the file; ***BlogConfig*** - the name of the class.

Please don't forget as I did.😬😬
## Homepage<a name="homepage"></a>
The last thing we would consider in this lesson is how to change the default homepage. By this, I mean the page that shows up on visiting 127.0.0.1:8000. To do this, we need to create a template, an HTML file.
Let us use our blog app. Create a new folder inside the blog folder and name it ***'templates'***. You could create your HTML file directly into this folder or further add subdirectories to organize the files. Either way is fine. (Edit: As an example, I created a main-site subdirectory in the templates directory. And that would reflect in my views.py.)

![Folder structure and HTML file](https://thepracticaldev.s3.amazonaws.com/i/6eujt5x3gnkfsacmn9bo.png)

> You can see both the folder arrangement and the placement of the HTML file.

Now the question is: How do I get this file to display? This is where we visit the ***view.py*** file alongside ***urls.py***. 

![minamal way to show the flow of information from the user and back](https://thepracticaldev.s3.amazonaws.com/i/wfj09is31bah6tsoo3z6.jpg)<figcaption>This is a quite skeletal representation</figcaption>
This isn't everything that happens, but this is all we need for now. So let's follow the image. The user's request takes a plane 🛬 and lands in the ***'urls.py'*** file. On getting there, it checks if the url exists. One thing you should know is our ***'urls.py'*** file deals with only the suffix. i.e It doesn't include the 127.0.0.1:8000 in itself. So keeping that in mind, if we want to replace the default home page, we add one line to ***'urls.py'***. 

    20. urlpatterns = [
    21.     path('some-random-text/', admin.site.urls),
    22.     path('',)
    23. ]
The newly added line says when they input the prefix(127.0.0.1:8000) without any suffix, come to me. The second box in our image says we should run the specified function in ***views.py***. Which means we have to create a function that returns something. And the question is what do we want to return? The HTML file. So let's go create our function. In ***views.py***, create a function, name it. It takes in at least one argument, which we would name request. And then returns the render of the HTML document on the URL that was requested. I know it's sounding confusing. Get a pen and paper, draw the different sections and try linking them up. My function looks like:

    4. def home(request):
    5.     return render(request, 'main-site/home.html')

The views automatically check the templates folder as the base directory of all HTML documents. Now to add the view to our url path, we first have to import it into the ***urls.py*** file. At the top of the file, add:

    1. from blog import views
>This imports views from the blog app

And in the url path we added earlier, add some extra information

    20. urlpatterns = [
    21.     path('some-random-text/', admin.site.urls),
    22.     path('', views.home)
    23. ]
>This invariably says that when you open the link; prefix with an empty suffix; run the function named home, which you would find in the views file. 

It is also a good practice to give names to your url's, as you would be referencing them a lot in your HTML documents. To add a name:

    20. urlpatterns = [
    21.     path('some-random-text/', admin.site.urls),
    22.     path('', views.home, name='home')
    23. ]
Save everything, and restart your server. 

![Testing changes made to site; new home page](https://thepracticaldev.s3.amazonaws.com/i/72hrh1si56fayr17t83m.png)<figcaption>Ignore the empty look</figcaption>
💃🕺🍾💃🕺🍾 I think we should celebrate. Go get yourself a bottle of whatever you like best, you've worked hard. 
You could go over it by creating another app and another url, and so on. Be curious. You have everything to gain!
I'd also take a break🍟. We continue another time.
<small>Project can be found [here](https://github.com/JonathanFarinloye/Beginners_Tutorial_Django)</small>