Building a Social Media Site With Python and Django: Part 1 Landing Page and User Authentication
Tags: Programming, Web Development, Django, Python3, Python

In this tutorial, we are going to start a simple social media app. This app will be pretty similar to Twitter. Users will be able to sign up and post short text as posts and other users will be able to comment on posts. We will have likes and dislikes as well on each post. Users will have the ability to follow other users and see their followers. In this first tutorial, we will set up authentication with Django AllAuth and we will set up the landing page for guest visitors. In this tutorial we will use Bootstrap 5 which is very new and has some small changes from Bootstrap 4. Most of the classes are the same but there will be some new classes that we will use here. Let’s get started with this application.

First we need to set up a new project:

django-admin startproject socialnetwork

cd socialnetwork

python3 manage.py startapp social

python3 manage.py startapp landing

python3 manage.py migrate

python3 manage.py createsuperuser

pip install django-allauth django-crispy-forms

The social will hold all of our routes that have to do with the actual social network, and landing will hold some views to introduce new users to the application. Now let’s register these two apps:

INSTALLED_APPS = [

'landing',

'social', 'allauth',

'allauth.account',

'allauth.socialaccount',

'crispy_forms', 'django.contrib.admin',

'django.contrib.auth',

'django.contrib.contenttypes',

'django.contrib.sessions',

'django.contrib.messages',

'django.contrib.staticfiles',

'django.contrib.sites'

]

Now let’s just set up a basic view and url pattern in our landing app. First in our landing/views.py:

from django.shortcuts import render

from django.views import View

class Index(View):

def get(self, request, *args, **kwargs):

return render(request, 'landing/index.html')

Now let’s set up the url in landing/urls.py:

from django.urls import path

from landing.views import Index urlpatterns = [

path('', Index.as_view(), name='index'),

]

Now we will include this in our root urls.py:

from django.contrib import admin

from django.urls import path, include urlpatterns = [

path('admin/', admin.site.urls),

path('', include('landing.urls')),

]

Finally let’s build a landing page HTML template. This will be located at landing/templates/landing/index.html:

<h1>Index</h1>

We should be able to go to the root url of the project at localhost:8000 and view the words index on the screen.

Now with that basic set up done and now we know everything is working and set up correctly, let’s build an actual landing page, first let’s set up a base template that will have Bootstrap 5 linked:

<!doctype html>

<html lang="en">

<head>

<!-- Required meta tags -->

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Font Awesome -->

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css"> <!-- Bootstrap CSS -->

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous"> <title>Social Network</title>

</head>

<body>

{% include 'landing/navbar.html' %}

{% block content %}

{% endblock content %} <!-- Optional JavaScript; choose one of the two! --> <!-- Option 1: Bootstrap Bundle with Popper -->

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script> <!-- Option 2: Separate Popper and Bootstrap JS -->

<!--

<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js" integrity="sha384-q2kxQ16AaE6UbzuKqyBE9/u/KzioAlnx2maXQHiDX9d4/zp8Ok3f+M7DPm+Ib6IU" crossorigin="anonymous"></script>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.min.js" integrity="sha384-pQQkAEnwaBkjpqZ8RU1fF1AKtTcHJwFl3pblpTlHXybJjHpMYo79HY3hIi4NKxyj" crossorigin="anonymous"></script>

-->

</body>

</html>

Now let’s jump back into our index.html template:

{% extends 'landing/base.html' %} {% block content %}

<div class="container">

<div class="row justify-content-center mt-5">

<div class="col-md-10 col-sm-12 text-center">

<h1 class="display-2">Connect With Your Friends!</h1>

<p class="mt-3 lead">Follow people who interest you, stay up to date on the latest news and join conversations with your friends!</p>

<div class="d-flex justify-content-center mt-5">

<a href="#" class="btn btn-light mr-2">Log In</a>

<a href="#" class="btn btn-dark">Register</a>

</div>

</div>

</div>

</div>

{% endblock content %}

Setting Up AllAuth

Now with the landing page complete, it’s time to set up AllAuth for user authentication. First we need to add some settings to our settings.py file.

AUTHENTICATION_BACKENDS = [

# Needed to login by username in Django admin, regardless of `allauth`

'django.contrib.auth.backends.ModelBackend', # `allauth` specific authentication methods, such as login by e-mail

'allauth.account.auth_backends.AuthenticationBackend',

] INSTALLED_APPS = [

'landing',

'social', 'allauth',

'allauth.account',

'allauth.socialaccount',

'crispy_forms', 'django.contrib.admin',

'django.contrib.auth',

'django.contrib.contenttypes',

'django.contrib.sessions',

'django.contrib.messages',

'django.contrib.staticfiles',

'django.contrib.sites'

] SITE_ID = 1 LOGIN_REDIRECT_URL = 'index'

ACCOUNT_EMAIL_REQUIRED = True

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

Here we are setting up the site id, installed apps, and the authentication backends. This is all in the AllAuth documentation. We are also changing a few settings to redirect the user to the index page after they log in and to require an email on sign up. We are settig up the console email backend so that all emails we send will show up in the console instead of needing to set up an actual email for testing.

Finally we need to migrate the changes to the database:

python3 manage.py migrate

Now with that set up, we should have working navigation. Let’s add the login and register link to our landing page in landing/templates/landing/index.html:

{% extends 'landing/base.html' %} {% block content %}

<div class="container">

<div class="row justify-content-center mt-5">

<div class="col-md-10 col-sm-12 text-center">

<h1 class="display-2">Connect With Your Friends!</h1>

<p class="mt-3 lead">Follow people who interest you, stay up to date on the latest news and join conversations with your friends!</p>

<div class="d-flex justify-content-center mt-5">

<a href="{% url 'account_login' %}" class="btn btn-light mr-2">Log In</a>

<a href="{% url 'account_signup' %}" class="btn btn-dark">Register</a>

</div>

</div>

</div>

</div>

{% endblock content %}

Now that is all we need to do to set everything up, although our templates look very bad right now. Instead of taking the time to go through some more basic bootstrap here. I will have the templates in the root directory of the github project. You can copy those in to improve the basic styles or you can add custom styles yourself. However to override them, we do need to tell Django that we want to use the templates in the templates folder of the root directory of the project.

TEMPLATES = [

{

'BACKEND': 'django.template.backends.django.DjangoTemplates',

'DIRS': [BASE_DIR / 'templates'],

'APP_DIRS': True,

'OPTIONS': {

'context_processors': [

'django.template.context_processors.debug',

'django.template.context_processors.request',

'django.contrib.auth.context_processors.auth',

'django.contrib.messages.context_processors.messages',

],

},

},

]

Notice how in the new version of Django file paths are created a little differently. Instead of os.path.join(BASE_DIR, ‘templates’). We can just put BASE_DIR / ‘tempates’.

That is where we will end this tutorial. We will come back in the future and add more features to our application.