-
Notifications
You must be signed in to change notification settings - Fork 10
Docs: translate model-definition rules to Vietnamese (DOL011-DOL015) #86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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"}}`. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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. | ||
|
Comment on lines
+1
to
+5
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift Translate the canonical DOL012 rule. The supplied 🤖 Prompt for AI Agents |
||
|
|
||
| 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"}}`. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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"}}`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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"}}`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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. | ||
| ``` | ||
|
Comment on lines
+1
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift Restore the canonical DOL015 content.
Replace lines 1-21 with a faithful Vietnamese translation of the canonical DOL015 page. Copy the Python blocks byte-identically; only translate prose outside the blocks. 🤖 Prompt for AI Agents |
||
|
|
||
| ## 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"}}`. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Preserve code fences byte-for-byte.
The same contract violation appears in all four pages. Keep comments inside Python code blocks unchanged while translating prose outside the fences.
docs/i18n/rules/vi/DOL011.md#L14-L14: restore the canonical comment.docs/i18n/rules/vi/DOL012.md#L14-L14: restore the canonical comment.docs/i18n/rules/vi/DOL013.md#L14-L14: restore the canonical comment.docs/i18n/rules/vi/DOL013.md#L20-L20: restore the canonical comment.docs/i18n/rules/vi/DOL014.md#L13-L13: restore the canonical comment.docs/i18n/rules/vi/DOL014.md#L20-L20: restore the canonical comment.📍 Affects 4 files
docs/i18n/rules/vi/DOL011.md#L14-L14(this comment)docs/i18n/rules/vi/DOL012.md#L14-L14docs/i18n/rules/vi/DOL013.md#L14-L14docs/i18n/rules/vi/DOL013.md#L20-L20docs/i18n/rules/vi/DOL014.md#L13-L13docs/i18n/rules/vi/DOL014.md#L20-L20🤖 Prompt for AI Agents