Django ListView:根据所选用户过滤历史记录
Django ListView: filter history based on chosen user
我有一个 History ListView,我想让我的用户根据他们在我提供的 ModelChoiceFields 中选择的用户来过滤 Historyitems
我的历史视图如下所示:
class HistoryItems(ListView):
model = HistoryItem
template_name = 'history/history_table.html'
context_object_name = 'history_items'
def get_context_data(self, **kwargs):
user_id = kwargs.get('user_id')
query = {}
if user_id:
user = get_object_or_404(User, pk=user_id)
query['changed_by'] = user
else:
user = None
history_items = HistoryItem.objects.filter(**query).select_related('changed_by',
'content_type')
return {
'filter_history_form': HistoryFilterForm(user_id=user_id),
'history_items': history_items,
}
它 returns 我在大 table 中找到了正确的历史记录(请参阅下面的 html)。然后我得到了这个表格:
class HistoryFilterForm(forms.Form):
normal_user = forms.ModelChoiceField(User.objects.filter(special=None), label="Normal Users", empty_label="All normal users")
special_user = forms.ModelChoiceField(User.objects.exclude(special=None), label="Special User", empty_label="All special users")
def __init__(self, *args, **kwargs):
user_id = kwargs.pop('user_id')
super(HistoryFilterForm, self).__init__(*args, **kwargs)
self.fields['normal_user'].initial = user_id
self.fields['special_user'].initial = user_id
self.helper = FormHelper()
self.helper.label_class = 'sr-only'
self.helper.add_layout(Layout(
Row(
Div('normal_user', css_class='col-sm-3'),
Div('special_user', css_class='col-sm-3'),
)
))
此表单简单地创建了同一用户对象的两个 ModelChoiceField,一个字段显示所有 "normal" 用户,另一个显示所有 "special users"
我的网址看起来很漂亮:
urls = [
path('', views.HistoryItems.as_view(), name='history_index'),
path('u=<int:pk>', views.HistoryItems.as_view(), name='history_index'),
]
我想当我搜索另一个用户的历史项目时,我需要一直刷新我的页面,我正在用 JavaScript 做这件事(见下面的 HTML ).我还将 url 中的用户 ID 设置为额外参数。
最后是我的 HTML:
{% block extra_js %}
{{ block.super }}
<script type="application/javascript">
$(function(){
var historyUrlBase = '/history/';
var getParams = function(){
return {
'normalUserId': $('#id_normal_user').val(),
'specialUserId': $('#id_special_user').val()
}
};
var getNormalUrl = function(){
var params = getParams();
return historyUrlBase + 'u=' + params.normalUserId;
};
$('#id_normal_user').change(function(){
window.location.href = getNormalUrl();
});
var getSpecialUrl = function(){
var params = getParams();
return historyUrlBase + 'u=' + params.specialUserId;
};
$('#id_special_user').change(function(){
window.location.href = getSpecialUrl();
});
});
</script>
{% endblock %}
{% block main %}
{% crispy filter_history_form %}
<table class="table table-bordered table-responsive-sm">
<thead class="thead-light">
<tr>
<th>Changed at</th>
<th>Object</th>
<th>Action</th>
<th>Changed by</th>
<th>Difference</th>
</tr>
</thead>
<tbody>
{% for history_item in history_items %}
<tr>
<td>
{{ history_item.changed_at|date:"d.m.Y h:i:s" }}
</td>
<td>
{{ history_item.object }}
</td>
<td>
{% if history_item.action == 'custom' %}
{{ history_item.description }}
{% else %}
{{ history_item.get_action_display }}
{% endif %}
</td>
<td>
{{ history_item.changed_by }}
</td>
<td>
{{ history_item.difference|default:'' }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
我现在的主要问题是,在我的 View 中,我收到的 kwargs 始终是一个空的 dict,ofc 没有任何作用。
但我不知道如何从我选择的用户那里接收 ID,我的表单总是在两个 ModelChoiceFields 中显示正确的用户,但我如何从这些用户那里获取 ID 以使用它们在我看来?
用户本身只是通过他们拥有的special
字段来区分,但他们共享相同的模型。
我正在使用 Django 2.2 和 Python 3.7 顺便说一句,所以也许如果有人知道更简单的方法,那也很受欢迎!
我希望有人知道一个好的解决方案或者可以告诉我我做错了什么。谢谢! :)
简答
get_context_data 中的 kwargs 字典包含在您的 url 中定义的任何关键字参数。
urls = [
path('', views.HistoryItems.as_view(), name='history_index'),
path('u=<int:pk>', views.HistoryItems.as_view(), name='history_index'),
]
您的第一个 url 没有定义关键字参数。您的第二个 url 有一个关键字参数 pk(即不是 user_id)。所以你的代码实际上应该是
user_id = kwargs.get('pk')
长答案
您设置表单的方式通常不是您处理数据过滤的方式。您要做的是使用 GET 请求提交表单。
https://docs.djangoproject.com/en/dev/topics/forms/#get-and-post
这将生成一个 url 查询字符串参数,类似于
/history/?normal_user=1&special_user=1
然后您可以通过请求对象中的 GET 字典在您的视图中访问这些查询字符串参数。
def get_context_data(self, **kwargs):
normal_user = self.request.GET.get('normal_user')
special_user = self.request.GET.get('special_user')
# filter your history with normal_user/special_user
最后,删除您的第二个 url,因为这不再是必需的。
我有一个 History ListView,我想让我的用户根据他们在我提供的 ModelChoiceFields 中选择的用户来过滤 Historyitems
我的历史视图如下所示:
class HistoryItems(ListView):
model = HistoryItem
template_name = 'history/history_table.html'
context_object_name = 'history_items'
def get_context_data(self, **kwargs):
user_id = kwargs.get('user_id')
query = {}
if user_id:
user = get_object_or_404(User, pk=user_id)
query['changed_by'] = user
else:
user = None
history_items = HistoryItem.objects.filter(**query).select_related('changed_by',
'content_type')
return {
'filter_history_form': HistoryFilterForm(user_id=user_id),
'history_items': history_items,
}
它 returns 我在大 table 中找到了正确的历史记录(请参阅下面的 html)。然后我得到了这个表格:
class HistoryFilterForm(forms.Form):
normal_user = forms.ModelChoiceField(User.objects.filter(special=None), label="Normal Users", empty_label="All normal users")
special_user = forms.ModelChoiceField(User.objects.exclude(special=None), label="Special User", empty_label="All special users")
def __init__(self, *args, **kwargs):
user_id = kwargs.pop('user_id')
super(HistoryFilterForm, self).__init__(*args, **kwargs)
self.fields['normal_user'].initial = user_id
self.fields['special_user'].initial = user_id
self.helper = FormHelper()
self.helper.label_class = 'sr-only'
self.helper.add_layout(Layout(
Row(
Div('normal_user', css_class='col-sm-3'),
Div('special_user', css_class='col-sm-3'),
)
))
此表单简单地创建了同一用户对象的两个 ModelChoiceField,一个字段显示所有 "normal" 用户,另一个显示所有 "special users"
我的网址看起来很漂亮:
urls = [
path('', views.HistoryItems.as_view(), name='history_index'),
path('u=<int:pk>', views.HistoryItems.as_view(), name='history_index'),
]
我想当我搜索另一个用户的历史项目时,我需要一直刷新我的页面,我正在用 JavaScript 做这件事(见下面的 HTML ).我还将 url 中的用户 ID 设置为额外参数。
最后是我的 HTML:
{% block extra_js %}
{{ block.super }}
<script type="application/javascript">
$(function(){
var historyUrlBase = '/history/';
var getParams = function(){
return {
'normalUserId': $('#id_normal_user').val(),
'specialUserId': $('#id_special_user').val()
}
};
var getNormalUrl = function(){
var params = getParams();
return historyUrlBase + 'u=' + params.normalUserId;
};
$('#id_normal_user').change(function(){
window.location.href = getNormalUrl();
});
var getSpecialUrl = function(){
var params = getParams();
return historyUrlBase + 'u=' + params.specialUserId;
};
$('#id_special_user').change(function(){
window.location.href = getSpecialUrl();
});
});
</script>
{% endblock %}
{% block main %}
{% crispy filter_history_form %}
<table class="table table-bordered table-responsive-sm">
<thead class="thead-light">
<tr>
<th>Changed at</th>
<th>Object</th>
<th>Action</th>
<th>Changed by</th>
<th>Difference</th>
</tr>
</thead>
<tbody>
{% for history_item in history_items %}
<tr>
<td>
{{ history_item.changed_at|date:"d.m.Y h:i:s" }}
</td>
<td>
{{ history_item.object }}
</td>
<td>
{% if history_item.action == 'custom' %}
{{ history_item.description }}
{% else %}
{{ history_item.get_action_display }}
{% endif %}
</td>
<td>
{{ history_item.changed_by }}
</td>
<td>
{{ history_item.difference|default:'' }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
我现在的主要问题是,在我的 View 中,我收到的 kwargs 始终是一个空的 dict,ofc 没有任何作用。
但我不知道如何从我选择的用户那里接收 ID,我的表单总是在两个 ModelChoiceFields 中显示正确的用户,但我如何从这些用户那里获取 ID 以使用它们在我看来?
用户本身只是通过他们拥有的special
字段来区分,但他们共享相同的模型。
我正在使用 Django 2.2 和 Python 3.7 顺便说一句,所以也许如果有人知道更简单的方法,那也很受欢迎!
我希望有人知道一个好的解决方案或者可以告诉我我做错了什么。谢谢! :)
简答
get_context_data 中的 kwargs 字典包含在您的 url 中定义的任何关键字参数。
urls = [
path('', views.HistoryItems.as_view(), name='history_index'),
path('u=<int:pk>', views.HistoryItems.as_view(), name='history_index'),
]
您的第一个 url 没有定义关键字参数。您的第二个 url 有一个关键字参数 pk(即不是 user_id)。所以你的代码实际上应该是
user_id = kwargs.get('pk')
长答案
您设置表单的方式通常不是您处理数据过滤的方式。您要做的是使用 GET 请求提交表单。
https://docs.djangoproject.com/en/dev/topics/forms/#get-and-post
这将生成一个 url 查询字符串参数,类似于
/history/?normal_user=1&special_user=1
然后您可以通过请求对象中的 GET 字典在您的视图中访问这些查询字符串参数。
def get_context_data(self, **kwargs):
normal_user = self.request.GET.get('normal_user')
special_user = self.request.GET.get('special_user')
# filter your history with normal_user/special_user
最后,删除您的第二个 url,因为这不再是必需的。