diff --git a/docs/i18n/rules/vi/DOL011.md b/docs/i18n/rules/vi/DOL011.md new file mode 100644 index 0000000..8580f5b --- /dev/null +++ b/docs/i18n/rules/vi/DOL011.md @@ -0,0 +1,30 @@ +# DOL011 — Thêm `db_index=True` cho trường `ForeignKey` dùng trong `filter()` / `order_by()` + +**Mức độ mặc định:** warning · **Khả năng áp dụng:** unsafe · **Danh mục:** model-definition + +Phát hiện các khai báo `ForeignKey` (và `OneToOneField`) xuất hiện trong các lời gọi `filter()`, `exclude()` hoặc `order_by()` ở nơi khác trong cùng file, nhưng khai báo trường đó không có `db_index=True`. Django tự động tạo index cho `ForeignKey`, nhưng chỉ trên chính cột đó — các pattern xuyên file hoặc đa bảng không được phát hiện. Khi FK là trục filter chính (ví dụ `orders.filter(customer=c)`), index ngầm định thường đủ dùng; rule này kích hoạt khi có thể xác nhận tĩnh rằng FK đang được filter mà không có khai báo index tường minh — đây là trường hợp có khả năng cao nhất bị bỏ sót index. + +Khả năng áp dụng là `unsafe` vì thêm index là một thay đổi schema: trên các bảng lớn, cần tạo index đồng thời (concurrent index build) và cửa sổ deploy phù hợp. + +## Sai + +```python +class Order(models.Model): + customer = models.ForeignKey(Customer, on_delete=models.CASCADE) + # ở nơi khác: Order.objects.filter(customer=c) — chỉ dựa vào index ngầm định +``` + +## Đúng + +```python +class Order(models.Model): + customer = models.ForeignKey(Customer, on_delete=models.CASCADE, db_index=True) +``` + +## Bỏ qua (Suppress) + +```python +# django-orm-lens-disable-next-line DOL011 +``` + +Hoặc theo từng workspace trong `.vscode/settings.json`: `{"djangoOrmLens.rules": {"DOL011": "off"}}`. diff --git a/docs/i18n/rules/vi/DOL012.md b/docs/i18n/rules/vi/DOL012.md new file mode 100644 index 0000000..dcf0fd8 --- /dev/null +++ b/docs/i18n/rules/vi/DOL012.md @@ -0,0 +1,30 @@ +# DOL012 — Thêm `db_index=True` cho các trường dùng thường xuyên trong `order_by()` + +**Mức độ mặc định:** info · **Khả năng áp dụng:** unsafe · **Danh mục:** model-definition + +Phát hiện các trường model (ngoại trừ `ForeignKey` đã được DOL011 xử lý) xuất hiện làm đối số duy nhất trong các lời gọi `order_by()` từ ba lần trở lên trong cùng file, mà không có khai báo `db_index=True` hoặc `unique=True`. Sắp xếp lặp lại trên cột không có index sẽ buộc database thực hiện filesort cho mỗi query; một index sẽ chuyển điều đó thành index scan. + +Khả năng áp dụng là `unsafe` vì thêm index là một thay đổi schema. + +## Sai + +```python +class Article(models.Model): + published_at = models.DateTimeField() + # ở nơi khác: Article.objects.order_by("published_at") — từ ba lần trở lên +``` + +## Đúng + +```python +class Article(models.Model): + published_at = models.DateTimeField(db_index=True) +``` + +## Bỏ qua (Suppress) + +```python +# django-orm-lens-disable-next-line DOL012 +``` + +Hoặc theo từng workspace trong `.vscode/settings.json`: `{"djangoOrmLens.rules": {"DOL012": "off"}}`. diff --git a/docs/i18n/rules/vi/DOL013.md b/docs/i18n/rules/vi/DOL013.md new file mode 100644 index 0000000..a9478dc --- /dev/null +++ b/docs/i18n/rules/vi/DOL013.md @@ -0,0 +1,30 @@ +# DOL013 — Dùng `select_related` cho các truy cập `ForeignKey` / `OneToOneField` trong serializer + +**Mức độ mặc định:** warning · **Khả năng áp dụng:** unsafe · **Danh mục:** model-definition + +Phát hiện các trường serializer Django REST Framework (hoặc truy cập thuộc tính thông thường) duyệt qua `ForeignKey` hoặc `OneToOneField` mà không có `select_related()` tương ứng trên queryset truyền vào serializer. Mỗi lần duyệt mà không có prefetching sẽ kích hoạt một query riêng biệt cho mỗi đối tượng — đây là N+1 kinh điển xảy ra ở tầng serialization thay vì tầng view. + +Khả năng áp dụng là `unsafe` vì cần sửa queryset tại call site, có thể nằm ở một file khác. + +## Sai + +```python +class OrderSerializer(serializers.ModelSerializer): + customer_name = serializers.CharField(source="customer.name") + # queryset: Order.objects.all() — thêm một query cho mỗi order +``` + +## Đúng + +```python +# trong view +queryset = Order.objects.select_related("customer") +``` + +## Bỏ qua (Suppress) + +```python +# django-orm-lens-disable-next-line DOL013 +``` + +Hoặc theo từng workspace trong `.vscode/settings.json`: `{"djangoOrmLens.rules": {"DOL013": "off"}}`. diff --git a/docs/i18n/rules/vi/DOL014.md b/docs/i18n/rules/vi/DOL014.md new file mode 100644 index 0000000..56ce8d9 --- /dev/null +++ b/docs/i18n/rules/vi/DOL014.md @@ -0,0 +1,29 @@ +# DOL014 — Dùng `prefetch_related` cho các truy cập ngược `ForeignKey` / `ManyToManyField` + +**Mức độ mặc định:** warning · **Khả năng áp dụng:** unsafe · **Danh mục:** model-definition + +Phát hiện các truy cập FK ngược hoặc M2M (ví dụ `post.comments.all()`, `user.groups.all()`) bên trong vòng lặp hoặc serializer mà không có `prefetch_related()` tương ứng. Mỗi lần truy cập sẽ kích hoạt một query riêng biệt cho mỗi đối tượng cha. + +Khả năng áp dụng là `unsafe` vì cần thêm `prefetch_related()` tại call site của queryset. + +## Sai + +```python +for post in Post.objects.all(): + comments = post.comments.all() # một query cho mỗi post +``` + +## Đúng + +```python +for post in Post.objects.prefetch_related("comments"): + comments = post.comments.all() # chỉ hai query tổng cộng +``` + +## Bỏ qua (Suppress) + +```python +# django-orm-lens-disable-next-line DOL014 +``` + +Hoặc theo từng workspace trong `.vscode/settings.json`: `{"djangoOrmLens.rules": {"DOL014": "off"}}`. diff --git a/docs/i18n/rules/vi/DOL015.md b/docs/i18n/rules/vi/DOL015.md new file mode 100644 index 0000000..7c3b4a0 --- /dev/null +++ b/docs/i18n/rules/vi/DOL015.md @@ -0,0 +1,29 @@ +# DOL015 — Tránh lưu trữ dữ liệu văn bản hoặc nhị phân lớn trực tiếp trên model + +**Mức độ mặc định:** info · **Khả năng áp dụng:** unsafe · **Danh mục:** model-definition + +Phát hiện các khai báo `TextField` hoặc `BinaryField` không có giới hạn `max_length`, đặc biệt khi tên trường gợi ý lưu nội dung (ví dụ `body`, `content`, `data`, `blob`, `payload`). Lưu trữ payload lớn trực tiếp làm phình kích thước row, tăng I/O cho mọi query trên bảng đó, và có thể gây TOAST thrashing trong PostgreSQL. Giải pháp thông thường là chuyển payload sang object storage và chỉ lưu URL hoặc key trên model. + +Khả năng áp dụng là `unsafe` vì đây là thay đổi kiến trúc. + +## Sai + +```python +class Document(models.Model): + content = models.TextField() # không giới hạn — có thể chiếm hàng megabyte mỗi row +``` + +## Đúng + +```python +class Document(models.Model): + storage_key = models.CharField(max_length=255) # trỏ đến S3 / GCS / v.v. +``` + +## Bỏ qua (Suppress) + +```python +# django-orm-lens-disable-next-line DOL015 +``` + +Hoặc theo từng workspace trong `.vscode/settings.json`: `{"djangoOrmLens.rules": {"DOL015": "off"}}`.