@chc880/everything-antigravity 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +54 -0
  3. package/assets/rules/common/coding-style.md +53 -0
  4. package/assets/rules/common/git-workflow.md +47 -0
  5. package/assets/rules/common/patterns.md +36 -0
  6. package/assets/rules/common/performance.md +21 -0
  7. package/assets/rules/common/security.md +34 -0
  8. package/assets/rules/common/testing.md +29 -0
  9. package/assets/rules/golang/coding-style.md +40 -0
  10. package/assets/rules/golang/patterns.md +44 -0
  11. package/assets/rules/golang/security.md +33 -0
  12. package/assets/rules/golang/testing.md +30 -0
  13. package/assets/rules/python/coding-style.md +52 -0
  14. package/assets/rules/python/patterns.md +39 -0
  15. package/assets/rules/python/security.md +30 -0
  16. package/assets/rules/python/testing.md +38 -0
  17. package/assets/rules/typescript/coding-style.md +44 -0
  18. package/assets/rules/typescript/patterns.md +50 -0
  19. package/assets/rules/typescript/security.md +27 -0
  20. package/assets/rules/typescript/testing.md +24 -0
  21. package/assets/skills/agent-guides/SKILL.md +40 -0
  22. package/assets/skills/agent-guides/references/architect.md +209 -0
  23. package/assets/skills/agent-guides/references/build-error-resolver.md +530 -0
  24. package/assets/skills/agent-guides/references/code-reviewer.md +102 -0
  25. package/assets/skills/agent-guides/references/database-reviewer.md +652 -0
  26. package/assets/skills/agent-guides/references/doc-updater.md +450 -0
  27. package/assets/skills/agent-guides/references/e2e-runner.md +795 -0
  28. package/assets/skills/agent-guides/references/go-build-resolver.md +366 -0
  29. package/assets/skills/agent-guides/references/go-reviewer.md +265 -0
  30. package/assets/skills/agent-guides/references/planner.md +117 -0
  31. package/assets/skills/agent-guides/references/python-reviewer.md +467 -0
  32. package/assets/skills/agent-guides/references/refactor-cleaner.md +304 -0
  33. package/assets/skills/agent-guides/references/security-reviewer.md +543 -0
  34. package/assets/skills/agent-guides/references/tdd-guide.md +278 -0
  35. package/assets/skills/backend-patterns/SKILL.md +587 -0
  36. package/assets/skills/clickhouse-io/SKILL.md +429 -0
  37. package/assets/skills/coding-standards/SKILL.md +520 -0
  38. package/assets/skills/cpp-testing/SKILL.md +322 -0
  39. package/assets/skills/django-patterns/SKILL.md +733 -0
  40. package/assets/skills/django-security/SKILL.md +592 -0
  41. package/assets/skills/django-tdd/SKILL.md +728 -0
  42. package/assets/skills/django-verification/SKILL.md +460 -0
  43. package/assets/skills/frontend-patterns/SKILL.md +631 -0
  44. package/assets/skills/golang-patterns/SKILL.md +673 -0
  45. package/assets/skills/golang-testing/SKILL.md +719 -0
  46. package/assets/skills/java-coding-standards/SKILL.md +138 -0
  47. package/assets/skills/jpa-patterns/SKILL.md +141 -0
  48. package/assets/skills/knowledge-management/SKILL.md +77 -0
  49. package/assets/skills/nutrient-document-processing/SKILL.md +165 -0
  50. package/assets/skills/postgres-patterns/SKILL.md +146 -0
  51. package/assets/skills/python-patterns/SKILL.md +749 -0
  52. package/assets/skills/python-testing/SKILL.md +815 -0
  53. package/assets/skills/security-hardening/SKILL.md +76 -0
  54. package/assets/skills/security-review/SKILL.md +494 -0
  55. package/assets/skills/security-review/cloud-infrastructure-security.md +361 -0
  56. package/assets/skills/springboot-patterns/SKILL.md +304 -0
  57. package/assets/skills/springboot-security/SKILL.md +119 -0
  58. package/assets/skills/springboot-tdd/SKILL.md +157 -0
  59. package/assets/skills/springboot-verification/SKILL.md +100 -0
  60. package/assets/skills/tdd-workflow/SKILL.md +409 -0
  61. package/assets/workflows/build-fix.md +50 -0
  62. package/assets/workflows/code-review.md +61 -0
  63. package/assets/workflows/e2e.md +65 -0
  64. package/assets/workflows/go-build.md +39 -0
  65. package/assets/workflows/go-review.md +44 -0
  66. package/assets/workflows/go-test.md +61 -0
  67. package/assets/workflows/plan.md +93 -0
  68. package/assets/workflows/python-review.md +95 -0
  69. package/assets/workflows/setup-pm.md +36 -0
  70. package/assets/workflows/tdd.md +75 -0
  71. package/assets/workflows/verify.md +81 -0
  72. package/bin/cli.js +69 -0
  73. package/lib/installer.js +301 -0
  74. package/package.json +34 -0
@@ -0,0 +1,733 @@
1
+ ---
2
+ name: django-patterns
3
+ description: Django architecture patterns, REST API design with DRF, ORM best practices, caching, signals, middleware, and production-grade Django apps.
4
+ ---
5
+
6
+ # Django Development Patterns
7
+
8
+ Production-grade Django architecture patterns for scalable, maintainable applications.
9
+
10
+ ## When to Activate
11
+
12
+ - Building Django web applications
13
+ - Designing Django REST Framework APIs
14
+ - Working with Django ORM and models
15
+ - Setting up Django project structure
16
+ - Implementing caching, signals, middleware
17
+
18
+ ## Project Structure
19
+
20
+ ### Recommended Layout
21
+
22
+ ```
23
+ myproject/
24
+ ├── config/
25
+ │ ├── __init__.py
26
+ │ ├── settings/
27
+ │ │ ├── __init__.py
28
+ │ │ ├── base.py # Base settings
29
+ │ │ ├── development.py # Dev settings
30
+ │ │ ├── production.py # Production settings
31
+ │ │ └── test.py # Test settings
32
+ │ ├── urls.py
33
+ │ ├── wsgi.py
34
+ │ └── asgi.py
35
+ ├── manage.py
36
+ └── apps/
37
+ ├── __init__.py
38
+ ├── users/
39
+ │ ├── __init__.py
40
+ │ ├── models.py
41
+ │ ├── views.py
42
+ │ ├── serializers.py
43
+ │ ├── urls.py
44
+ │ ├── permissions.py
45
+ │ ├── filters.py
46
+ │ ├── services.py
47
+ │ └── tests/
48
+ └── products/
49
+ └── ...
50
+ ```
51
+
52
+ ### Split Settings Pattern
53
+
54
+ ```python
55
+ # config/settings/base.py
56
+ from pathlib import Path
57
+
58
+ BASE_DIR = Path(__file__).resolve().parent.parent.parent
59
+
60
+ SECRET_KEY = env('DJANGO_SECRET_KEY')
61
+ DEBUG = False
62
+ ALLOWED_HOSTS = []
63
+
64
+ INSTALLED_APPS = [
65
+ 'django.contrib.admin',
66
+ 'django.contrib.auth',
67
+ 'django.contrib.contenttypes',
68
+ 'django.contrib.sessions',
69
+ 'django.contrib.messages',
70
+ 'django.contrib.staticfiles',
71
+ 'rest_framework',
72
+ 'rest_framework.authtoken',
73
+ 'corsheaders',
74
+ # Local apps
75
+ 'apps.users',
76
+ 'apps.products',
77
+ ]
78
+
79
+ MIDDLEWARE = [
80
+ 'django.middleware.security.SecurityMiddleware',
81
+ 'whitenoise.middleware.WhiteNoiseMiddleware',
82
+ 'django.contrib.sessions.middleware.SessionMiddleware',
83
+ 'corsheaders.middleware.CorsMiddleware',
84
+ 'django.middleware.common.CommonMiddleware',
85
+ 'django.middleware.csrf.CsrfViewMiddleware',
86
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
87
+ 'django.contrib.messages.middleware.MessageMiddleware',
88
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
89
+ ]
90
+
91
+ ROOT_URLCONF = 'config.urls'
92
+ WSGI_APPLICATION = 'config.wsgi.application'
93
+
94
+ DATABASES = {
95
+ 'default': {
96
+ 'ENGINE': 'django.db.backends.postgresql',
97
+ 'NAME': env('DB_NAME'),
98
+ 'USER': env('DB_USER'),
99
+ 'PASSWORD': env('DB_PASSWORD'),
100
+ 'HOST': env('DB_HOST'),
101
+ 'PORT': env('DB_PORT', default='5432'),
102
+ }
103
+ }
104
+
105
+ # config/settings/development.py
106
+ from .base import *
107
+
108
+ DEBUG = True
109
+ ALLOWED_HOSTS = ['localhost', '127.0.0.1']
110
+
111
+ DATABASES['default']['NAME'] = 'myproject_dev'
112
+
113
+ INSTALLED_APPS += ['debug_toolbar']
114
+
115
+ MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware']
116
+
117
+ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
118
+
119
+ # config/settings/production.py
120
+ from .base import *
121
+
122
+ DEBUG = False
123
+ ALLOWED_HOSTS = env.list('ALLOWED_HOSTS')
124
+ SECURE_SSL_REDIRECT = True
125
+ SESSION_COOKIE_SECURE = True
126
+ CSRF_COOKIE_SECURE = True
127
+ SECURE_HSTS_SECONDS = 31536000
128
+ SECURE_HSTS_INCLUDE_SUBDOMAINS = True
129
+ SECURE_HSTS_PRELOAD = True
130
+
131
+ # Logging
132
+ LOGGING = {
133
+ 'version': 1,
134
+ 'disable_existing_loggers': False,
135
+ 'handlers': {
136
+ 'file': {
137
+ 'level': 'WARNING',
138
+ 'class': 'logging.FileHandler',
139
+ 'filename': '/var/log/django/django.log',
140
+ },
141
+ },
142
+ 'loggers': {
143
+ 'django': {
144
+ 'handlers': ['file'],
145
+ 'level': 'WARNING',
146
+ 'propagate': True,
147
+ },
148
+ },
149
+ }
150
+ ```
151
+
152
+ ## Model Design Patterns
153
+
154
+ ### Model Best Practices
155
+
156
+ ```python
157
+ from django.db import models
158
+ from django.contrib.auth.models import AbstractUser
159
+ from django.core.validators import MinValueValidator, MaxValueValidator
160
+
161
+ class User(AbstractUser):
162
+ """Custom user model extending AbstractUser."""
163
+ email = models.EmailField(unique=True)
164
+ phone = models.CharField(max_length=20, blank=True)
165
+ birth_date = models.DateField(null=True, blank=True)
166
+
167
+ USERNAME_FIELD = 'email'
168
+ REQUIRED_FIELDS = ['username']
169
+
170
+ class Meta:
171
+ db_table = 'users'
172
+ verbose_name = 'user'
173
+ verbose_name_plural = 'users'
174
+ ordering = ['-date_joined']
175
+
176
+ def __str__(self):
177
+ return self.email
178
+
179
+ def get_full_name(self):
180
+ return f"{self.first_name} {self.last_name}".strip()
181
+
182
+ class Product(models.Model):
183
+ """Product model with proper field configuration."""
184
+ name = models.CharField(max_length=200)
185
+ slug = models.SlugField(unique=True, max_length=250)
186
+ description = models.TextField(blank=True)
187
+ price = models.DecimalField(
188
+ max_digits=10,
189
+ decimal_places=2,
190
+ validators=[MinValueValidator(0)]
191
+ )
192
+ stock = models.PositiveIntegerField(default=0)
193
+ is_active = models.BooleanField(default=True)
194
+ category = models.ForeignKey(
195
+ 'Category',
196
+ on_delete=models.CASCADE,
197
+ related_name='products'
198
+ )
199
+ tags = models.ManyToManyField('Tag', blank=True, related_name='products')
200
+ created_at = models.DateTimeField(auto_now_add=True)
201
+ updated_at = models.DateTimeField(auto_now=True)
202
+
203
+ class Meta:
204
+ db_table = 'products'
205
+ ordering = ['-created_at']
206
+ indexes = [
207
+ models.Index(fields=['slug']),
208
+ models.Index(fields=['-created_at']),
209
+ models.Index(fields=['category', 'is_active']),
210
+ ]
211
+ constraints = [
212
+ models.CheckConstraint(
213
+ check=models.Q(price__gte=0),
214
+ name='price_non_negative'
215
+ )
216
+ ]
217
+
218
+ def __str__(self):
219
+ return self.name
220
+
221
+ def save(self, *args, **kwargs):
222
+ if not self.slug:
223
+ self.slug = slugify(self.name)
224
+ super().save(*args, **kwargs)
225
+ ```
226
+
227
+ ### QuerySet Best Practices
228
+
229
+ ```python
230
+ from django.db import models
231
+
232
+ class ProductQuerySet(models.QuerySet):
233
+ """Custom QuerySet for Product model."""
234
+
235
+ def active(self):
236
+ """Return only active products."""
237
+ return self.filter(is_active=True)
238
+
239
+ def with_category(self):
240
+ """Select related category to avoid N+1 queries."""
241
+ return self.select_related('category')
242
+
243
+ def with_tags(self):
244
+ """Prefetch tags for many-to-many relationship."""
245
+ return self.prefetch_related('tags')
246
+
247
+ def in_stock(self):
248
+ """Return products with stock > 0."""
249
+ return self.filter(stock__gt=0)
250
+
251
+ def search(self, query):
252
+ """Search products by name or description."""
253
+ return self.filter(
254
+ models.Q(name__icontains=query) |
255
+ models.Q(description__icontains=query)
256
+ )
257
+
258
+ class Product(models.Model):
259
+ # ... fields ...
260
+
261
+ objects = ProductQuerySet.as_manager() # Use custom QuerySet
262
+
263
+ # Usage
264
+ Product.objects.active().with_category().in_stock()
265
+ ```
266
+
267
+ ### Manager Methods
268
+
269
+ ```python
270
+ class ProductManager(models.Manager):
271
+ """Custom manager for complex queries."""
272
+
273
+ def get_or_none(self, **kwargs):
274
+ """Return object or None instead of DoesNotExist."""
275
+ try:
276
+ return self.get(**kwargs)
277
+ except self.model.DoesNotExist:
278
+ return None
279
+
280
+ def create_with_tags(self, name, price, tag_names):
281
+ """Create product with associated tags."""
282
+ product = self.create(name=name, price=price)
283
+ tags = [Tag.objects.get_or_create(name=name)[0] for name in tag_names]
284
+ product.tags.set(tags)
285
+ return product
286
+
287
+ def bulk_update_stock(self, product_ids, quantity):
288
+ """Bulk update stock for multiple products."""
289
+ return self.filter(id__in=product_ids).update(stock=quantity)
290
+
291
+ # In model
292
+ class Product(models.Model):
293
+ # ... fields ...
294
+ custom = ProductManager()
295
+ ```
296
+
297
+ ## Django REST Framework Patterns
298
+
299
+ ### Serializer Patterns
300
+
301
+ ```python
302
+ from rest_framework import serializers
303
+ from django.contrib.auth.password_validation import validate_password
304
+ from .models import Product, User
305
+
306
+ class ProductSerializer(serializers.ModelSerializer):
307
+ """Serializer for Product model."""
308
+
309
+ category_name = serializers.CharField(source='category.name', read_only=True)
310
+ average_rating = serializers.FloatField(read_only=True)
311
+ discount_price = serializers.SerializerMethodField()
312
+
313
+ class Meta:
314
+ model = Product
315
+ fields = [
316
+ 'id', 'name', 'slug', 'description', 'price',
317
+ 'discount_price', 'stock', 'category_name',
318
+ 'average_rating', 'created_at'
319
+ ]
320
+ read_only_fields = ['id', 'slug', 'created_at']
321
+
322
+ def get_discount_price(self, obj):
323
+ """Calculate discount price if applicable."""
324
+ if hasattr(obj, 'discount') and obj.discount:
325
+ return obj.price * (1 - obj.discount.percent / 100)
326
+ return obj.price
327
+
328
+ def validate_price(self, value):
329
+ """Ensure price is non-negative."""
330
+ if value < 0:
331
+ raise serializers.ValidationError("Price cannot be negative.")
332
+ return value
333
+
334
+ class ProductCreateSerializer(serializers.ModelSerializer):
335
+ """Serializer for creating products."""
336
+
337
+ class Meta:
338
+ model = Product
339
+ fields = ['name', 'description', 'price', 'stock', 'category']
340
+
341
+ def validate(self, data):
342
+ """Custom validation for multiple fields."""
343
+ if data['price'] > 10000 and data['stock'] > 100:
344
+ raise serializers.ValidationError(
345
+ "Cannot have high-value products with large stock."
346
+ )
347
+ return data
348
+
349
+ class UserRegistrationSerializer(serializers.ModelSerializer):
350
+ """Serializer for user registration."""
351
+
352
+ password = serializers.CharField(
353
+ write_only=True,
354
+ required=True,
355
+ validators=[validate_password],
356
+ style={'input_type': 'password'}
357
+ )
358
+ password_confirm = serializers.CharField(write_only=True, style={'input_type': 'password'})
359
+
360
+ class Meta:
361
+ model = User
362
+ fields = ['email', 'username', 'password', 'password_confirm']
363
+
364
+ def validate(self, data):
365
+ """Validate passwords match."""
366
+ if data['password'] != data['password_confirm']:
367
+ raise serializers.ValidationError({
368
+ "password_confirm": "Password fields didn't match."
369
+ })
370
+ return data
371
+
372
+ def create(self, validated_data):
373
+ """Create user with hashed password."""
374
+ validated_data.pop('password_confirm')
375
+ password = validated_data.pop('password')
376
+ user = User.objects.create(**validated_data)
377
+ user.set_password(password)
378
+ user.save()
379
+ return user
380
+ ```
381
+
382
+ ### ViewSet Patterns
383
+
384
+ ```python
385
+ from rest_framework import viewsets, status, filters
386
+ from rest_framework.decorators import action
387
+ from rest_framework.response import Response
388
+ from rest_framework.permissions import IsAuthenticated, IsAdminUser
389
+ from django_filters.rest_framework import DjangoFilterBackend
390
+ from .models import Product
391
+ from .serializers import ProductSerializer, ProductCreateSerializer
392
+ from .permissions import IsOwnerOrReadOnly
393
+ from .filters import ProductFilter
394
+ from .services import ProductService
395
+
396
+ class ProductViewSet(viewsets.ModelViewSet):
397
+ """ViewSet for Product model."""
398
+
399
+ queryset = Product.objects.select_related('category').prefetch_related('tags')
400
+ permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]
401
+ filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
402
+ filterset_class = ProductFilter
403
+ search_fields = ['name', 'description']
404
+ ordering_fields = ['price', 'created_at', 'name']
405
+ ordering = ['-created_at']
406
+
407
+ def get_serializer_class(self):
408
+ """Return appropriate serializer based on action."""
409
+ if self.action == 'create':
410
+ return ProductCreateSerializer
411
+ return ProductSerializer
412
+
413
+ def perform_create(self, serializer):
414
+ """Save with user context."""
415
+ serializer.save(created_by=self.request.user)
416
+
417
+ @action(detail=False, methods=['get'])
418
+ def featured(self, request):
419
+ """Return featured products."""
420
+ featured = self.queryset.filter(is_featured=True)[:10]
421
+ serializer = self.get_serializer(featured, many=True)
422
+ return Response(serializer.data)
423
+
424
+ @action(detail=True, methods=['post'])
425
+ def purchase(self, request, pk=None):
426
+ """Purchase a product."""
427
+ product = self.get_object()
428
+ service = ProductService()
429
+ result = service.purchase(product, request.user)
430
+ return Response(result, status=status.HTTP_201_CREATED)
431
+
432
+ @action(detail=False, methods=['get'], permission_classes=[IsAuthenticated])
433
+ def my_products(self, request):
434
+ """Return products created by current user."""
435
+ products = self.queryset.filter(created_by=request.user)
436
+ page = self.paginate_queryset(products)
437
+ serializer = self.get_serializer(page, many=True)
438
+ return self.get_paginated_response(serializer.data)
439
+ ```
440
+
441
+ ### Custom Actions
442
+
443
+ ```python
444
+ from rest_framework.decorators import api_view, permission_classes
445
+ from rest_framework.permissions import IsAuthenticated
446
+ from rest_framework.response import Response
447
+
448
+ @api_view(['POST'])
449
+ @permission_classes([IsAuthenticated])
450
+ def add_to_cart(request):
451
+ """Add product to user cart."""
452
+ product_id = request.data.get('product_id')
453
+ quantity = request.data.get('quantity', 1)
454
+
455
+ try:
456
+ product = Product.objects.get(id=product_id)
457
+ except Product.DoesNotExist:
458
+ return Response(
459
+ {'error': 'Product not found'},
460
+ status=status.HTTP_404_NOT_FOUND
461
+ )
462
+
463
+ cart, _ = Cart.objects.get_or_create(user=request.user)
464
+ CartItem.objects.create(
465
+ cart=cart,
466
+ product=product,
467
+ quantity=quantity
468
+ )
469
+
470
+ return Response({'message': 'Added to cart'}, status=status.HTTP_201_CREATED)
471
+ ```
472
+
473
+ ## Service Layer Pattern
474
+
475
+ ```python
476
+ # apps/orders/services.py
477
+ from typing import Optional
478
+ from django.db import transaction
479
+ from .models import Order, OrderItem
480
+
481
+ class OrderService:
482
+ """Service layer for order-related business logic."""
483
+
484
+ @staticmethod
485
+ @transaction.atomic
486
+ def create_order(user, cart: Cart) -> Order:
487
+ """Create order from cart."""
488
+ order = Order.objects.create(
489
+ user=user,
490
+ total_price=cart.total_price
491
+ )
492
+
493
+ for item in cart.items.all():
494
+ OrderItem.objects.create(
495
+ order=order,
496
+ product=item.product,
497
+ quantity=item.quantity,
498
+ price=item.product.price
499
+ )
500
+
501
+ # Clear cart
502
+ cart.items.all().delete()
503
+
504
+ return order
505
+
506
+ @staticmethod
507
+ def process_payment(order: Order, payment_data: dict) -> bool:
508
+ """Process payment for order."""
509
+ # Integration with payment gateway
510
+ payment = PaymentGateway.charge(
511
+ amount=order.total_price,
512
+ token=payment_data['token']
513
+ )
514
+
515
+ if payment.success:
516
+ order.status = Order.Status.PAID
517
+ order.save()
518
+ # Send confirmation email
519
+ OrderService.send_confirmation_email(order)
520
+ return True
521
+
522
+ return False
523
+
524
+ @staticmethod
525
+ def send_confirmation_email(order: Order):
526
+ """Send order confirmation email."""
527
+ # Email sending logic
528
+ pass
529
+ ```
530
+
531
+ ## Caching Strategies
532
+
533
+ ### View-Level Caching
534
+
535
+ ```python
536
+ from django.views.decorators.cache import cache_page
537
+ from django.utils.decorators import method_decorator
538
+
539
+ @method_decorator(cache_page(60 * 15), name='dispatch') # 15 minutes
540
+ class ProductListView(generic.ListView):
541
+ model = Product
542
+ template_name = 'products/list.html'
543
+ context_object_name = 'products'
544
+ ```
545
+
546
+ ### Template Fragment Caching
547
+
548
+ ```django
549
+ {% load cache %}
550
+ {% cache 500 sidebar %}
551
+ ... expensive sidebar content ...
552
+ {% endcache %}
553
+ ```
554
+
555
+ ### Low-Level Caching
556
+
557
+ ```python
558
+ from django.core.cache import cache
559
+
560
+ def get_featured_products():
561
+ """Get featured products with caching."""
562
+ cache_key = 'featured_products'
563
+ products = cache.get(cache_key)
564
+
565
+ if products is None:
566
+ products = list(Product.objects.filter(is_featured=True))
567
+ cache.set(cache_key, products, timeout=60 * 15) # 15 minutes
568
+
569
+ return products
570
+ ```
571
+
572
+ ### QuerySet Caching
573
+
574
+ ```python
575
+ from django.core.cache import cache
576
+
577
+ def get_popular_categories():
578
+ cache_key = 'popular_categories'
579
+ categories = cache.get(cache_key)
580
+
581
+ if categories is None:
582
+ categories = list(Category.objects.annotate(
583
+ product_count=Count('products')
584
+ ).filter(product_count__gt=10).order_by('-product_count')[:20])
585
+ cache.set(cache_key, categories, timeout=60 * 60) # 1 hour
586
+
587
+ return categories
588
+ ```
589
+
590
+ ## Signals
591
+
592
+ ### Signal Patterns
593
+
594
+ ```python
595
+ # apps/users/signals.py
596
+ from django.db.models.signals import post_save
597
+ from django.dispatch import receiver
598
+ from django.contrib.auth import get_user_model
599
+ from .models import Profile
600
+
601
+ User = get_user_model()
602
+
603
+ @receiver(post_save, sender=User)
604
+ def create_user_profile(sender, instance, created, **kwargs):
605
+ """Create profile when user is created."""
606
+ if created:
607
+ Profile.objects.create(user=instance)
608
+
609
+ @receiver(post_save, sender=User)
610
+ def save_user_profile(sender, instance, **kwargs):
611
+ """Save profile when user is saved."""
612
+ instance.profile.save()
613
+
614
+ # apps/users/apps.py
615
+ from django.apps import AppConfig
616
+
617
+ class UsersConfig(AppConfig):
618
+ default_auto_field = 'django.db.models.BigAutoField'
619
+ name = 'apps.users'
620
+
621
+ def ready(self):
622
+ """Import signals when app is ready."""
623
+ import apps.users.signals
624
+ ```
625
+
626
+ ## Middleware
627
+
628
+ ### Custom Middleware
629
+
630
+ ```python
631
+ # middleware/active_user_middleware.py
632
+ import time
633
+ from django.utils.deprecation import MiddlewareMixin
634
+
635
+ class ActiveUserMiddleware(MiddlewareMixin):
636
+ """Middleware to track active users."""
637
+
638
+ def process_request(self, request):
639
+ """Process incoming request."""
640
+ if request.user.is_authenticated:
641
+ # Update last active time
642
+ request.user.last_active = timezone.now()
643
+ request.user.save(update_fields=['last_active'])
644
+
645
+ class RequestLoggingMiddleware(MiddlewareMixin):
646
+ """Middleware for logging requests."""
647
+
648
+ def process_request(self, request):
649
+ """Log request start time."""
650
+ request.start_time = time.time()
651
+
652
+ def process_response(self, request, response):
653
+ """Log request duration."""
654
+ if hasattr(request, 'start_time'):
655
+ duration = time.time() - request.start_time
656
+ logger.info(f'{request.method} {request.path} - {response.status_code} - {duration:.3f}s')
657
+ return response
658
+ ```
659
+
660
+ ## Performance Optimization
661
+
662
+ ### N+1 Query Prevention
663
+
664
+ ```python
665
+ # Bad - N+1 queries
666
+ products = Product.objects.all()
667
+ for product in products:
668
+ print(product.category.name) # Separate query for each product
669
+
670
+ # Good - Single query with select_related
671
+ products = Product.objects.select_related('category').all()
672
+ for product in products:
673
+ print(product.category.name)
674
+
675
+ # Good - Prefetch for many-to-many
676
+ products = Product.objects.prefetch_related('tags').all()
677
+ for product in products:
678
+ for tag in product.tags.all():
679
+ print(tag.name)
680
+ ```
681
+
682
+ ### Database Indexing
683
+
684
+ ```python
685
+ class Product(models.Model):
686
+ name = models.CharField(max_length=200, db_index=True)
687
+ slug = models.SlugField(unique=True)
688
+ category = models.ForeignKey('Category', on_delete=models.CASCADE)
689
+ created_at = models.DateTimeField(auto_now_add=True)
690
+
691
+ class Meta:
692
+ indexes = [
693
+ models.Index(fields=['name']),
694
+ models.Index(fields=['-created_at']),
695
+ models.Index(fields=['category', 'created_at']),
696
+ ]
697
+ ```
698
+
699
+ ### Bulk Operations
700
+
701
+ ```python
702
+ # Bulk create
703
+ Product.objects.bulk_create([
704
+ Product(name=f'Product {i}', price=10.00)
705
+ for i in range(1000)
706
+ ])
707
+
708
+ # Bulk update
709
+ products = Product.objects.all()[:100]
710
+ for product in products:
711
+ product.is_active = True
712
+ Product.objects.bulk_update(products, ['is_active'])
713
+
714
+ # Bulk delete
715
+ Product.objects.filter(stock=0).delete()
716
+ ```
717
+
718
+ ## Quick Reference
719
+
720
+ | Pattern | Description |
721
+ |---------|-------------|
722
+ | Split settings | Separate dev/prod/test settings |
723
+ | Custom QuerySet | Reusable query methods |
724
+ | Service Layer | Business logic separation |
725
+ | ViewSet | REST API endpoints |
726
+ | Serializer validation | Request/response transformation |
727
+ | select_related | Foreign key optimization |
728
+ | prefetch_related | Many-to-many optimization |
729
+ | Cache first | Cache expensive operations |
730
+ | Signals | Event-driven actions |
731
+ | Middleware | Request/response processing |
732
+
733
+ Remember: Django provides many shortcuts, but for production applications, structure and organization matter more than concise code. Build for maintainability.