How does one do a model query from other model function?
I have the following classes: Student, LabJournal, JournalResponse, and JournalField. I want to define a "status" function for student to determine how many questions (JournalField) they've answered (JournalResponse). The problem is the function dies without a return on the following line:
total_questions = models.JournalResponse.objects.filter(owner__exact=self.id).filter(field__journal__exact=self.assignment).count()
My guess is that I'm doing the model query wrong from within the class definition, or that you're not allowed to query from within a separate model. However I have not found anything in the docs to confirm or开发者_如何学编程 deny this, and without any errors it's difficult to debug. Running Django 1.1.
Code below:
class Student (models.Model):
user = models.ForeignKey(User, unique=True, null=False, related_name='student')
teacher = models.ForeignKey(User, null=False, related_name='students')
assignment = models.ForeignKey(LabJournal, blank=True, null=True, related_name='students')
def get_absolute_url(self):
return "/labjournal/student/%i/" % self.id
def status(self):
if self.assignment == None : return "unassigned"
percent_done = 0
total_questions = models.JournalResponse.objects.filter(owner__exact=self.id).filter(field__journal__exact=self.assignment).count()
answered_questions = models.JournalResponse.objects.filter(owner__exact=self.id).filter(field__journal__exact=self.assignment).filter(text!=None).count()
percent_done = (answered_questions/total_questions)*100
return '%d%% done' % percent_done
class JournalResponse (models.Model):
owner = models.ForeignKey(Student, null=False, related_name='responses')
field = models.ForeignKey(JournalField, null=False, related_name='responses')
text = models.TextField(null=True, blank=True)
file = models.URLField(null=True, blank=True)
class JournalField (models.Model):
TYPE_CHOICES = (
(u'HTML', u'HTML'),
(u'IF', u'ImageField'),
(u'TF', u'TextField'),
)
journal = models.ForeignKey(LabJournal, null=False, related_name='fields', help_text='Parent Journal')
ordinal = models.IntegerField(help_text='Field order')
type = models.CharField(null=False, max_length=64, choices=TYPE_CHOICES, help_text='Field type')
# Contains HTML content for HTML fields, contains the text marked "question" closest
# to and above the current field for picture and text entry fields
content = models.TextField(help_text='Should contain HTML content for HTML (question) fields or associated (previous question) HTML for ImageFields and TextFields.')
UPDATED Here's the working status method:
def status(self):
if self.assignment == None : return "unassigned"
percent_done = 0
# sets up query, but doesn't actually hit database
response_set = self.responses.filter(owner=self).filter(field__journal=self.assignment)
# force float so divide returns float
# the two count statements are the only two actual hits on the database
total_questions = float(response_set.count())
answered_questions = float(response_set.exclude(text='').count())
percent_done = (answered_questions/total_questions)*100
return '%d%% done' % percent_done
It looks like you're referring to models.JournalResponse
which shouldn't exist (AttributeError?) because in the class definition the same models
name is referring to django.db.models
You would need to refer to it via the actual model object, so JournalResponse.objects.filter()
.
In your case, you have a reverse relationship to JournalResponse
from Student
so you can simply use self.journalresponse_set.filter()
to access JournalResponse.objects.filter(student=self)
http://docs.djangoproject.com/en/dev/topics/db/queries/#following-relationships-backward
Try:
self.journalresponse_set.filter(field__journal=self.assignment)
Also, your next filter line would break as well on text!=None
. Use exclude(text=None)
syntax instead.
精彩评论