Django Diaries - Getting started
Tags: django, webdev
Published: 2020-08-02 18:28:50

I have recently started learning Django as my Back-end of choice. So to help me and any future learners, this series of notes will contain my notes and what I've learned about different parts of Django. 

Firstly I have discovered a few YouTube creators so far who have awesome Django content:
- [Corey Schafer](https://www.youtube.com/user/schafer5)
- [Dennis Ivy](https://www.youtube.com/channel/UCTZRcDjjkVajGL6wd76UnGg)
- [JustDjango](https://www.youtube.com/channel/UCRM1gWNTDx0SHIqUJygD-kQ)

## Getting Started  
The first step is to install everything needed to start working with Django.
- I will assume you have python an pip installed. 
```
pip install django
pip install virtualenv
```
We can start a project using the django CLI
```
django-admin startproject project_name
```

## Project Structure
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/t5t73mt2w689joo4shlk.jpg)

Your project will look like this. You will have another folder inside with your app name and a 'manage.py' file.

- The `manage.py` file gives you command line commands to perform actions such as starting the server and updating the database.

- Within the second 'project_name' folder you have a couple of files. 
    - The `__init__.py` tells python that it's a python package. 
    - `settings.py` this allows you to configure the project.
    - `urls.py` this is where routing happens and takes the user to other places
    - `wsgi.py` is how the server communicates with the project. 
You won't have to touch the init file or the wsgi file.

### making a virtual environment

For bigger python projects I prefer to make a virtual environment. This allows you to install packages only on that project. 

You can create one in python for your Django project.

> In terminal
```
virtualenv env 
env\Scripts\activate.bat
```
For Mac I'm pretty sure it's bin/activate

### Running the server 
You can start the server, and view the default landing page with the command given by the 'manage.py' file.
```
python manage.py runserver
```
This will tell you about unapplied migrations, but ignore that for now. You should see that your sever is running on localhost:8000

If you now visit `localhost:8000/admin` you should see the admin login panel. You won't be able to access that just yet but this is handled by the urls file.
```
from django.contrib import admin
from django.urls import path

urlpatterns = [
    path('admin/', admin.site.urls)
]
```
This bit of code allows django to send the user to 'admin.site.urls' when they visit /admin. This is how you handle routes in django.

## Apps

You have now created a project. To start your website you create apps which handle separate functionality. Each app does something different, you can have multiple in one project (SoC).
```
python manage.py startapp blog
```
Your project directory will now look something like this:
(db.sqlite3 was generated when you ran the server)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/1ycqp2qcp7djo4dn3l4b.jpg)

- `admin.py` - this is where you add models to the admin site.
- `apps.py` - Holds the name of the app this is added to settings.
- `migrations` - the migrations folder holds info about the state of the database. You won't need to do anything here.
- `models.py` - This is were you define your database schema.
- `test.py`  - This can be used for unittests.
- `views.py` - Views is where you define what the user sees.

#### Let's create our first View
> Views.py
```
from django.shortcuts import render
from djagno.http import HttpResponse

def home(request):
    return HttpResponse("<h1>Hello World</h1>
```
We can now map a url to this view, which will render 'Hello World' on the screen. To do this we create a new file in the app directory called `urls.py`

This will be very similar to the project urls.py:
> blog/urls.py
```
from django.urls import path
from . import views

urlpatterns = [
    path("", views.home,name="blog-home")
]
```
An empty string will be the root url of / and would map that to the home view. However we also have to add this route in the project `urls.py` as that's where django will look first. For this we need to import include: 
```
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path("blog/",include("blog.urls")),
]
```
Now when a user goes to 'localhost:8000/blog' django will check the main 'urls.py' file and map to the urls file in the blog app. It will cut this part of and go to urls in the blog app. From where the user is mapped to an empty string '' and will render the home view. 

If you open this in the browser you will see a 404 page on 'localhost:8000', if we go to 'localhost:8000/blog' you should see "hello world".

Let's say we have added another view to the blog app called 'about', we don't need to add anything more to the project urls.py as we are already matching the blog app. We just add it to the blog/urls.py file like so `path("about/",views.about,name="blog-about")`

## Templates

To start rendering HTML pages we create templates. In the blog app make a new folder called 'templates' and within that as a django convention add another folder called 'blog'. This is were we add templates. I will make one called 'home.html' :
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2iv0aho3hxm5ax7cgkyt.jpg)

In order for Django to look for templates we must add the app to the installed apps array in 'settings.py'.
Navigate to blog/apps.py and you will see the name you add to settings: 
```
INSTALLED_APPS = [
    'blog.apps.BlogConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
```
We can create regular HTML pages in the template and add variables from context via the DTL (Django template language) syntax; this is very similar to Jinja.
- Any code that is repeated through out templates can be added to a base.html file and then inherited. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/yv6qrjq0lz5mp2eult4s.jpg)

Here I have everything that will be repeated. You can them extend this base and add extra content between the blocks:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ffafujxtll4eoebyd85t.jpg)

You can now render the template from the blog view, using the render function:

```
from django.shortcuts import render
from django.http import HttpResponse

def home(req):
    return render(req, "blog/home.html")
```

We can pass information to the template by passing context to the render method.

```
posts = [
   {
      "author":"Richard",
      "title":"New blog"
   },
   {
      "author":"Steve",
      "title":"This is my new blog post"
   }
]


def home(req):
   context = {
     'posts':posts
   }
   return render(req, "blog/home.html", context)
```

We use DTL to access the variables 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/9nxud71dpnxq5muy9r33.jpg)

#### Adding Static Files

Static files are stored in a static folder in the app. I will add my CSS file like this:

project_name > blog > static > blog > main.css

To add this to the base template we first load the static files in the top:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/t01a0d88jjtjj9fa0wec.jpg)
Then Link the CSS:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vku1nkkmstjw1et6zatw.jpg)

## Using the admin page
If recall visiting 'localhost:8000/admin' takes you to the admin page, but we couldn't quite log in. We need to create an admin user in our terminal:
```
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
```
If we run createsuperuser without making migrations first it will throw an error. Migrations create updates to the database. This will ask you to add a username and a password.

Here you will be able to see all the models and tables, along with users. 



Thank you for reading part one. I will be posting more as I learn. 


-----

✨If you would like to follow my day to day development journey be sure to check my [Instagram](https://www.instagram.com/me_richard1/).