Full Project Structure
project/
├── apps/
│ ├── company/
│ │ ├── __init__.py
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── models.py # Database models
│ │ ├── tests/
│ │ │ ├── __init__.py
│ │ │ ├── test_models.py # Model tests
│ │ │ ├── test_views.py # View tests
│ │ ├── templates/ # Template-based views
│ │ │ └── company/
│ │ │ ├── list.html # Company list page
│ │ │ ├── detail.html # Company detail page
│ │ ├── urls.py # URL routing for templates
│ │ ├── views.py # Template-based views
│ │ ├── api/ # API-specific folder
│ │ │ ├── __init__.py
│ │ │ ├── urls.py # URL routing for APIs
│ │ │ ├── serializers.py # DRF serializers
│ │ │ ├── views.py # API views
│ │ │ ├── permissions.py # Custom API permissions
│ │ │ ├── utils.py # API-specific utilities
│ │ ├── utils/ # Reusable utilities
│ │ │ ├── __init__.py
│ │ │ ├── helpers.py # Helper functions
│ │ │ ├── validators.py # Custom validators
│ │ ├── exceptions.py # Custom exceptions
├── config/
│ ├── settings/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── development.py
│ │ ├── production.py
│ ├── urls.py # Global URL routing
│ ├── wsgi.py
│ ├── asgi.py
├── static/
├── templates/
│ └── base.html # Main template
├── media/
├── manage.py
├── .env
├── requirements.txt
└── venv/
Step-by-Step Implementation
1. Create company App
python manage.py startapp company
Move company to apps/ folder:
mv company apps/
Update INSTALLED_APPS in config/settings/base.py:
INSTALLED_APPS = [
...
'apps.company',
]
2. Define Database Models in apps/company/models.py
from django.db import models
class Company(models.Model):
name = models.CharField(max_length=255)
address = models.TextField()
email = models.EmailField(unique=True)
phone = models.CharField(max_length=15)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
Run migrations:
python manage.py makemigrations
python manage.py migrate
3. Template-Based Views and Routing
Templates Folder Setup
Create apps/company/templates/company/ and add:
list.html:
{% extends "base.html" %}
{% block title %}Company List{% endblock %}
{% block content %}
<h1>Company List</h1>
<ul>
{% for company in companies %}
<li>{{ company.name }}</li>
{% endfor %}
</ul>
{% endblock %}
detail.html:
{% extends "base.html" %}
{% block title %}Company Details{% endblock %}
{% block content %}
<h1>{{ company.name }}</h1>
<p>Address: {{ company.address }}</p>
<p>Email: {{ company.email }}</p>
<p>Phone: {{ company.phone }}</p>
{% endblock %}
Template-Based Views in views.py
from django.shortcuts import render, get_object_or_404
from .models import Company
def company_list(request):
companies = Company.objects.all()
return render(request, 'company/list.html', {'companies': companies})
def company_detail(request, pk):
company = get_object_or_404(Company, pk=pk)
return render(request, 'company/detail.html', {'company': company})
Template URLs in urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.company_list, name='company_list'),
path('<int:pk>/', views.company_detail, name='company_detail'),
]
Add apps.company.urls to config/urls.py:
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('companies/', include('apps.company.urls')),
]
4. API Development
Serializers in api/serializers.py
from rest_framework import serializers
from ..models import Company
class CompanySerializer(serializers.ModelSerializer):
class Meta:
model = Company
fields = '__all__'
Views in api/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from ..models import Company
from .serializers import CompanySerializer
class CompanyListAPI(APIView):
def get(self, request):
companies = Company.objects.all()
serializer = CompanySerializer(companies, many=True)
return Response(serializer.data)
def post(self, request):
serializer = CompanySerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
URLs in api/urls.py
from django.urls import path
from .views import CompanyListAPI
urlpatterns = [
path('', CompanyListAPI.as_view(), name='api_company_list'),
]
Add apps.company.api.urls to config/urls.py:
urlpatterns = [
...
path('api/companies/', include('apps.company.api.urls')),
]
5. Reusable Utilities
utils/helpers.py
def format_phone_number(phone):
return f"+{phone}" if not phone.startswith('+') else phone
utils/validators.py
from django.core.exceptions import ValidationError
def validate_company_name(value):
if len(value) < 3:
raise ValidationError("Company name must be at least 3 characters long.")
6. Testing
Test for Models in tests/test_models.py
from django.test import TestCase
from ..models import Company
class CompanyModelTest(TestCase):
def test_create_company(self):
company = Company.objects.create(
name="Test Company",
address="123 Test Street",
email="test@example.com",
phone="123456789"
)
self.assertEqual(str(company), "Test Company")
Run the Project
Start the server:
python manage.py runserver