- Add Django extensions (sorl-thumbnail, Font Awesome, jQuery) - Add Frontend/CSS Guidelines section - Document design system (colors, components, typography, icons) - Add CSS guidelines and naming conventions - Document jQuery usage patterns - Add available pages/views table - Add template best practices section - Update Common Pitfalls for templates directory structure - Create backup of original AGENTS.md
404 lines
11 KiB
Markdown
404 lines
11 KiB
Markdown
# AGENTS.md - AI Coding Agent Guidelines
|
|
|
|
This document provides guidelines for AI coding agents working in the labhelper repository.
|
|
|
|
## Project Overview
|
|
|
|
- **Type**: Django web application
|
|
- **Python**: 3.13.7
|
|
- **Django**: 5.2.9
|
|
- **Database**: SQLite (development)
|
|
- **Virtual Environment**: `.venv/`
|
|
|
|
## Build/Run Commands
|
|
|
|
### Development Server
|
|
|
|
```bash
|
|
python manage.py runserver # Start dev server on port 8000
|
|
python manage.py runserver 0.0.0.0:8000 # Bind to all interfaces
|
|
```
|
|
|
|
### Database Operations
|
|
|
|
```bash
|
|
python manage.py makemigrations # Create migration files
|
|
python manage.py makemigrations boxes # Create migrations for specific app
|
|
python manage.py migrate # Apply all migrations
|
|
python manage.py showmigrations # List migration status
|
|
```
|
|
|
|
### Testing
|
|
|
|
```bash
|
|
# Run all tests
|
|
python manage.py test
|
|
|
|
# Run tests for a specific app
|
|
python manage.py test boxes
|
|
|
|
# Run a specific test class
|
|
python manage.py test boxes.tests.TestClassName
|
|
|
|
# Run a single test method
|
|
python manage.py test boxes.tests.TestClassName.test_method_name
|
|
|
|
# Run tests with verbosity
|
|
python manage.py test -v 2
|
|
|
|
# Run tests with coverage
|
|
coverage run manage.py test
|
|
coverage report
|
|
coverage html # Generate HTML report
|
|
```
|
|
|
|
### Django Shell
|
|
|
|
```bash
|
|
python manage.py shell # Interactive Django shell
|
|
python manage.py createsuperuser # Create admin user
|
|
python manage.py collectstatic # Collect static files
|
|
```
|
|
|
|
### Production
|
|
|
|
```bash
|
|
gunicorn labhelper.wsgi:application # Run with Gunicorn
|
|
```
|
|
|
|
## Code Style Guidelines
|
|
|
|
### Python Style
|
|
|
|
- Follow PEP 8 conventions
|
|
- Use 4-space indentation (no tabs)
|
|
- Maximum line length: 79 characters (PEP 8 standard)
|
|
- Use single quotes for strings: `'string'`
|
|
- Use double quotes for docstrings: `"""Docstring."""`
|
|
|
|
### Import Order
|
|
|
|
Organize imports in this order, with blank lines between groups:
|
|
|
|
```python
|
|
# 1. Standard library imports
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# 2. Django imports
|
|
from django.db import models
|
|
from django.contrib import admin
|
|
from django.shortcuts import render, redirect
|
|
from django.http import HttpResponse, JsonResponse
|
|
|
|
# 3. Third-party imports
|
|
import requests
|
|
from markdown import markdown
|
|
|
|
# 4. Local application imports
|
|
from .models import MyModel
|
|
from .forms import MyForm
|
|
```
|
|
|
|
### Naming Conventions
|
|
|
|
| Type | Convention | Example |
|
|
|------|------------|---------|
|
|
| Modules | lowercase_with_underscores | `user_profile.py` |
|
|
| Classes | PascalCase | `UserProfile` |
|
|
| Functions | lowercase_with_underscores | `get_user_data()` |
|
|
| Constants | UPPERCASE_WITH_UNDERSCORES | `MAX_CONNECTIONS` |
|
|
| Variables | lowercase_with_underscores | `user_count` |
|
|
| Django Models | PascalCase (singular) | `Box`, `UserProfile` |
|
|
| Django Apps | lowercase (short) | `boxes`, `users` |
|
|
|
|
### Django-Specific Conventions
|
|
|
|
**Models:**
|
|
```python
|
|
from django.db import models
|
|
|
|
class Box(models.Model):
|
|
"""A storage box in the lab."""
|
|
|
|
name = models.CharField(max_length=255)
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
updated_at = models.DateTimeField(auto_now=True)
|
|
|
|
class Meta:
|
|
verbose_name_plural = 'boxes'
|
|
ordering = ['-created_at']
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
```
|
|
|
|
**Views:**
|
|
```python
|
|
from django.shortcuts import render, get_object_or_404
|
|
from django.http import Http404
|
|
|
|
def box_detail(request, box_id):
|
|
"""Display details for a specific box."""
|
|
box = get_object_or_404(Box, pk=box_id)
|
|
return render(request, 'boxes/detail.html', {'box': box})
|
|
```
|
|
|
|
### Error Handling
|
|
|
|
```python
|
|
# Use specific exceptions
|
|
try:
|
|
result = some_operation()
|
|
except SpecificError as exc:
|
|
raise CustomError('Descriptive message') from exc
|
|
|
|
# Django: Use get_object_or_404 for model lookups
|
|
box = get_object_or_404(Box, pk=box_id)
|
|
|
|
# Log errors appropriately
|
|
import logging
|
|
logger = logging.getLogger(__name__)
|
|
logger.error('Error message: %s', error_detail)
|
|
```
|
|
|
|
### Type Hints (Recommended)
|
|
|
|
```python
|
|
from typing import Optional
|
|
from django.http import HttpRequest, HttpResponse
|
|
|
|
def get_box(request: HttpRequest, box_id: int) -> HttpResponse:
|
|
"""Retrieve a box by ID."""
|
|
...
|
|
```
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
labhelper/
|
|
├── manage.py # Django CLI entry point
|
|
├── requirements.txt # Python dependencies
|
|
├── labhelper/ # Project configuration
|
|
│ ├── settings.py # Django settings
|
|
│ ├── urls.py # Root URL routing
|
|
│ ├── wsgi.py # WSGI application
|
|
│ └── asgi.py # ASGI application
|
|
└── boxes/ # Django app
|
|
├── admin.py # Admin configuration
|
|
├── apps.py # App configuration
|
|
├── models.py # Data models
|
|
├── views.py # View functions
|
|
├── tests.py # Test cases
|
|
├── migrations/ # Database migrations
|
|
└── templates/ # HTML templates
|
|
```
|
|
|
|
## Available Django Extensions
|
|
|
|
The project includes these pre-installed packages:
|
|
|
|
- **django-mptt**: Tree structures (categories, hierarchies)
|
|
- **django-mptt-admin**: Admin interface for MPTT models
|
|
- **django-admin-sortable2**: Drag-and-drop ordering in admin
|
|
- **django-nested-admin**: Nested inline forms in admin
|
|
- **django-nested-inline**: Additional nested inline support
|
|
- **django-revproxy**: Reverse proxy functionality
|
|
- **sorl-thumbnail**: Image thumbnailing
|
|
- **Font Awesome**: Icon library (loaded via CDN)
|
|
- **jQuery**: JavaScript library (loaded via CDN)
|
|
|
|
## Frontend/CSS Guidelines
|
|
|
|
### Base Template
|
|
|
|
The project uses a base template system at `labhelper/templates/base.html`. All page templates should extend this base:
|
|
|
|
```django
|
|
{% extends "base.html" %}
|
|
|
|
{% block title %}Page Title - LabHelper{% endblock %}
|
|
|
|
{% block page_header %}
|
|
<!-- Optional page header with breadcrumbs -->
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<!-- Main page content -->
|
|
{% endblock %}
|
|
|
|
{% block extra_css %}{% endblock %}
|
|
{% block extra_js %}{% endblock %}
|
|
```
|
|
|
|
### Design System
|
|
|
|
**Color Scheme:**
|
|
- Primary gradient: `#667eea` (purple) to `#764ba2` (purple-blue)
|
|
- Success: Green gradient
|
|
- Error: Red gradient
|
|
- Background: Light gray `#f5f5f5` with gradient overlays
|
|
- Cards: White with subtle shadows
|
|
|
|
**Components:**
|
|
- **Navigation**: Glassmorphism effect with blur backdrop
|
|
- **Buttons**: Gradient backgrounds with hover lift effect
|
|
- **Cards**: White with rounded corners and box shadows
|
|
- **Tables**: Gradient headers with hover row effects
|
|
- **Alerts**: Gradient backgrounds with icons
|
|
- **Form Inputs**: Focused states with color transitions
|
|
|
|
**Typography:**
|
|
- System fonts: `-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif`
|
|
- Headings: Bold, colored
|
|
- Body: Regular, dark gray
|
|
|
|
**Icons:**
|
|
- Font Awesome 6.5.1 (CDN)
|
|
- Use semantic icons for actions
|
|
- Color: Match context or inherit from parent
|
|
|
|
**Responsive Design:**
|
|
- Mobile-first approach
|
|
- Grid layouts with `repeat(auto-fill, minmax(250px, 1fr))`
|
|
- Flexbox for component layouts
|
|
- Breakpoints handled by grid and flex-wrap
|
|
|
|
### CSS Guidelines
|
|
|
|
**Naming:**
|
|
- Use descriptive class names
|
|
- BEM pattern encouraged for complex components
|
|
- Inline styles allowed for template-specific styling
|
|
|
|
**Styles:**
|
|
- Use base template styles when possible
|
|
- Template-specific styles in `{% block extra_css %}`
|
|
- JavaScript in `{% block extra_js %}`
|
|
- Smooth transitions (0.2s - 0.3s)
|
|
- Hover effects with transform and box-shadow
|
|
|
|
**jQuery Usage:**
|
|
- Loaded in base template
|
|
- Use for interactive elements (toggles, hovers)
|
|
- Event delegation for dynamically added elements
|
|
- Focus/blur events for form inputs
|
|
|
|
### Available Pages/Views
|
|
|
|
| View Name | URL Pattern | Description |
|
|
|-----------|--------------|-------------|
|
|
| `index` | `/` | Home page with boxes grid and thing types tree |
|
|
| `box_detail` | `/box/<str:box_id>/` | List items in a specific box |
|
|
| `thing_detail` | `/thing/<int:thing_id>/` | Thing details with move-to-box form |
|
|
| `thing_type_detail` | `/thing-type/<int:type_id>/` | Thing type hierarchy and items |
|
|
| `add_things` | `/box/<str:box_id>/add/` | Form to add/edit items in a box |
|
|
| `search` | `/search/` | Search page with AJAX autocomplete |
|
|
| `search_api` | `/search/api/` | AJAX endpoint for search results |
|
|
|
|
### Template Best Practices
|
|
|
|
1. **Always extend base template**
|
|
```django
|
|
{% extends "base.html" %}
|
|
```
|
|
|
|
2. **Use block system for content injection**
|
|
- `title`: Page title tag
|
|
- `page_header`: Page header with breadcrumbs
|
|
- `content`: Main page content
|
|
- `extra_css`: Additional styles
|
|
- `extra_js`: Additional JavaScript
|
|
|
|
3. **Load required template tags**
|
|
```django
|
|
{% load static %}
|
|
{% load mptt_tags %}
|
|
{% load thumbnail %}
|
|
```
|
|
|
|
4. **Use URL names for links**
|
|
```django
|
|
<a href="{% url 'box_detail' box.id %}">
|
|
```
|
|
|
|
5. **Use icons with Font Awesome**
|
|
```django
|
|
<i class="fas fa-box"></i>
|
|
```
|
|
|
|
6. **Add breadcrumbs for navigation**
|
|
```django
|
|
<p class="breadcrumb">
|
|
<a href="/"><i class="fas fa-home"></i> Home</a> /
|
|
<a href="/box/{{ box.id }}/"><i class="fas fa-box"></i> Box {{ box.id }}</a>
|
|
</p>
|
|
```
|
|
|
|
## Testing Guidelines
|
|
|
|
- Use `django.test.TestCase` for database tests
|
|
- Use `django.test.SimpleTestCase` for tests without database
|
|
- Name test files `test_*.py` or `*_tests.py`
|
|
- Name test methods `test_*`
|
|
- Use descriptive test method names
|
|
|
|
```python
|
|
from django.test import TestCase
|
|
from .models import Box
|
|
|
|
class BoxModelTests(TestCase):
|
|
"""Tests for the Box model."""
|
|
|
|
def setUp(self):
|
|
"""Set up test fixtures."""
|
|
self.box = Box.objects.create(name='Test Box')
|
|
|
|
def test_box_str_returns_name(self):
|
|
"""Box __str__ should return the box name."""
|
|
self.assertEqual(str(self.box), 'Test Box')
|
|
```
|
|
|
|
## Files to Never Commit
|
|
|
|
Per `.gitignore`:
|
|
- `__pycache__/`, `*.pyc` - Python bytecode
|
|
- `.venv/` - Virtual environment
|
|
- `.env` - Environment variables
|
|
- `data/db.sqlite3` - Database file
|
|
- `keys/` - Secret keys
|
|
|
|
## Common Pitfalls
|
|
|
|
1. **Always activate venv**: `source .venv/bin/activate`
|
|
2. **Run migrations after model changes**: `makemigrations` then `migrate`
|
|
3. **Add new apps to INSTALLED_APPS** in `settings.py`
|
|
4. **Templates in labhelper/templates/**: The base template and shared templates are in `labhelper/templates/`. App-specific templates remain in `app_name/templates/`.
|
|
4. **Use get_object_or_404** instead of bare `.get()` calls
|
|
5. **Never commit SECRET_KEY** - use environment variables in production
|
|
|
|
## Deployment Commands
|
|
|
|
### Prepare a Full Deployment
|
|
|
|
When instructed to "Prepare a full deployment", perform the following steps:
|
|
|
|
1. **Bump container versions**: In `argocd/deployment.yaml`, increment the version numbers by 0.001 for both containers:
|
|
- `labhelper-data-loader` (initContainer)
|
|
- `labhelper` (main container)
|
|
|
|
2. **Copy database**: Copy the current development database to the data-loader preload location:
|
|
```bash
|
|
cp data/db.sqlite3 data-loader/preload.sqlite3
|
|
```
|
|
|
|
### Prepare a Partial Deployment
|
|
|
|
When instructed to "Prepare a partial deployment", perform the following step:
|
|
|
|
1. **Bump main container version only**: In `argocd/deployment.yaml`, increment the version number by 0.001 for the main container only:
|
|
- `labhelper` (main container)
|
|
|
|
Do NOT bump the data-loader version or copy the database.
|