Отображение дочерних записей на основе родительского идентификатора из URL

У меня есть одна модель Dataset и другая, называемая DatasetReview, где DatasetReview имеет соединение с Dataset по внешнему ключу. Я хотел бы отобразить все модели DatasetReview, привязанные к конкретному Dataset, на отдельной странице.

В настоящее время я могу просматривать каждую Dataset вот так: http://127.0.0.1:8000/dataset/3/ и хотел бы видеть все DatasetReview модели для Dataset 3 вот так: http://127.0.0.1:8000/dataset/3/reviews Но я не знаю, как это настроить.

Я не уверен, как правильно сформулировать этот вопрос, поэтому мне было трудно найти другие сообщения, в которых обсуждалось, как сделать что-то подобное. Вот мой код:

urls.py:

from django.urls import path
from .views import (
    DatasetListView, 
    DatasetDetailView, 
    DatasetCreateView,
    DatasetUpdateView,
    DatasetDeleteView,
    DatasetReviewsView
    )
from . import views

urlpatterns = [
    path('', DatasetListView.as_view(), name='argo-home'),
    path('dataset/<int:pk>/', DatasetDetailView.as_view(), name='dataset-detail'),
    path('dataset/new/', DatasetCreateView.as_view(), name='dataset-create'),
    path('dataset/<int:pk>/update', DatasetUpdateView.as_view(), name='dataset-update'),
    path('dataset/<int:pk>/delete', DatasetDeleteView.as_view(), name='dataset-delete'),
    path('dataset/<int:pk>/reviews', DatasetReviewsView.as_view(), name='dataset-review'),
    path('about/', views.about, name='argo-about'),
]

views.py:

from django.shortcuts import render
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic import (
    ListView, 
    DetailView, 
    CreateView,
    UpdateView,
    DeleteView
)
from .models import Dataset, DatasetReview

def home(request):
    context = {
        'datasets' : Dataset.objects.all(),
    }
    return render(request, 'argo/home.html', context)

class DatasetListView(ListView):
    model = Dataset
    template_name = 'argo/home.html' # <app>/<model>_<viewtype>.html
    context_object_name = 'datasets'
    ordering = ['-date_posted']

class DatasetDetailView(DetailView):
    model = Dataset

class DatasetCreateView(LoginRequiredMixin, CreateView):
    model = Dataset
    fields = ['title', 'description', 'access']

    def form_valid(self, form):
        form.instance.author = self.request.user
        form.instance.affiliation = self.request.user.affiliation
        return super().form_valid(form)

class DatasetUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
    model = Dataset
    fields = ['title', 'description']

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)

    def test_func(self):
        Dataset = self.get_object()
        if self.request.user == Dataset.author:
            return True
        return False

class DatasetDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = Dataset
    success_url = '/'
    
    def test_func(self):
        dataset = self.get_object()
        if self.request.user == dataset.author:
            return True
        return False
    
class DatasetReviewsView(DetailView):
    model = DatasetReview
    success_url = '/'
    
    def test_func(self):
        datasetReview = self.get_object()
        if self.request.user == datasetReview.author:
            return True
        return False

def about(request):
    return render(request, 'argo/about.html', {'title': 'About'})

models.py:

from django.db import models
from django.utils import timezone
from django.core.validators import MaxValueValidator, MinValueValidator
from django.urls import reverse
from users.models import User, Affiliation

# from django.contrib.auth.models import User

class Dataset(models.Model):
    title = models.CharField(max_length=100)
    description = models.TextField()
    date_posted = models.DateTimeField(default=timezone.now)
    affiliation = models.ForeignKey(Affiliation, on_delete=models.CASCADE, related_name='posted_datasets')
    access = models.ManyToManyField(Affiliation, related_name='available_datasets')
    author = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.title
    
    def get_absolute_url(self):
        return reverse('dataset-detail', kwargs = {'pk' : self.pk})

class DatasetReview(models.Model):
    dataset = models.ForeignKey(Dataset, on_delete=models.CASCADE, related_name='reviews_obj')
    reviewer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='reviews')
    comments = models.TextField()
    rating = models.FloatField(
        default=3.0,
        validators=[MaxValueValidator(5.0), MinValueValidator(1.0)]
     )

    def __str__(self):
        return self.dataset.title + ' review by ' + self.reviewer.username

    def get_absolute_url(self):
        return reverse('dataset-review', kwargs = {'rpk' : self.pk})

admin.py:

from django.contrib import admin
from .models import Dataset, DatasetReview

admin.site.register(Dataset)
admin.site.register(DatasetReview)

Любые советы были бы очень полезными, очень новыми для django.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
32
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Разобрался с этим.

Ключ находится внутри class DatasetReviewsView(DetailView) в views.py. Сначала мне нужно было изменить это наследование на ListView, чтобы включить то, что я искал.

Затем мне просто нужно было предоставить контекст для того, что я хотел показать на своей html-странице. Это легко сделать, переопределив функцию get_context_data, которая предоставляет данные контекста для шаблонов, отображающих это представление на основе класса.

Это позволяет очень легко использовать python для предоставления нужной мне информации. Я мог бы запросить идентификатор набора данных, который я просматривал, с помощью id = self.kwargs['pk'] (который должен быть включен в параметры функции для get_context_data), а затем я мог бы просто отфильтровать все отзывы только для тех, набор данных которых соответствует этому идентификатору. Затем в html я мог перебрать переменную num_reviews.

Есть еще один код, который усредняет все рейтинги, чтобы получить общий рейтинг.

class DatasetReviewsView(ListView):
    model = DatasetReview
    context_object_name = 'reviews'
    success_url = '/'

    def get_context_data(self, **kwargs):
        id = self.kwargs['pk']
        context = super(DatasetReviewsView, self).get_context_data(**kwargs)
        context['id'] = id
        context['name'] = Dataset.objects.get(pk=id).title
        context['num_reviews'] = len(DatasetReview.objects.filter(dataset=id))
        tot = 0
        for review in DatasetReview.objects.filter(dataset=id):
            tot += review.rating
        context['avg_rating'] = tot / context['num_reviews']
        return context

Другие вопросы по теме