Skip to content

f-lajoc/Django-python-test

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Django Project Setup & Deployment Guide

Overview

This guide walks through setting up and running a Django web application from scratch on Windows, covering environment configuration, app creation, template rendering, form handling, user authentication, database management, static files, and deployment to Render. It is intended for developers who are new to Django or need a step-by-step reference for building their first project.


Table of Contents

  1. Prerequisites
  2. Setting Up a Virtual Environment
  3. Installing Django
  4. Starting the Development Server
  5. Creating a Django App
  6. Registering the App
  7. Templates
  8. Views
  9. URL Configuration
  10. Template Inheritance (Blocks)
  11. Form Submission
  12. Backend Validation & Flash Messages
  13. Redirect and Resolve
  14. Database Models
  15. Django Admin Panel
  16. User Authentication
  17. Login-Required Protection
  18. Static Files (CSS, JS, Images)
  19. Media & File Uploads
  20. Comments in Python
  21. .gitignore
  22. Deploying to Render

Prerequisites

Check Python Installation

Open Command Prompt and run:

python --version

If Python is not installed, download the latest version from python.org and run the installer. Check all boxes during installation, then confirm the installation by running the command above again.

Check pip Installation

pip --version

Setting Up a Virtual Environment

It is good practice to always use a virtual environment in Python projects. A virtual environment creates an isolated space for each project's dependencies, preventing version conflicts between projects.

Install virtualenv

pip install virtualenv

Create the Virtual Environment

Run this in your project terminal (e.g., VS Code):

python -m venv env

Note: You can name your environment anything, but env or venv are recommended because .gitignore templates automatically exclude them. If you use a different name, you will need to add it manually to .gitignore.

Activate the Virtual Environment

Windows:

env\Scripts\activate

Mac/Linux:

source env/bin/activate

Note: If Windows blocks the activation script, switch your terminal from PowerShell to Command Prompt and run the command again.

You will need to reactivate the virtual environment each time you return to the project.

Install Project Packages

Once the virtual environment is active, install packages as needed. Example:

pip install django

Installing Django

pip install django

Create a new Django project:

django-admin startproject projectname .

Note: The . at the end is important because without it, Django creates a nested project folder.

Do not modify the manage.py file.


Starting the Development Server

python manage.py runserver

Open the port shown in the terminal in your browser. To stop the server, press Ctrl + C.

Security tip: Change the default admin/ path in urls.py to something less predictable to reduce exposure to automated attacks:

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

Creating a Django App

python manage.py startapp appname

Registering the App

  1. Open settings.py in your project folder.
  2. Add your app name to the INSTALLED_APPS list:
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'appname',  # your app
]
  1. Create a urls.py file inside your app folder and add:
from django.urls import path

urlpatterns = []
  1. In the project's urls.py, import include and add a path for your app:
from django.urls import path, include

urlpatterns = [
    path('', include('appname.urls')),           # handles all root-level requests
    path('appname/', include('appname.urls')),   # handles requests prefixed with appname/
]

Templates

In settings.py, locate the TEMPLATES configuration block. The recommended approach is to create a templates folder inside each app directory, so each app manages its own templates.

Create HTML files inside the templates folder.


Views

Navigate to views.py in your app folder.

Django supports two types of views:

Function-Based Views

Easier to learn and suitable for most use cases:

def homepage(request):
    return render(request, 'home.html')

Class-Based Views

More concise for complex views:

from django.views import View

class ContactView(View):
    def get(self, request):
        return render(request, 'contact.html')

    def post(self, request):
        return render(request, 'contact.html')

URL Configuration

Function-Based Views

In your app's urls.py:

from django.urls import path
from appname.views import homepage, aboutpage

urlpatterns = [
    path('', homepage, name='home'),
    path('about', aboutpage, name='about'),
]

Class-Based Views

from appname.views import ContactView

urlpatterns = [
    path('contact', ContactView.as_view(), name='contact'),
]

Linking Pages in Templates

Use the {% url %} tag to reference named URL patterns:

<a href="{% url 'about' %}">About</a>

Template Inheritance (Blocks)

Create a base.html file that contains elements common to all pages (e.g., navigation, header, footer). Use blocks to define areas that child pages can override:

<!-- base.html -->
<title>{% block title %}{% endblock title %}</title>

<body>
    {% block main %}{% endblock main %}
</body>

In child pages, extend the base and fill in the blocks:

{% extends 'base.html' %}

{% block title %}Homepage{% endblock title %}

{% block main %}
    <h1>Welcome</h1>
    <a href="{% url 'about' %}">About</a>
{% endblock main %}

To include one template inside another (e.g., a testimonial section on the homepage):

{% include 'testimony.html' %}

Form Submission

Use the POST method for form submissions to keep data out of the URL. Add {% csrf_token %} inside the form to prevent cross-site request forgery:

<form method="POST">
    {% csrf_token %}
    <input type="text" name="fullname">
    <button type="submit">Submit</button>
</form>

Extract submitted data in views.py using .get() to avoid errors when a field is missing:

def contactpage(request):
    if request.method == "POST":
        fullname = request.POST.get("fullname")
        email = request.POST.get("email")
        about = request.POST.get("about")
        print(f'Submitted by: {fullname}, Message: {about}')
    return render(request, 'contact.html')

Backend Validation & Flash Messages

Django's built-in messages framework lets you send feedback from the backend to the frontend. It is included by default in INSTALLED_APPS.

In views.py:

from django.contrib import messages

def contactpage(request):
    if request.method == "POST":
        fullname = request.POST.get("fullname")
        email = request.POST.get("email")
        about = request.POST.get("about")

        if not fullname:
            messages.error(request, "Please provide your full name.")
            return render(request, 'contact.html')
        if not email or not about:
            messages.error(request, "All fields are required.")
            return render(request, 'contact.html')
        if len(fullname) < 5:
            messages.error(request, "Name is too short.")
            return render(request, 'contact.html')

        messages.success(request, "Details submitted successfully.")
    return render(request, 'contact.html')

Display messages in base.html so they appear on every page:

<div class="error_container">
    {% for msg in messages %}
        <p>{{ msg }}</p>
    {% endfor %}
</div>

Note: Django uses Jinja-style template syntax, similar to how React uses JSX.


Redirect and Resolve

Import redirect and resolve_url from Django shortcuts to navigate users after a successful form submission:

from django.shortcuts import render, redirect, resolve_url

return redirect(homepage)
# or, if the view is in a different file:
return redirect(resolve_url('home'))

Database Models

Creating Models

In models.py, create a class that extends models.Model:

from django.db import models
import uuid

class ContactMessage(models.Model):
    fullname = models.CharField(max_length=250)
    email = models.EmailField()
    about = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)  # set on creation
    updated_at = models.DateTimeField(auto_now=True)       # updated on save

    def __str__(self):
        return f'Name: {self.fullname} | Email: {self.email}'

Note: Django automatically adds an id field to every model.

To use a non-predictable UUID as the primary key:

id = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)

To link a model to a user (foreign key relationship):

from django.contrib.auth.models import User

user = models.ForeignKey(User, on_delete=models.CASCADE)

Running Migrations

Run these two commands whenever you create or modify a model:

python manage.py makemigrations
python manage.py migrate

Saving Data from a Form

In views.py, import the model and save submitted data:

from appname.models import ContactMessage

ContactMessage.objects.create(
    fullname=fullname,
    email=email,
    about=about
)

Checking for Errors

python manage.py check

Note: This command does not catch all errors but is useful for quick validation.


Django Admin Panel

Creating a Superuser

python manage.py createsuperuser

Follow the prompts for username, email, and password. The password will not be visible as you type. If prompted about password strength, type y to bypass.

Django has three user types: SuperUser, Staff User, and Normal User.

Registering a Model in Admin

In admin.py:

from django.contrib import admin
from appname.models import ContactMessage

admin.site.register(ContactMessage)

Reload the admin panel in your browser to see the registered model.


User Authentication

Signup View

from django.views import View
from django.contrib.auth.models import User
from django.contrib import messages
from django.shortcuts import render, redirect, resolve_url

class SignupView(View):
    def get(self, request):
        return render(request, 'signup.html')

    def post(self, request):
        username = request.POST.get("username")
        email = request.POST.get("email")
        firstname = request.POST.get("firstname")
        lastname = request.POST.get("lastname")
        password = request.POST.get("password")

        if not all([username, email, firstname, lastname, password]):
            messages.error(request, "All fields are required.")
            return render(request, 'signup.html')

        if len(password) < 8:
            messages.error(request, "Password must be at least 8 characters.")
            return render(request, 'signup.html')

        username = username.lower()
        email = email.lower()

        if User.objects.filter(username=username).exists():
            messages.error(request, "Username is already taken.")
            return render(request, 'signup.html')

        if User.objects.filter(email=email).exists():
            messages.error(request, "An account with this email already exists.")
            return render(request, 'signup.html')

        user = User.objects.create(
            username=username,
            email=email,
            first_name=firstname,
            last_name=lastname
        )
        user.set_password(password)
        user.save()

        return redirect(resolve_url('home'))

Note: Always set the password using set_password(), saving it directly stores it as plain text, which is a security risk.

Add the path in urls.py:

from authapp.views import SignupView

urlpatterns = [
    path('signup', SignupView.as_view(), name='signup'),
]

Login View

from django.contrib.auth import login, logout, authenticate

def login_view(request):
    if request.method == "POST":
        next_page = request.GET.get('next')
        username = request.POST.get("username")
        password = request.POST.get("password")

        if not username or not password:
            messages.error(request, "All fields are required.")
            return render(request, 'login.html')

        username = username.lower()
        user_exists = User.objects.filter(username=username).first()

        if not user_exists:
            messages.error(request, "Invalid login credentials.")
            return render(request, 'login.html')

        user = authenticate(username=username, password=password)

        if user:
            login(request, user)
            messages.success(request, "Login successful.")
            return redirect(next_page or resolve_url('home'))

    return render(request, 'login.html')

Logout View

def logout_view(request):
    logout(request)
    return render(request, 'login.html')

Conditional Navigation in Templates

Show different nav items based on whether the user is logged in:

{% if user.is_authenticated %}
    <li><a href="{% url 'logout' %}">Logout</a></li>
{% else %}
    <li><a href="{% url 'signup' %}">Sign Up</a></li>
    <li><a href="{% url 'login' %}">Login</a></li>
{% endif %}

Login-Required Protection

Restrict views to authenticated users only.

Function-Based Views

from django.contrib.auth.decorators import login_required

@login_required
def homepage(request):
    return render(request, 'home.html')

Class-Based Views

from django.contrib.auth.mixins import LoginRequiredMixin

class DashboardView(LoginRequiredMixin, View):
    def get(self, request):
        return render(request, 'dashboard.html')

In settings.py, set the login redirect URL:

LOGIN_URL = 'authapp/login'

Static Files (CSS, JS, Images)

  1. Create a static folder at the root level of your project.
  2. In settings.py, add after STATIC_URL:
import os

STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)
  1. Link your stylesheet in templates. Load static at the top of the file:
{% load static %}
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
  1. Reference images:
{% load static %}
<img src="{% static 'assets/image.png' %}" alt="description" width="250px">

For page-specific styles, define a block in base.html:

{% block styles %}{% endblock styles %}

Then in child pages (remember to load static after extends):

{% extends 'base.html' %}
{% load static %}

{% block styles %}
    <link rel="stylesheet" href="{% static 'css/about.css' %}">
{% endblock styles %}

Media & File Uploads

  1. Create a media folder at the root level.
  2. Add the following to settings.py:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
  1. In your model, use upload_to to organize uploads into subfolders:
image = models.ImageField(upload_to="products/")

Note: Handling image fields requires the Pillow library:

pip install pillow

Comments in Python

# This is a single-line comment

"""
This is a multi-line comment
or docstring.
"""

.gitignore

Create a .gitignore file at the root of your project. Visit gitignore.io, search for Django, copy the output, and paste it into your .gitignore file.


Deploying to Render

  1. Go to the Render Dashboard and click New + Web Service.
  2. Connect your GitHub repository.
  3. Set Runtime to Python.

Prepare for Deployment

Install Gunicorn (required by Render):

pip install gunicorn

Generate a 'requirements.txt' file in your project root:

pip freeze > requirements.txt

Push the changes to GitHub:

git add .
git commit -m "Added requirements.txt"
git push

Update settings.py

Update ALLOWED_HOSTS with your Render domain:

ALLOWED_HOSTS = [
    "your-app-name.onrender.com",
    "localhost",
    "127.0.0.1",
]

Set DEBUG to False for production:

DEBUG = False

Push the final changes:

git add .
git commit -m "Configured for Render deployment"
git push

About

Django project

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors