Помогите составить запрос к модели Django
У меня есть одна проблема. Пишу сайт с видео курсами и на html странице слева есть панель навигации с ссылками на уроки в упорядоченном виде. Ссылка на следующий урок должна отображаться в только в том случае, если домашнее задание к прошлому уроку выполнено верно (поле модели is_correct с булевыми значениями). Проблема в том, как грамотно составить запрос, который будет брать предыдущий урок, проверять его поле is_correct и только в этом случае выводить ссылку на следующий (Пример: есть курс с уроками "Урок1, Урок2, Урок3". на html странице на навиг. панели отображется только ссылка на "Урок1", после просмотра видеоролика пользователь прикрепляет в форму д/з и преподаватель из админки в случае правильности д/з ставит галочку в поле "is_correct" и только в этом случае пользователю отобразится ссылка на "Урок 2" в навигационной панели
Прикрепляю сам код
views.py
def lessons_detail(request, pk):
lesson_item = get_object_or_404(Lessons, pk=pk)
lessons_nav = Lessons.objects.all()
prev_lesson = Lessons.objects.filter(pk__lt=pk).order_by('-pk').first()
lesson_previous = Answers.objects.filter(
Q(user_answer=request.user) & Q(from_lesson=prev_lesson)
).first()
if request.method == 'POST':
images = request.FILES.getlist('photos')
answer = Answers.objects.create(user_answer=request.user, from_lesson=lesson_item,
is_correct=False)
for image in images:
Photos.objects.create(
image=image,
answer=answer
)
return render(request, 'brows/lesson_detail.html', {'lessons': lesson_item,
'lessons_nav': lessons_nav,
'lesson_previous': lesson_previous
})
lessons_detail.html
<aside class="panel">
<a href="{% url 'logout' %}" class="btn btn-danger">Выйти</a>
<a href="#"><p>LOGO</p></a>
{% for i in lessons_nav %}
{% if i.get_pre %}
<div class="lesson_link">
<a href="{{ i.get_absolute_url }}" class="btn btn-primary">{{ i.lesson }}</a>
</div>
{% elif i == first %}
<div class="lesson_link">
<a href="{{ i.get_absolute_url }}" class="btn btn-primary">{{ i.lesson }}</a>
<p>{{ lesson_previous.is_correct }}</p>
</div>
{% endif %}
{% endfor %}
</aside>
models.py
class Lessons(models.Model):
lesson = models.CharField(max_length=250, verbose_name='Урок')
Video = models.CharField(max_length=250, verbose_name='Видео')
abstract = models.TextField(verbose_name='Конспект')
home_work = models.TextField(verbose_name='Домашнее задание')
def __str__(self):
return f'{self.lesson}'
class Meta:
verbose_name = 'Урок'
verbose_name_plural = 'Уроки'
ordering = ['pk']
def get_absolute_url(self):
return reverse('lessons_detail', kwargs={'pk': self.pk})
class Answers(models.Model):
user_answer = models.ForeignKey(User, on_delete=models.CASCADE, default=1, verbose_name='Пользователь')
from_lesson = models.ForeignKey(Lessons, on_delete=models.CASCADE, verbose_name='Урок')
comments = models.TextField(verbose_name='Комментарий преподавателя', blank=True)
is_correct = models.BooleanField(default=0, verbose_name='Допуск к следующему уроку')
next = models.ForeignKey('self', on_delete=models.CASCADE, related_name='prev')
def __str__(self):
return f'{self.user_answer}'
def get_absolute_url(self, from_lesson):
return reverse('lessons_detail', kwargs={'pk': from_lesson.pk})
def lesson_prev(self, lesson_next):
prev_lesson = Lessons.objects.filter(pk__lt=lesson_next).order_by('-pk').first()
lesson_previous = Answers.objects.filter(
Q(user_answer=self.user_answer) & Q(from_lesson=prev_lesson)).first()
return lesson_previous.is_correct
class Meta:
verbose_name = 'Ответ'
verbose_name_plural = 'Ответы'
ordering = ['pk']
class Photos(models.Model):
image = models.ImageField(upload_to='photos/%Y/%m/%d', verbose_name='Ответ')
answer = models.ForeignKey(Answers, related_name='photos', on_delete=models.CASCADE)
def __str__(self):
return f'{self.answer}'
def get_absolute_url(self):
return reverse('lessons_detail', kwargs={'pk': self.pk})
class Meta:
verbose_name = 'Фото'
verbose_name_plural = 'Фото'
ordering = ['pk']
Ответы (1 шт):
Я бы посоветовал не искать по pk__lt, так как Вы не можете 100% гарантировать, что следущий урок будет с бОльшим id.
Например, если нужно будет вставить урок между двумя другими.
Так же проще добавить поле next = models.ForeignKey('self', on_delete=..., related_name='prev'), что позволит Вам обращаться к следущему и прошлому уроку по obj.next и obj.prev. Даже наверное лучше подойдет OneToOne связь.
Что касается "следущий урок в навигационной панели", можете сделать выборку выполненных и/или не выполнных уроков (их id) и при выводе смотреть, является ли он выполненным
# .py
lessons = Lessons.objects.all()
show_link = lessons.filter(is_correct=True).values_list('id')
# Для моего случая
show_link = lessons.objects.filter(Q(prev__isnull=True) | Q(prev__is_correct=True))
# .html
{% for obj in lessons %}
{% if obj.in in show_link %)
{# выполнен #}
{% else %}
{# не выполнен #}
{% endif %}
{% endfor %}