mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2026-02-05 04:25:17 -05:00
7.4 KiB
7.4 KiB
description
| description |
|---|
| Implement a full-stack feature across Django backend and Nuxt frontend |
New Feature Workflow
Implement a complete feature spanning the Django backend and Nuxt frontend.
Planning Phase
Before writing any code, create an implementation plan:
1. Feature Definition
- Goal: What problem does this feature solve?
- User Stories: Who uses it and how?
- Acceptance Criteria: How do we know it's done?
2. Technical Scope
- Backend Changes: Models, APIs, permissions
- Frontend Changes: Pages, components, state
- Data Flow: How data moves between layers
3. Implementation Order
Always implement in this order:
- Database/Models - Foundation first
- API Endpoints - Backend logic
- Frontend Components - UI building blocks
- Frontend Pages - Assembled views
- Integration - Wire it all together
- Tests - Verify everything works
Implementation Steps
Step 1: Backend - Models
# Create or modify models
# Remember: Inherit from BaseModel, add proper indexes
class NewFeature(BaseModel):
# Fields
name = models.CharField(max_length=255)
# ... other fields
class Meta:
ordering = ['-created_at']
Run migrations:
python manage.py makemigrations
python manage.py migrate
Step 2: Backend - Serializers
# backend/apps/[app]/serializers.py
class NewFeatureSerializer(serializers.ModelSerializer):
class Meta:
model = NewFeature
fields = ['id', 'name', 'created_at', 'updated_at']
read_only_fields = ['id', 'created_at', 'updated_at']
class NewFeatureDetailSerializer(NewFeatureSerializer):
# Extended fields for detail view
related_data = RelatedSerializer(many=True, read_only=True)
class Meta(NewFeatureSerializer.Meta):
fields = NewFeatureSerializer.Meta.fields + ['related_data']
Step 3: Backend - API Views
# backend/apps/[app]/views.py
class NewFeatureViewSet(viewsets.ModelViewSet):
queryset = NewFeature.objects.all()
serializer_class = NewFeatureSerializer
permission_classes = [IsAuthenticatedOrReadOnly]
def get_queryset(self):
return NewFeature.objects.select_related(
# Add related models
).prefetch_related(
# Add many-to-many or reverse relations
)
def get_serializer_class(self):
if self.action == 'retrieve':
return NewFeatureDetailSerializer
return NewFeatureSerializer
Step 4: Backend - URLs
# backend/apps/[app]/urls.py
router.register('new-features', NewFeatureViewSet, basename='new-feature')
Step 5: Backend - Tests
# backend/apps/[app]/tests/test_new_feature.py
class TestNewFeatureAPI(APITestCase):
def test_list_features(self):
response = self.client.get('/api/v1/new-features/')
self.assertEqual(response.status_code, 200)
def test_create_feature_authenticated(self):
self.client.force_authenticate(user=self.user)
response = self.client.post('/api/v1/new-features/', {'name': 'Test'})
self.assertEqual(response.status_code, 201)
Step 6: Frontend - Types
// frontend/types/newFeature.ts
export interface NewFeature {
id: string
name: string
createdAt: string
updatedAt: string
}
export interface NewFeatureDetail extends NewFeature {
relatedData: RelatedItem[]
}
Step 7: Frontend - Composables
// frontend/composables/useNewFeatures.ts
export function useNewFeatures() {
const api = useApi()
async function getFeatures(params?: Record<string, any>) {
return api<PaginatedResponse<NewFeature>>('/new-features/', { params })
}
async function getFeature(id: string) {
return api<NewFeatureDetail>(`/new-features/${id}/`)
}
async function createFeature(data: Partial<NewFeature>) {
return api<NewFeature>('/new-features/', {
method: 'POST',
body: data
})
}
return { getFeatures, getFeature, createFeature }
}
Step 8: Frontend - Components
Create necessary components following component patterns:
<!-- frontend/components/entity/NewFeatureCard.vue -->
<script setup lang="ts">
import type { NewFeature } from '~/types'
defineProps<{
feature: NewFeature
}>()
</script>
<template>
<Card interactive>
<div class="p-4">
<h3 class="font-semibold">{{ feature.name }}</h3>
<!-- Additional content -->
</div>
</Card>
</template>
Step 9: Frontend - Pages
<!-- frontend/pages/new-features/index.vue -->
<script setup lang="ts">
definePageMeta({
// middleware: ['auth'], // if needed
})
useSeoMeta({
title: 'New Features | ThrillWiki',
})
const { data, pending, error } = await useAsyncData('new-features', () =>
useNewFeatures().getFeatures()
)
</script>
<template>
<PageContainer>
<h1 class="text-3xl font-bold mb-8">New Features</h1>
<div v-if="pending" class="grid grid-cols-1 md:grid-cols-3 gap-6">
<Skeleton v-for="i in 6" :key="i" class="h-48" />
</div>
<div v-else-if="data?.results" class="grid grid-cols-1 md:grid-cols-3 gap-6">
<NewFeatureCard
v-for="feature in data.results"
:key="feature.id"
:feature="feature"
/>
</div>
<EmptyState v-else title="No features found" />
</PageContainer>
</template>
Step 10: Integration Testing
Test the full flow:
- API Test: Verify endpoints with curl or API client
- Component Test: Test components in isolation
- E2E Test: Test complete user journey
// frontend/tests/e2e/newFeature.spec.ts
import { test, expect } from '@playwright/test'
test('user can view new features', async ({ page }) => {
await page.goto('/new-features')
await expect(page.locator('h1')).toContainText('New Features')
})
test('authenticated user can create feature', async ({ page }) => {
// Login first
await page.goto('/auth/login')
// ... login steps
await page.goto('/new-features/create')
await page.fill('input[name="name"]', 'Test Feature')
await page.click('button[type="submit"]')
await expect(page).toHaveURL(/\/new-features\//)
})
Feature Checklist
Backend
- Models created with proper fields and indexes
- Migrations created and applied
- Serializers handle validation
- ViewSet has proper permissions
- Queries are optimized
- URLs registered
- Unit tests pass
Frontend
- Types defined
- Composables created for API calls
- Components follow design system
- Pages have proper SEO meta
- Loading states implemented
- Error states handled
- Responsive design verified
- Keyboard accessible
Integration
- Data flows correctly between backend and frontend
- Authentication/authorization works
- Error handling covers edge cases
- Performance is acceptable
Output Summary
After completing the feature:
## Feature: [Feature Name]
### Backend
- Model: `apps/[app]/models.py` - NewFeature
- API: `/api/v1/new-features/`
- Permissions: [describe]
### Frontend
- Page: `/new-features` (list), `/new-features/[id]` (detail)
- Components: NewFeatureCard, NewFeatureForm
- Composable: useNewFeatures
### Tests
- Backend: X tests passing
- Frontend: X tests passing
- E2E: X tests passing
### Notes
- [Any important implementation notes]
- [Known limitations]
- [Future improvements]