【发布时间】:2017-12-25 12:24:06
【问题描述】:
所以我对 Django 很陌生,我昨天开始玩,一直在玩标准投票教程。
上下文
我希望能够根据自定义方法(在本例中为 Question.is_open() 方法(下图 1)的结果过滤活动问题。
我理解的问题
当我尝试使用过滤器仅访问活动问题时
questions.objects.filter(is_open=true) 它失败了。如果我理解正确,这依赖于通过模型管理器公开的查询集,该模型管理器只能根据 sql 数据库中的记录进行过滤。
我的问题
1) 我是否以大多数 pythonic/django/dry 方式来解决这个问题?我应该通过继承 models.Manager 并生成自定义查询集来公开这些方法吗? (这似乎是网上的共识)。
2) 如果我应该使用带有自定义查询集的管理器子类,我不确定代码会是什么样子。例如,我是否应该通过 cursor.execute 使用 sql(根据文档here,这似乎非常低级)?还是在 django 本身中有更好、更高级别的方法来实现这一点?
我会很感激任何关于如何解决这个问题的见解。
谢谢
马特
我的models.py
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published',default=timezone.now())
start_date = models.DateTimeField('poll start date',default=timezone.now())
closed_date = models.DateTimeField('poll close date', default=timezone.now() + datetime.timedelta(days=1))
def time_now(self):
return timezone.now()
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
def is_open(self):
return ((timezone.now() > self.start_date) and (timezone.now() < self.closed_date))
def was_opened_recently(self):
return self.start_date >= timezone.now() - datetime.timedelta(days=1) and self.is_open()
def was_closed_recently(self):
return self.closed_date >= timezone.now() - datetime.timedelta(days=1) and not self.is_open()
def is_opening_soon(self):
return self.start_date <= timezone.now() - datetime.timedelta(days=1)
def closing_soon(self):
return self.closed_date <= timezone.now() - datetime.timedelta(days=1)
[更新]
只是作为后续。我用硬编码的 SQL 字符串对默认管理器进行了子类化(仅用于测试),但是,它失败了,因为它不是属性
class QuestionManager(models.Manager):
def get_queryset(self):
return super().get_queryset()
def get_expired(self):
from django.db import connection
with connection.cursor() as cursor:
cursor.execute("""
select id, question_text, closed_date, start_date, pub_date from polls_question
where ( polls_question.start_date < '2017-12-24 00:08') and (polls_question.closed_date > '2017-12-25 00:01')
order by pub_date;""")
result_list = []
for row in cursor.fetchall():
p = self.model(id=row[0], question=row[1], closed_date=row[2], start_date=row[3], pub_date=row[4])
result_list.append(p)
return result_list
我用 active_poll_list = Question.objects.get_expired()调用方法
但我得到了例外
Exception Value:
'Manager' object has no attribute 'get_expired'
我真的不确定我是否理解为什么这不起作用。这一定是我对如何调用从管理器返回查询集的方法的误解。
任何建议将不胜感激。
谢谢
【问题讨论】:
标签: django django-models django-queryset