Project Structure

This document outlines the organization and structure of the NSGG Backend project.

Directory Structure

nsgg_backend/
├── config/                 # Project configuration
│   ├── __init__.py
│   ├── settings/          # Settings modules
│   │   ├── base.py       # Base settings
│   │   ├── local.py      # Local development settings
│   │   └── production.py # Production settings
│   ├── urls.py           # Main URL configuration
│   └── wsgi.py           # WSGI configuration
├── products/             # Products app
│   ├── api/             # API-related code
│   │   ├── serializers.py
│   │   ├── views.py
│   │   └── urls.py
│   ├── migrations/
│   ├── models.py        # Product-related models
│   ├── services.py      # Business logic
│   └── tests/           # Test files
├── users/               # Users app
│   ├── api/
│   ├── migrations/
│   ├── models.py
│   └── tests/
├── orders/              # Orders app
│   ├── api/
│   ├── migrations/
│   ├── models.py
│   └── tests/
├── common/              # Shared utilities
│   ├── exceptions.py
│   ├── middleware.py
│   └── utils.py
├── docs/               # Documentation
│   ├── api/
│   ├── architecture/
│   └── development/
├── requirements/       # Dependencies
│   ├── base.txt
│   ├── local.txt
│   ├── production.txt
│   └── testing.txt
├── scripts/           # Utility scripts
│   ├── setup.sh
│   └── deploy.sh
├── static/           # Static files
│   ├── admin/
│   └── rest_framework/
├── media/            # User-uploaded files
├── .env             # Environment variables
├── .gitignore
├── docker-compose.yml
├── Dockerfile
├── manage.py
├── pytest.ini
└── README.md

Key Components

1. Configuration (config/)

The config directory contains project-wide settings and configurations:

  • settings/: Split settings for different environments
  • urls.py: Main URL routing configuration
  • wsgi.py: WSGI application entry point

2. Applications

Products App (products/)

Handles product management:

# products/models.py
class Product(models.Model):
    name = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    category = models.ForeignKey('Category', on_delete=models.PROTECT)

Users App (users/)

Manages user accounts and authentication:

# users/models.py
class User(AbstractUser):
    email = models.EmailField(unique=True)
    phone = models.CharField(max_length=15, blank=True)

Orders App (orders/)

Handles order processing and cart management:

# orders/models.py
class Order(models.Model):
    user = models.ForeignKey('users.User', on_delete=models.PROTECT)
    status = models.CharField(max_length=20, choices=ORDER_STATUS_CHOICES)
    total = models.DecimalField(max_digits=10, decimal_places=2)

3. Common Utilities (common/)

Shared code and utilities:

# common/exceptions.py
class ApplicationError(Exception):
    def __init__(self, message, code=None):
        self.message = message
        self.code = code

# common/middleware.py
class RequestLoggingMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # Log request
        response = self.get_response(request)
        # Log response
        return response

4. API Structure

Each app follows a consistent API structure:

# products/api/views.py
class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    permission_classes = [IsAuthenticated]

# products/api/serializers.py
class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ['id', 'name', 'price', 'category']

# products/api/urls.py
router = DefaultRouter()
router.register('products', ProductViewSet)

5. Testing Structure

Each app has its own test directory:

# products/tests/test_models.py
class TestProduct:
    def test_create_product(self):
        product = ProductFactory()
        assert product.pk is not None

# products/tests/test_views.py
class TestProductAPI:
    def test_list_products(self, client):
        response = client.get('/api/v1/products/')
        assert response.status_code == 200

Code Organization Principles

  1. Separation of Concerns
  2. Models define data structure
  3. Views handle request/response
  4. Services contain business logic
  5. Serializers handle data transformation

  6. DRY (Don't Repeat Yourself)

  7. Common utilities in common/
  8. Shared mixins and base classes
  9. Reusable test fixtures

  10. Configuration Management

  11. Environment-specific settings
  12. Environment variables for secrets
  13. Separate requirement files

  14. Testing Organization

  15. Tests mirror application structure
  16. Factories for test data
  17. Fixtures for common setup

Development Guidelines

  1. Creating New Apps

    python manage.py startapp new_app
    

  2. Adding Models

    # new_app/models.py
    class NewModel(models.Model):
        name = models.CharField(max_length=255)
        created_at = models.DateTimeField(auto_now_add=True)
    

  3. API Endpoints

    # new_app/api/views.py
    class NewModelViewSet(viewsets.ModelViewSet):
        queryset = NewModel.objects.all()
        serializer_class = NewModelSerializer
    

  4. URL Configuration

    # new_app/api/urls.py
    router = DefaultRouter()
    router.register('new-model', NewModelViewSet)
    urlpatterns = router.urls
    

Deployment Structure

  1. Docker Configuration
  2. Dockerfile for building images
  3. docker-compose.yml for local development
  4. docker-compose.prod.yml for production

  5. Static Files

  6. Collected to static/
  7. Served through Nginx
  8. CDN in production

  9. Media Files

  10. Uploaded to media/
  11. S3 storage in production
  12. Local storage in development