Как мне связать мою модель с ее внешним ключом и множеством полей в шаблонах в django?

#django #templates #foreign-keys #many-to-many

#django #шаблоны #внешние ключи #многие ко многим

Вопрос:

Я новичок в django, и у меня довольно простой вопрос, однако я не смог найти свой ответ в Интернете, поэтому прошу прощения, если на этот вопрос был дан ответ ранее…

У меня есть 3 модели:

 class Type(models.Model):
    name = models.CharField(max_length=100)

class Exercise(models.Model):
    name = models.CharField(max_length=100)
    type = models.ForeignKey(Type, on_delete=models.CASCADE, default=1)

class Area(models.Model):
    name = models.CharField(max_length=100)
    notes = models.TextField(blank=True, null=True)
    exercise = models.ManyToManyField(Exercise)
  

и 3 представления:

 class AreaView(ListView):
    model = Area
    template_name = 'workouts/areas.html'
    context_object_name = 'areas'

    def get_context_data(self, **kwargs):
        context = super(AreaView, self).get_context_data(**kwargs)
        return context

class ExerciseView(ListView):
    model = Area
    template_name = 'workouts/exercises.html'
    context_object_name = 'exercises'

    def get_context_data(self, **kwargs):
        context = super(ExerciseView, self).get_context_data(**kwargs)
        return context

class TypeView(ListView):
    model = Exercise
    template_name = 'workouts/types.html'
    context_object_name = 'types'

    def get_context_data(self, **kwargs):
        context = super(TypeView, self).get_context_data(**kwargs)
        return context
  

Я зарегистрировал каждое представление на URL, подобный этому:

 urlpatterns = [
    path('', AreaView.as_view(), name='areas'),
    path('exercises/<int:id>', ExerciseView.as_view(), name='exercises'),
    path('types/<int:id>', TypeView.as_view(), name='types'),
]
  

и создал 3 шаблона, areas.html:

 {% for area in areas %}
    <ul>
        <li><a href="{% url 'exercises' id=area.id %}">{{ area.name }}</a></li>
    </ul>
{% endfor %}
  

exercises.html:

 {% for area in areas %}
    <ul>
        <li><a href="{% url 'types' id=exercise.id %}">{% for exercise in area.exercise.all %}{{ exercise }}{% endfor %}</a></li>
    </ul>
{% endfor %}
  

и types.html:

 {% for exercise in exercises %}
    <ul>
        <li>{% for type in exercise.type.all %}{{ type}}{% endfor %}</li>
    </ul>
{% endfor %}
  

Я добавил конкретные упражнения в каждую область в admin, а также конкретные типы для каждого упражнения. То, что я пытаюсь сделать, это отобразить полный список всех областей, в areas.html которых затем ссылаются на список соответствующих им упражнений exercises.html , которые, в свою очередь, затем ссылаются на страницу, на которой показаны соответствующие типы упражнений. Надеюсь, это имеет смысл… Я пробовал играть с различными соглашениями об именовании для контекста, циклов и тому подобного, но пока ничего не получилось так, как я хочу.

Нужно ли мне определять набор запросов в представлениях или есть что-то еще, что я делаю неправильно?

Ответ №1:

Для этого вы можете использовать DetailView.

 class AreaDetailView(DetailView):
    model = Area
    context_object_name = 'area'
    template_name = 'exercises.html'
  

И сопоставьте это подробное представление с URL-адресом следующим образом.

 path('area/<int:pk>/detail/', AreaDetailView.as_view(), name='area_detail'),
  

Теперь вы можете связать этот URL-адрес в своем шаблоне.

 {% for area in areas %}
    <ul>
        <li><a href="{% url 'area_detail' area.pk %}">{{ area.name }}</a></li>
    </ul>
{% endfor %}
  

Теперь в exercise.html вы можете получить соответствующее упражнение в этой области следующим образом.

 {% for exercise in area.exercise_set.all %}
    <ul>
        <li><a href="{% url 'exercise_detail' id=exercise.id %}">{{ exercise.name }}</a></li>
    </ul>
{% endfor %}
  

Аналогичным образом вы можете использовать аналогичный подход с ExerciseDetailView

Комментарии:

1. Большое вам спасибо за вашу помощь. Это почти сработало, мне просто нужно было изменить цикл for на exercises.html {% for exercise in area.exercise.all %} , и это было идеально. Однако, используя ту же технику types.html , т. Е. {% for type in exercise.type.all %} и {{ type.name }} отображает только пустую страницу. Есть идеи, почему это так?

2. это должно быть {{exercise.type}} только и удалить forloop, если вы хотите отобразить тип упражнения.

3. Легенда. Теперь это идеально. Большое вам спасибо!