Filter中添加动态初值
Add a dynamic initial value in Filter
我想为我的 DetailView 添加 django-filter 或 django-autocomplete-light 的动态初始值。我不知道如何最好地使用 django-filter、django-autocomplete-light 或不使用第三方应用程序来构建它。
每个 JournalDetailView 都有一个依赖项下拉列表(在我的例子中,这是期刊 → 期刊年份 → 期刊卷)。依赖下拉列表与 django-autocomplete-light 一起工作,过滤器与 django-filter 一起工作。
我想为期刊传递动态字段,所以我有 ForeignKey 用于期刊年份和期刊卷的依赖下拉列表
例如,在本例中我有三个字段:期刊、期刊年份和期刊卷。我想传递价值取决于日记的 DetailView。例如,对于期刊“Nature”,它将传递字段“Nature”;对于期刊“Ca-A Cancer Journal for Clinicians”,它将通过“Ca-A Cancer Journal for Clinicians”。
我有这个
我想建立这个
models.py
class Journal(models.Model):
slug = models.SlugField(unique=True)
name = models.CharField(max_length=100, blank=True, null=True)
class Article(models.Model, HitCountMixin):
slug = models.SlugField(unique=True)
journal = models.ForeignKey(
"Journal", on_delete=models.SET_NULL, null=True, blank=True
)
journalyear = models.ForeignKey(
"JournalYear", on_delete=models.SET_NULL, null=True, blank=True
)
journalvolume = models.ForeignKey(
"JournalVolume", on_delete=models.SET_NULL, null=True, blank=True
)
def __str__(self):
return self.title
class JournalYear(models.Model):
journal = models.ForeignKey(
"Journal", on_delete=models.SET_NULL, null=True, blank=True
)
name = models.CharField(max_length=10, blank=True, null=True)
def __str__(self):
return self.name
class JournalVolume(models.Model):
journalyear = models.ForeignKey(
"JournalYear", on_delete=models.CASCADE, blank=True, null=True
)
name = models.CharField(max_length=10, blank=True, null=True)
def __str__(self):
return self.name
views.py
class JournalAutocomplete2(autocomplete.Select2QuerySetView):
def get_queryset(self):
# Don't forget to filter out results depending on the visitor !
if not self.request.user.is_authenticated:
return Journal.objects.none()
qs = Journal.objects.all()
if self.q:
qs = qs.filter(name__icontains=self.q)
return qs
class JournalYearAutocomplete2(autocomplete.Select2QuerySetView):
def get_queryset(self):
# Don't forget to filter out results depending on the visitor !
if not self.request.user.is_authenticated:
return JournalYear.objects.none()
journal = self.forwarded.get("journal")
qs = JournalYear.objects.all()
if journal:
qs = qs.filter(journal=journal)
if self.q:
qs = qs.filter(name__icontains=self.q)
return qs
class JournalVolumeAutocomplete2(autocomplete.Select2QuerySetView):
def get_queryset(self):
# Don't forget to filter out results depending on the visitor !
if not self.request.user.is_authenticated:
return JournalVolume.objects.none()
qs = JournalVolume.objects.all()
journalyear = self.forwarded.get("journalyear", None)
if journalyear:
qs = qs.filter(journalyear=journalyear)
if self.q:
qs = qs.filter(name__icontains=self.q)
return qs
class JournalListView(ListView):
model = Journal
template_name = "journals/journals.html"
context_object_name = "journals"
class JournalDetailView(DetailView):
model = Journal
template_name = "journals/journal_detail.html"
context_object_name = "journal"
def get_context_data(self, **kwargs):
context_data = super(JournalDetailView, self).get_context_data()
journal_slug = self.kwargs.get("slug", None)
f = JournalFilter(
self.request.GET,
queryset=Article.objects.filter(
journal__slug__exact=self.kwargs["slug"]),
)
context_data["filter"] = f
return context_data
filters.py
class JournalFilter(django_filters.FilterSet):
journal = django_filters.ModelChoiceFilter(
queryset=Journal.objects.all(),
widget=autocomplete.ModelSelect2(url="journalautocomplete2"),
)
journalyear = django_filters.ModelChoiceFilter(
queryset=JournalYear.objects.all(),
widget=autocomplete.ModelSelect2(
url="journalyearautocomplete2", forward=["journal"]
),
)
journalvolume = django_filters.ModelChoiceFilter(
queryset=JournalVolume.objects.all(),
widget=autocomplete.ModelSelect2(
url="journalvolumeautocomplete2", forward=["journalyear"]
),
)
class Meta:
model = Article
fields = {"journalyear", "journalvolume", "journal"}
urls.py
urlpatterns = [
path("journals/", JournalListView.as_view(), name="journals"),
path("journal/<str:slug>", JournalDetailView.as_view(), name="journal_detail"),
# Django-autocomplete-light
path(
"journalyearautocomplete2/",
JournalYearAutocomplete2.as_view(),
name="journalyearautocomplete2",
),
path(
"journalvolumeautocomplete2/",
JournalVolumeAutocomplete2.as_view(),
name="journalvolumeautocomplete2",
),
path(
"journalautocomplete2/",
JournalAutocomplete2.as_view(),
name="journalautocomplete2",
),
]
编辑:
它对读者有效。
def article_list(request, slug):
journal = get_object_or_404(Journal, slug=slug)
my_filter_defaults = {'journal': journal}
f = JournalFilter(request.GET or my_filter_defaults)
return render(request, 'journals/journaldetail_list.html', {'filter': f, 'journal': journal})
Django-filter 绑定一个字典,通常是 request.GET
来过滤它的查询集。来自文档:
def product_list(request):
f = ProductFilter(request.GET, queryset=Product.objects.all())
return render(request, 'my_app/template.html', {'filter': f})
因此,如果您在未指定过滤的情况下需要默认值,您可以这样做
my_filter_defaults = { ... }
f = ProductFilter(request.GET or my_filter_defaults, queryset=Product.objects.all())
(Pythonic 用法:空字典是错误的,因此使用默认值代替)
您也可以修改 request.GET,但请注意它是 QueryDict 且不可变,因此您必须先复制它
my_dict = request.GET.copy( )
if not my_dict.get( 'foo', None):
my_dict['foo'] = 'my_foo_default'
...
f = ProductFilter(my_dict, queryset=Product.objects.all())
我对 DAL 不熟悉。
我想为我的 DetailView 添加 django-filter 或 django-autocomplete-light 的动态初始值。我不知道如何最好地使用 django-filter、django-autocomplete-light 或不使用第三方应用程序来构建它。
每个 JournalDetailView 都有一个依赖项下拉列表(在我的例子中,这是期刊 → 期刊年份 → 期刊卷)。依赖下拉列表与 django-autocomplete-light 一起工作,过滤器与 django-filter 一起工作。 我想为期刊传递动态字段,所以我有 ForeignKey 用于期刊年份和期刊卷的依赖下拉列表
例如,在本例中我有三个字段:期刊、期刊年份和期刊卷。我想传递价值取决于日记的 DetailView。例如,对于期刊“Nature”,它将传递字段“Nature”;对于期刊“Ca-A Cancer Journal for Clinicians”,它将通过“Ca-A Cancer Journal for Clinicians”。
我有这个
我想建立这个
models.py
class Journal(models.Model):
slug = models.SlugField(unique=True)
name = models.CharField(max_length=100, blank=True, null=True)
class Article(models.Model, HitCountMixin):
slug = models.SlugField(unique=True)
journal = models.ForeignKey(
"Journal", on_delete=models.SET_NULL, null=True, blank=True
)
journalyear = models.ForeignKey(
"JournalYear", on_delete=models.SET_NULL, null=True, blank=True
)
journalvolume = models.ForeignKey(
"JournalVolume", on_delete=models.SET_NULL, null=True, blank=True
)
def __str__(self):
return self.title
class JournalYear(models.Model):
journal = models.ForeignKey(
"Journal", on_delete=models.SET_NULL, null=True, blank=True
)
name = models.CharField(max_length=10, blank=True, null=True)
def __str__(self):
return self.name
class JournalVolume(models.Model):
journalyear = models.ForeignKey(
"JournalYear", on_delete=models.CASCADE, blank=True, null=True
)
name = models.CharField(max_length=10, blank=True, null=True)
def __str__(self):
return self.name
views.py
class JournalAutocomplete2(autocomplete.Select2QuerySetView):
def get_queryset(self):
# Don't forget to filter out results depending on the visitor !
if not self.request.user.is_authenticated:
return Journal.objects.none()
qs = Journal.objects.all()
if self.q:
qs = qs.filter(name__icontains=self.q)
return qs
class JournalYearAutocomplete2(autocomplete.Select2QuerySetView):
def get_queryset(self):
# Don't forget to filter out results depending on the visitor !
if not self.request.user.is_authenticated:
return JournalYear.objects.none()
journal = self.forwarded.get("journal")
qs = JournalYear.objects.all()
if journal:
qs = qs.filter(journal=journal)
if self.q:
qs = qs.filter(name__icontains=self.q)
return qs
class JournalVolumeAutocomplete2(autocomplete.Select2QuerySetView):
def get_queryset(self):
# Don't forget to filter out results depending on the visitor !
if not self.request.user.is_authenticated:
return JournalVolume.objects.none()
qs = JournalVolume.objects.all()
journalyear = self.forwarded.get("journalyear", None)
if journalyear:
qs = qs.filter(journalyear=journalyear)
if self.q:
qs = qs.filter(name__icontains=self.q)
return qs
class JournalListView(ListView):
model = Journal
template_name = "journals/journals.html"
context_object_name = "journals"
class JournalDetailView(DetailView):
model = Journal
template_name = "journals/journal_detail.html"
context_object_name = "journal"
def get_context_data(self, **kwargs):
context_data = super(JournalDetailView, self).get_context_data()
journal_slug = self.kwargs.get("slug", None)
f = JournalFilter(
self.request.GET,
queryset=Article.objects.filter(
journal__slug__exact=self.kwargs["slug"]),
)
context_data["filter"] = f
return context_data
filters.py
class JournalFilter(django_filters.FilterSet):
journal = django_filters.ModelChoiceFilter(
queryset=Journal.objects.all(),
widget=autocomplete.ModelSelect2(url="journalautocomplete2"),
)
journalyear = django_filters.ModelChoiceFilter(
queryset=JournalYear.objects.all(),
widget=autocomplete.ModelSelect2(
url="journalyearautocomplete2", forward=["journal"]
),
)
journalvolume = django_filters.ModelChoiceFilter(
queryset=JournalVolume.objects.all(),
widget=autocomplete.ModelSelect2(
url="journalvolumeautocomplete2", forward=["journalyear"]
),
)
class Meta:
model = Article
fields = {"journalyear", "journalvolume", "journal"}
urls.py
urlpatterns = [
path("journals/", JournalListView.as_view(), name="journals"),
path("journal/<str:slug>", JournalDetailView.as_view(), name="journal_detail"),
# Django-autocomplete-light
path(
"journalyearautocomplete2/",
JournalYearAutocomplete2.as_view(),
name="journalyearautocomplete2",
),
path(
"journalvolumeautocomplete2/",
JournalVolumeAutocomplete2.as_view(),
name="journalvolumeautocomplete2",
),
path(
"journalautocomplete2/",
JournalAutocomplete2.as_view(),
name="journalautocomplete2",
),
]
编辑: 它对读者有效。
def article_list(request, slug):
journal = get_object_or_404(Journal, slug=slug)
my_filter_defaults = {'journal': journal}
f = JournalFilter(request.GET or my_filter_defaults)
return render(request, 'journals/journaldetail_list.html', {'filter': f, 'journal': journal})
Django-filter 绑定一个字典,通常是 request.GET
来过滤它的查询集。来自文档:
def product_list(request):
f = ProductFilter(request.GET, queryset=Product.objects.all())
return render(request, 'my_app/template.html', {'filter': f})
因此,如果您在未指定过滤的情况下需要默认值,您可以这样做
my_filter_defaults = { ... }
f = ProductFilter(request.GET or my_filter_defaults, queryset=Product.objects.all())
(Pythonic 用法:空字典是错误的,因此使用默认值代替)
您也可以修改 request.GET,但请注意它是 QueryDict 且不可变,因此您必须先复制它
my_dict = request.GET.copy( )
if not my_dict.get( 'foo', None):
my_dict['foo'] = 'my_foo_default'
...
f = ProductFilter(my_dict, queryset=Product.objects.all())
我对 DAL 不熟悉。