我有一些複雜的業務邏輯,我放在一個自定義模型管理器中。管理器方法返回值的元組而不是查詢集。這被認爲是不好的做法?如果是的話,推薦的方法是什麼。我不想要View中的邏輯,而Django沒有服務層。另外,我的邏輯需要潛在地執行多個查詢。從Django Manager方法而不是查詢集返回元組是否是不好的做法?
邏輯需要選擇一個最接近當前時間的事件,再加上任何一方的3個事件。放置在模板中時,知道最接近的事件會很有幫助,因爲這是最初顯示在全屏滑塊中的事件。
當前呼叫如下:
closest_event, previous_events, next_events = Event.objects.closest()
邏輯當前確實做工精細。我即將轉換我的應用程序。在模板中將事件數據呈現爲JSON,以便在頁面加載時引導backbone.js視圖。我打算使用TastyPie將資源服務器端渲染到模板中。在重構我的代碼之前,我很高興知道我目前的方法不被認爲是不好的做法。
這就是我的應用程序。當前工作:
views.py
class ClosestEventsListView(TemplateView):
template_name = 'events/event_list.html'
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
closest_event, previous_events, next_events = Event.objects.closest()
context['closest_event'] = closest_event
context['previous_events'] = previous_events
context['next_events'] = next_events
return self.render_to_response(context)
models.py
from datetime import timedelta
from django.db import models
from django.utils import timezone
from model_utils.models import TimeStampedModel
class ClosestEventsManager(models.Manager):
def closest(self, **kwargs):
"""
We are looking for the closest event to now plus the 3 events either side.
First select by date range until we have a count of 7 or greater
Initial range is 1 day eithee side, then widening by another day, if required
Then compare delta for each event data and determine the closest
Return closest event plus events either side
"""
now = timezone.now()
range_in_days = 1
size = 0
while size < 7:
start_time = now + timedelta(days=-range_in_days)
end_time = now + timedelta(days=range_in_days)
events = self.filter(date__gte=start_time, date__lte=end_time, **kwargs).select_related()
size = events.count()
range_in_days += 1
previous_delta = None
closest_event = None
previous_events = None
next_events = None
position = 0
for event in events:
delta = (event.date - now).total_seconds()
delta = delta * -1 if delta < 0 else delta
if previous_delta and previous_delta <= delta:
# we have found the closest event. Now, based on
# position get events either size
next_events = events[:position-1]
previous_events = events[position:]
break
previous_delta = delta
closest_event = event
position += 1
return closest_event, previous_events, next_events
class Event(TimeStampedModel):
class Meta:
ordering = ['-date']
topic = models.ForeignKey(Topic)
event_type = models.ForeignKey(EventType)
title = models.CharField(max_length=100)
slug = models.SlugField()
date = models.DateTimeField(db_index=True)
end_time = models.TimeField()
location = models.ForeignKey(Location)
twitter_hashtag = models.CharField(null=True, blank=True, max_length=100)
web_link = models.URLField(null=True, blank=True)
objects = ClosestEventsManager()
def __unicode__(self):
return self.title
有趣。我永遠不會想到這樣做。就我而言,我還需要再次order_by日期。自那以後,我改變了我的代碼來返回一個合併列表,但返回一個查詢集會更可取。 – Howie 2013-03-08 01:03:46