Reputation: 363
I am learning Django by building an example app in which I have student users who can sign up for Study sections. For each student user I have a ListView which creates a table list of all of the relevant study sections for them. Each Study model is related to a Detail model which contains the details of the study section such as location and start time. For each Study I would like to add values of the associated Detail such as location and start time, but I am having trouble figuring out how to pass this information into the template from the ListView.
models.py
class Study(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='studies')
name = models.CharField(max_length=255)
condition = models.ForeignKey(Condition, on_delete=models.CASCADE, related_name='studies')
def get_details(self, study):
details = study.details.all().order_by('start_date')
return details
def __str__(self):
return self.name
class Detail(models.Model):
study = models.ForeignKey(Study, on_delete=models.CASCADE, related_name='details')
Location = models.CharField('Detail', max_length=255)
start_date = models.DateField('event start date', default=datetime.date.today)
end_date = models.DateField('event end date', default=datetime.date.today)
start_time = models.TimeField('event start time', default=now)
end_time = models.TimeField('event end time', default=now)
description = models.TextField(blank=True)
def __str__(self):
return self.Location
views.py
@method_decorator([login_required, student_required], name='dispatch')
class StudyListView(ListView):
model = Study
ordering = ('name', )
context_object_name = 'studies'
template_name = 'classroom/students/study_list.html'
def get_object(self):
return self.request.user.studies
def get_context_data(self, **kwargs):
kwargs['details'] = self.get_object().details.annotate()
return super().get_context_data(**kwargs)
def get_queryset(self):
student = self.request.user.student
student_conditions = student.conditions.values_list('pk', flat=True)
participating_studies = student.study_answers.filter(participate=True).values_list('study_id', flat=True)
queryset = Study.objects.filter(condition__in=student_conditions) \
.exclude(pk__in=participating_studies)
return queryset
template.html
{% for study,detail in zip(studies,details) %}
<tr>
<td class="align-middle">{{ study.name }}</td>
<td class="align-middle">{{ study.condition.get_html_badge }}</td>
<td class="align-middle">{{ detail.Location }} details</td>
<td class="text-right">
<a href="{% url 'students:past_study' study.pk %}" class="btn btn-primary">View Study</a>
</td>
</tr>
This current try yields the error:
Exception Value: 'RelatedManager' object has no attribute 'details'
Upvotes: 1
Views: 828
Reputation: 81
Django ORM doesn't create a Study.details
property. To access all related Detail
objects, you should write Study.detail_set
. Furthermore, Study.get_details
is a method, so it shouldn't accept a second argument – it just makes no sense.
Together, this means your code should look like this:
def get_details(self):
return self.detail_set.order_by('start_date').all()
Also, your code seems chaotic, let me know if you have more issues.
Upvotes: 2