Monkey patch phù hợp từng trường hợp trong Django
I. Monkey patch một model method
Ví dụ: bạn muốn override method save
của User
model trong Django mà không sửa trực tiếp User
gốc
from django.contrib.auth.models import User
original_save = User.save
def custom_save(self, *args, **kwargs):
print(f"[Custom Save] Saving user: {self.username}")
return original_save(self, *args, **kwargs)
User.save = custom_save
II. Monkey patch một view của app khác (hoặc của Django)
from django.contrib.auth.views import LoginView
original_dispatch = LoginView.dispatch
def custom_dispatch(self, request, *args, **kwargs):
print("[Custom LoginView] User is logging in")
return original_dispatch(self, request, *args, **kwargs)
LoginView.dispatch = custom_dispatch
III. Monkey patch Django Signals
Ví dụ: override xử lý mặc định của post_save
signal
from django.db.models.signals import post_save
from django.contrib.auth.models import User
def custom_user_post_save(sender, instance, created, **kwargs):
if created:
print(f"[Custom Signal] New user created: {instance.username}")
# Ngắt kết nối các signal hiện tại nếu cần
post_save.disconnect(dispatch_uid="default_user_post_save", sender=User)
# Gắn signal monkey patch
post_save.connect(custom_user_post_save, sender=User)
IV. Monkey patch một form method
Ví dụ: bạn muốn thay đổi method clean_email
trong UserCreationForm
from django.contrib.auth.forms import UserCreationForm
def custom_clean_email(self):
email = self.cleaned_data.get("email")
if not email.endswith("@mycompany.com"):
raise forms.ValidationError("Email must be a company email")
return email
UserCreationForm.clean_email = custom_clean_email
V. Monkey patch Django admin
Ví dụ: thêm log mỗi lần object được lưu trong admin
from django.contrib import admin
from django.contrib.auth.models import User
original_save_model = admin.ModelAdmin.save_model
def custom_save_model(self, request, obj, form, change):
print(f"[Admin Log] {obj} saved by {request.user}")
return original_save_model(self, request, obj, form, change)
admin.ModelAdmin.save_model = custom_save_model
VI. Gợi ý tổ chức Monkey Patch sạch sẽ
myapp/
├── monkey/
│ ├── __init__.py
│ ├── user_patch.py
│ └── view_patch.py
Trong myapp/monkey/__init__.py
:
from .user_patch import patch_user
from .view_patch import patch_login_view
def apply_monkey_patches():
patch_user()
patch_login_view()
Trong apps.py
của app bạn:
from django.apps import AppConfig
class MyAppConfig(AppConfig):
name = 'myapp'
def ready(self):
from myapp.monkey import apply_monkey_patches
apply_monkey_patches()
💡 Mẹo vặt
Tình huống | Lời khuyên |
---|---|
App bạn override chưa load | Hãy đảm bảo thứ tự cài đặt trong INSTALLED_APPS |
Gọi lại hàm gốc | Luôn backup lại hàm gốc original_func = Class.func |
Muốn patch tạm | Có thể dùng unittest.mock.patch() |
Patch không hoạt động | Kiểm tra xem ready() trong apps.py có được gọi không |
Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft
Không có bình luận