django - 如何将两个查询混合为一个作为下拉元素
问题描述
我需要加入并传递类别和子类别的两个查询作为自动完成 select2 下拉列表的元素,作为我的 django 表单字段,如下所示:
这是我的表格:
class CategoriesAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated:
return Categories.objects.none()
qs = Categories.objects.all()
if self.q:
qs = qs.filter(Q(name__icontains=self.q))
return qs
def get_result_label(self, item):
return format_html( item.name)
class categories_form(forms.ModelForm):
categories = forms.ModelChoiceField(
queryset= Categories.objects.none(),
widget= autocomplete.ModelSelect2(
url='load_categories',
attrs={
'data-placeholder': 'Select a category',
'data-html': True,
'style': 'min-width: 15em !important;',
}
)
)
class Meta:
model = Post
fields = ['categories']
def __init__(self, *args, **kwargs):
super(category_form, self).__init__(*args, **kwargs)
self.fields['categories'].queryset = Categories.objects.all()
在网址中:
path('ajax/categories-autocomplete', CategoriesAutocomplete.as_view(), name='load_categories'),
对于类别模型:
class Categories(models.Model):
name = models.CharField(max_length=100)
brief = models.TextField(null=True)
slug = models.SlugField(max_length=200)
date = models.DateTimeField(default=timezone.now)
class Meta:
db_table = "categories"
对于子类别模型:
class Sub_Categories(models.Model):
name = models.CharField(max_length=100)
brief = models.TextField(null=True)
slug = models.SlugField(max_length=200)
date = models.DateTimeField(default=timezone.now)
class Meta:
db_table = "sub_categories"
将类别与子类别联系起来的模型:
class Categories_Sub_Categories(models.Model):
category = models.OneToOneField(Categories, primary_key=True, on_delete=models.CASCADE)
sub_cat = models.OneToOneField(Sub_Categories, on_delete=models.CASCADE)
class Meta:
db_table = "categories_sub-categories"
在 Post 模型中:
class Post(models.Model):
title = models.CharField(max_length=50)
descript = HTMLField(blank=True, null=True)
categories = models.ForeignKey(Categories, blank=True, null=True, on_delete=models.CASCADE)
subcategories = models.ForeignKey(Sub_Categories, blank=True, null=True, on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.CASCADE)
date = models.DateTimeField(default=timezone.now)
更新:
@ha-neul 提供的答案只是有一个错误。我用一个例子来展示它:
这是下拉列表中的预期:
**Asia**
China
Malaysia
India
Tajikistan
Iran
Qatar
**Europe**
Germany
Italy
Spain
Netherlands
France
**Africa**
Gana
...
但这就是我所看到的:
**Asia**
China
Malaysia
**Europe**
Netherlands
France
Sweden
Norway
**Asia**
India
Tajikistan
Iran
**Europe**
Germany
Italy
**Asia**
Qatar
**Africa**
Gana
...
**America**
....
**Europe**
Spain
在 SubCategory 表中,我有类似的内容:
id ........... category_id
1 1
2 1
3 1
4 1
5 3
6 1
7 2
我正在关注这个包。任何让我更接近解决方案的想法将不胜感激!
解决方案
如果这是您想要实现的目标,那么:
简短的回答是你应该
- 让您的子类别
ForeignKeyField
参考类别模型。 - 使用
Select2GroupQuerySetView
而不是Select2QuerySetView
.
但是实现起来有点复杂。
首先,虽然django- autocomplete -light 的源代码有. 因此,您必须在自己的. 另外,源码有错别字,需要修正。Select2GroupQuerySetView
autocomplete.Select2GroupQuerySetView
views.py
步骤 1. 在 models.py 中:
class Category(models.Model):
name = models.CharField(max_length=100)
brief = models.TextField(null=True)
slug = models.SlugField(max_length=200)
date = models.DateTimeField(default=timezone.now)
class SubCategory(models.Model):
##################
#You need add this line, so there is a one-to-many relationship
category = models.ForeignKey(Category, on_delete=models.CASCADE,
related_name='subcategories')
###############
name = models.CharField(max_length=100)
brief = models.TextField(null=True)
slug = models.SlugField(max_length=200)
date = models.DateTimeField(default=timezone.now)
Step2.in views.py 复制粘贴 Select2GroupQuerySetView 代码并修正错字
# import collections, so Select2GroupQuerySetView can work
import collections
class Select2GroupQuerySetView(autocomplete.Select2QuerySetView):
group_by_related = None
related_field_name = 'name'
def get_results(self, context):
if not self.group_by_related:
raise ImproperlyConfigured("Missing group_by_related.")
groups = collections.OrderedDict()
object_list = context['object_list']
print(object_list)
object_list = object_list.annotate(
group_name=F(f'{self.group_by_related}__{self.related_field_name}'))
for result in object_list:
group_name = getattr(result, 'group_name')
groups.setdefault(group_name, [])
groups[group_name].append(result)
return [{
'id': None,
'text': group,
'children': [{
'id': result.id,
'text': getattr(result, self.related_field_name),
# this is the line I had to comment out
#'title': result.descricao
} for result in results]
} for group, results in groups.items()]
3. 使用 Select2GroupQuerySetView 编写自己的视图
class SubCategoryAutocomplete(Select2GroupQuerySetView):
print('under subcategory autocomplete')
group_by_related = 'category' # this is the fieldname of ForeignKey
related_field_name = 'name' # this is the fieldname that you want to show.
def get_queryset(self):
##### Here is what you normally put... I am showing the minimum code.
qs = SubCategory.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
如何在您的项目中使用此视图?
1.假设您有一个Post
模型如下,子类别为 ForeignKey。
class Post(models.Model):
title = models.CharField(max_length=100)
subcategory = models.ForeignKey(SubCategory,on_delete=models.CASCADE)
def __str__(self):
return self.title
2.您将生成一个包含子类别自动完成字段的 PostForm。
在forms.py中
from django.conf.urls import url
class PostForm(forms.ModelForm):
subcategory = forms.ModelChoiceField(
queryset=Subcategory.objects.all(),
widget=autocomplete.ModelSelect2(url='subcategory-autocomplete')
)
class Meta:
model= Post
fields = ('title','subcategory')
- 您将生成一个
CreatePostView
使用泛型CreateView
from django.views.generic.edit import CreateView
class CreatePostView(CreateView):
model=Post
template_name='yourapp/yourtemplate.html'# need to change
form_class=PostForm
success_url = '/'
- 现在,在您的 urls.py 中,一个
CreatePostView
用于自动完成视图的另一个 url。
urlpatterns = [
url(
r'^subcategory-autocomplete/$',
SubCategoryAutocomplete.as_view(),
name='subcategory-autocomplete',
),
path('post/create',CreatePostView.as_view(), name='create_post'),
一切就绪,您将
post/create
看到一个带有子类别自动完成字段的 PostForm。OP 在使用上面的代码后有一个奇怪的分组行为。他在评论中提到:
在 qs 中添加了 .order_by(category_id')` 并修复了它。
推荐阅读
- terraform - 在资源创建中使用地图列表的地图
- vba - 由于格式错误,VBA 运行时错误 13
- php - 尽管进行了数小时的故障排除并且它是一个相对简单的程序,但我似乎无法让我的帖子表单在 PHP 中正常工作
- java - 用于openge连接问题的插件sonarqube
- php - PHP将带有空格的字符串数字转换为浮点数
- php - PHPMailer 在浏览器中工作,但不能作为 cron 工作
- javascript - 为什么“事件”在不将其作为参数传递的情况下起作用?
- prolog - 将字符列表转换为字符串列表,每个字符串在 Prolog 中包含 3 个字符
- scala - 为什么函数参数名称中不允许使用尾随下划线?
- r - 在 r 中选择 ARIMA 模型