根据来自 URL 的父 ID 显示子记录
Displaying child records based on parent id from URL
我有一个模型 Dataset
和另一个模型 DatasetReview
,其中 DatasetReview
有一个到 Dataset
的外键连接。我想在单独的页面中显示与特定 Dataset
关联的所有 DatasetReview
模型。
我目前可以像这样查看每个 Dataset
:http://127.0.0.1:8000/dataset/3/
并且想像这样查看 Dataset
3 的所有 DatasetReview
模型: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 来说非常新。
想通了。
密钥在 views.py
中的 class DatasetReviewsView(DetailView)
内。我首先需要将此继承更改为 ListView
以启用我正在寻找的内容。
接下来,我只需要为我想在 html 页面中显示的内容提供上下文。这可以通过覆盖 get_context_data
函数轻松完成,该函数为显示此基于 class 的视图的模板提供上下文数据。
这使得利用 python 提供我想要的信息变得非常容易。我可以使用 id = self.kwargs['pk']
查询我正在查看的数据集的 ID(它必须包含在 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
我有一个模型 Dataset
和另一个模型 DatasetReview
,其中 DatasetReview
有一个到 Dataset
的外键连接。我想在单独的页面中显示与特定 Dataset
关联的所有 DatasetReview
模型。
我目前可以像这样查看每个 Dataset
:http://127.0.0.1:8000/dataset/3/
并且想像这样查看 Dataset
3 的所有 DatasetReview
模型: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 来说非常新。
想通了。
密钥在 views.py
中的 class DatasetReviewsView(DetailView)
内。我首先需要将此继承更改为 ListView
以启用我正在寻找的内容。
接下来,我只需要为我想在 html 页面中显示的内容提供上下文。这可以通过覆盖 get_context_data
函数轻松完成,该函数为显示此基于 class 的视图的模板提供上下文数据。
这使得利用 python 提供我想要的信息变得非常容易。我可以使用 id = self.kwargs['pk']
查询我正在查看的数据集的 ID(它必须包含在 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