Django:动态查询集函数分配性能
Django3: Dynamic queryset function allocation performance
我只是在试验如何 'dynamically allocate queryset functions' 我想知道以后可能会遇到的性能问题。
我的查询集运行良好,但我对它们有点怀疑。
请看我的代码:
settings.py:
...
TODO_PRIORITY = (
('LOW', 'Low'),
('MEDIUM', 'Medium'),
('HIGH', 'High'),
)
...
models.py
from django.db import models
from django.contrib.auth import get_user_model
from django.utils import timezone
from .manager import TodoManager
from django.conf import settings
User = get_user_model()
TODO_PRIORITY = getattr(settings, 'TODO_PRIORITY', None)
assert TODO_PRIORITY is not None, "Your settings file is missing `TODO_PRIORITY` variable"
assert isinstance(TODO_PRIORITY, tuple), "`TODO_PRIORITY` must be a tuple"
# Create your models here.
class Todo(models.Model):
class Meta:
ordering = ('start_time',)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="todos")
content = models.TextField(max_length=500, blank=False)
start_time = models.DateTimeField(default=timezone.now)
end_time = models.DateTimeField(blank=False)
priority = models.CharField(max_length=6, choices=TODO_PRIORITY, default="MEDIUM")
timestamp = models.DateTimeField(auto_now_add=True)
objects = TodoManager()
@property
def todo_id(self):
return self.id
manager.py
from django.db import models
from django.utils import timezone
from django.conf import settings
now = timezone.now()
today = now.replace(hour=0, minute=0, second=0, microsecond=0)
tomorrow = today + timezone.timedelta(days=1)
TODO_PRIORITY = getattr(settings, 'TODO_PRIORITY', None)
assert TODO_PRIORITY is not None, "Your settings file is missing `TODO_PRIORITY` variable."
assert isinstance(TODO_PRIORITY, tuple), "`TODO_PRIORITY` must be a tuple."
class TodoQueryset(models.query.QuerySet):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for priority in TODO_PRIORITY:
self.add__fn(priority)
def add__fn(self, object):
assert isinstance(object, tuple), '`TODO_PRIORITY` object must be a tuple.'
fn_name = object[1].lower()
def fn():
return self.filter(priority=object[0].upper(), start_time__gte=today)
setattr(self, fn_name, fn)
class TodoManager(models.Manager):
_queryset_class = TodoQueryset
UPDATE 0
我注意到 __init__()
运行了多次,我该如何避免?
=> 我四处询问,这似乎是一种正常行为,因为 django 使用 filter()
然后 get()
UPDATE 1
我终于让经理找到了一种自动创建 class 方法的方法,我会 post 一分钟内给出答案
四处寻找后,我意识到每次调用 TodoQuerySet
时都会调用我的 add__fn()
函数,所以我决定将 add__fn()
移到 class 之外,并且从那里添加功能。
manager.py
from django.db import models
from django.utils import timezone
from django.conf import settings
now = timezone.now()
today = now.replace(hour=0, minute=0, second=0, microsecond=0)
tomorrow = today + timezone.timedelta(days=1)
TODO_PRIORITY = getattr(settings, 'TODO_PRIORITY', None)
assert TODO_PRIORITY is not None, "Your settings file is missing `TODO_PRIORITY` variable."
assert isinstance(TODO_PRIORITY, tuple), "`TODO_PRIORITY` must be a tuple."
class TodoQuerySet(models.QuerySet):
pass
def add__fn(object):
assert isinstance(object, tuple), '`TODO_PRIORITY` object must be a tuple.'
fn_name = object[1].lower()
def fn(self):
return self.filter(priority=object[0].upper(), start_time__gte=today)
setattr(TodoQuerySet, fn_name, fn)
for priority in TODO_PRIORITY:
add__fn(priority)
TodoQueryset = TodoQuerySet
models.py
from .manager import TodoQueryset
class Todo(...):
objects = TodoQueryset.as_manager()
我只是在试验如何 'dynamically allocate queryset functions' 我想知道以后可能会遇到的性能问题。
我的查询集运行良好,但我对它们有点怀疑。
请看我的代码:
settings.py:
...
TODO_PRIORITY = (
('LOW', 'Low'),
('MEDIUM', 'Medium'),
('HIGH', 'High'),
)
...
models.py
from django.db import models
from django.contrib.auth import get_user_model
from django.utils import timezone
from .manager import TodoManager
from django.conf import settings
User = get_user_model()
TODO_PRIORITY = getattr(settings, 'TODO_PRIORITY', None)
assert TODO_PRIORITY is not None, "Your settings file is missing `TODO_PRIORITY` variable"
assert isinstance(TODO_PRIORITY, tuple), "`TODO_PRIORITY` must be a tuple"
# Create your models here.
class Todo(models.Model):
class Meta:
ordering = ('start_time',)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="todos")
content = models.TextField(max_length=500, blank=False)
start_time = models.DateTimeField(default=timezone.now)
end_time = models.DateTimeField(blank=False)
priority = models.CharField(max_length=6, choices=TODO_PRIORITY, default="MEDIUM")
timestamp = models.DateTimeField(auto_now_add=True)
objects = TodoManager()
@property
def todo_id(self):
return self.id
manager.py
from django.db import models
from django.utils import timezone
from django.conf import settings
now = timezone.now()
today = now.replace(hour=0, minute=0, second=0, microsecond=0)
tomorrow = today + timezone.timedelta(days=1)
TODO_PRIORITY = getattr(settings, 'TODO_PRIORITY', None)
assert TODO_PRIORITY is not None, "Your settings file is missing `TODO_PRIORITY` variable."
assert isinstance(TODO_PRIORITY, tuple), "`TODO_PRIORITY` must be a tuple."
class TodoQueryset(models.query.QuerySet):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for priority in TODO_PRIORITY:
self.add__fn(priority)
def add__fn(self, object):
assert isinstance(object, tuple), '`TODO_PRIORITY` object must be a tuple.'
fn_name = object[1].lower()
def fn():
return self.filter(priority=object[0].upper(), start_time__gte=today)
setattr(self, fn_name, fn)
class TodoManager(models.Manager):
_queryset_class = TodoQueryset
UPDATE 0
我注意到 __init__()
运行了多次,我该如何避免?
=> 我四处询问,这似乎是一种正常行为,因为 django 使用 filter()
然后 get()
UPDATE 1
我终于让经理找到了一种自动创建 class 方法的方法,我会 post 一分钟内给出答案
四处寻找后,我意识到每次调用 TodoQuerySet
时都会调用我的 add__fn()
函数,所以我决定将 add__fn()
移到 class 之外,并且从那里添加功能。
manager.py
from django.db import models
from django.utils import timezone
from django.conf import settings
now = timezone.now()
today = now.replace(hour=0, minute=0, second=0, microsecond=0)
tomorrow = today + timezone.timedelta(days=1)
TODO_PRIORITY = getattr(settings, 'TODO_PRIORITY', None)
assert TODO_PRIORITY is not None, "Your settings file is missing `TODO_PRIORITY` variable."
assert isinstance(TODO_PRIORITY, tuple), "`TODO_PRIORITY` must be a tuple."
class TodoQuerySet(models.QuerySet):
pass
def add__fn(object):
assert isinstance(object, tuple), '`TODO_PRIORITY` object must be a tuple.'
fn_name = object[1].lower()
def fn(self):
return self.filter(priority=object[0].upper(), start_time__gte=today)
setattr(TodoQuerySet, fn_name, fn)
for priority in TODO_PRIORITY:
add__fn(priority)
TodoQueryset = TodoQuerySet
models.py
from .manager import TodoQueryset
class Todo(...):
objects = TodoQueryset.as_manager()