我正在修改类似于以下内容的Django视图:
class ListBase(DashboardAccessMixin, OrderingMixin, FilterMixin, SearchMixin):
def get(self, request, *args, **kwargs):
if should_delete_filter_cookie(request, path=reverse('dashboard:families')):
request.COOKIES.pop('filters', None)
self.query_dict = query_dict_from_params_or_cookies(request)
return super().get(request, *args, **kwargs)
def render_to_response(self, context, **response_kwargs):
response = super().render_to_response(context, **response_kwargs)
path = reverse('dashboard:families')
if should_delete_filter_cookie(self.request, path=path):
response.delete_cookie('filters', path=path)
elif list(self.request.GET.items()):
response.set_cookie('filters', self.request.GET.urlencode(), path=path)
return response
辅助函数should_delete_filter_cookie
和query_dict_from_params_or_cookies
定义为
def query_dict_from_params_or_cookies(request):
query_dict = request.GET
cookie_filters = request.COOKIES.get('filters')
if cookie_filters and not list(query_dict.items()):
query_dict = QueryDict(cookie_filters)
return query_dict
def should_delete_filter_cookie(request, path):
referer_path = urlparse(request.META.get('HTTP_REFERER')).path
if referer_path and path not in referer_path:
return True
else:
return False
该视图包含filter_form
和search_form
(通过相应的mixins),它们与self.query_dict
绑定。此外,我们遵循命名惯例,即UpdateView
和CreateView
的网址只是ListView
网址的“扩展名”:例如,前者为{{1而后者只是/dashboard/families
(但不是dashboard/families/1
)。
dashboard/family/1
现在是这样的,当您从ListView
返回时,它会通过从Cookie中获取UpdateView
来保留之前应用的过滤器。
我想知道为什么在self.query_dict
方法和should_delete_filter_cookie
方法中调用get()
两次。仅仅这样做一次还不够吗?
另外,render_to_response()
方法中为什么response.set_cookie
使用render_to_response
而不是request.COOKIES['filters'] = request.GET.urlencode()
方法中仅使用get()
?
在更基础的层面上,我很难理解request.COOKIES
和response.cookies
之间的区别。例如,在以下测试用例中,
from django.test import SimpleTestCase, RequestFactory
from django.urls import reverse
from http.cookies import SimpleCookie
class SearchFilterTest(SimpleTestCase):
def setUp(self):
# Use a RequestFactory instead of a Client to obtain Request objects instead of Response objects
self.factory = RequestFactory()
def test_get_with_cookies(self):
self.client.cookies = SimpleCookie({'filters': 'q=Christine'})
response = self.client.get(
reverse('dashboard:families'),
HTTP_REFERER=reverse('dashboard:family', kwargs={'pk': 1, 'tab': 'case-management'}))
import ipdb; ipdb.set_trace()
如果我进入调试器,我看到response.cookies
为空SimpleCookie
,即使已为测试客户端设置了cookie:
ipdb> response.cookies
<SimpleCookie: >
response.cookies
仅代表使用response.set_cookie
设置的Cookie,而不代表原始请求附带的Cookie吗?
此外,使用get()
或render_to_response()
方法在此用例中设置Cookie的最佳方法是什么?