Django3: производительность выделения функций из набора запросов Dynami c - PullRequest
0 голосов
/ 09 апреля 2020

Я просто экспериментирую с тем, как «динамически распределить функции набора запросов», и мне хотелось бы знать о проблемах производительности, с которыми я мог бы столкнуться позже.

Мои наборы запросов работают отлично, но я немного скептически к ним отношусь .

Пожалуйста, посмотрите на мой код:

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

ОБНОВЛЕНИЕ 0

Я заметил, что __init__() работает несколько раз, как я могу избежать этого?

=> я спрашивал вокруг, и это кажется нормальным поведением, потому что django использует filter() затем get()

ОБНОВЛЕНИЕ 1

У меня наконец-то менеджер, который нашел способ автоматического создания методов класса, и я опубликую ответ через минуту

1 Ответ

0 голосов
/ 11 апреля 2020

После прослушивания я понял, что моя add__fn() функция будет вызываться каждый раз, когда вызывается TodoQuerySet, поэтому я решил переместить add__fn() за пределы класса и добавить оттуда функции.

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...