bookmark.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. from django.contrib.contenttypes.models import ContentType
  2. from django.urls.base import reverse
  3. from django.db import transaction
  4. from django.db.models import Q
  5. from django.forms import ModelChoiceField
  6. from django.http import QueryDict
  7. from django.template import loader
  8. from django.utils.decorators import method_decorator
  9. from django.utils.encoding import smart_text
  10. from django.utils.translation import ugettext_lazy as _
  11. from django.views.decorators.csrf import csrf_protect
  12. from xadmin.filters import FILTER_PREFIX, SEARCH_VAR
  13. from xadmin.plugins.relate import RELATE_PREFIX
  14. from xadmin.plugins.utils import get_context_dict
  15. from xadmin.sites import site
  16. from xadmin.views import ModelAdminView, BaseAdminPlugin, ListAdminView
  17. from xadmin.views.list import COL_LIST_VAR, ORDER_VAR
  18. from xadmin.views.dashboard import widget_manager, BaseWidget, PartialBaseWidget
  19. from xadmin.models import Bookmark
  20. csrf_protect_m = method_decorator(csrf_protect)
  21. class BookmarkPlugin(BaseAdminPlugin):
  22. # [{'title': "Female", 'query': {'gender': True}, 'order': ('-age'), 'cols': ('first_name', 'age', 'phones'), 'search': 'Tom'}]
  23. list_bookmarks = []
  24. show_bookmarks = True
  25. def has_change_permission(self, obj=None):
  26. if not obj or self.user.is_superuser:
  27. return True
  28. else:
  29. return obj.user == self.user
  30. def get_context(self, context):
  31. if not self.show_bookmarks:
  32. return context
  33. bookmarks = []
  34. current_qs = '&'.join([
  35. '%s=%s' % (k, v)
  36. for k, v in sorted(filter(
  37. lambda i: bool(i[1] and (
  38. i[0] in (COL_LIST_VAR, ORDER_VAR, SEARCH_VAR)
  39. or i[0].startswith(FILTER_PREFIX)
  40. or i[0].startswith(RELATE_PREFIX)
  41. )),
  42. self.request.GET.items()
  43. ))
  44. ])
  45. model_info = (self.opts.app_label, self.opts.model_name)
  46. has_selected = False
  47. menu_title = _(u"Bookmark")
  48. list_base_url = reverse('xadmin:%s_%s_changelist' %
  49. model_info, current_app=self.admin_site.name)
  50. # local bookmarks
  51. for bk in self.list_bookmarks:
  52. title = bk['title']
  53. params = dict([
  54. (FILTER_PREFIX + k, v)
  55. for (k, v) in bk['query'].items()
  56. ])
  57. if 'order' in bk:
  58. params[ORDER_VAR] = '.'.join(bk['order'])
  59. if 'cols' in bk:
  60. params[COL_LIST_VAR] = '.'.join(bk['cols'])
  61. if 'search' in bk:
  62. params[SEARCH_VAR] = bk['search']
  63. def check_item(i):
  64. return bool(i[1]) or i[1] == False
  65. bk_qs = '&'.join([
  66. '%s=%s' % (k, v)
  67. for k, v in sorted(filter(check_item, params.items()))
  68. ])
  69. url = list_base_url + '?' + bk_qs
  70. selected = (current_qs == bk_qs)
  71. bookmarks.append(
  72. {'title': title, 'selected': selected, 'url': url})
  73. if selected:
  74. menu_title = title
  75. has_selected = True
  76. content_type = ContentType.objects.get_for_model(self.model)
  77. bk_model_info = (Bookmark._meta.app_label, Bookmark._meta.model_name)
  78. bookmarks_queryset = Bookmark.objects.filter(
  79. content_type=content_type,
  80. url_name='xadmin:%s_%s_changelist' % model_info
  81. ).filter(Q(user=self.user) | Q(is_share=True))
  82. for bk in bookmarks_queryset:
  83. selected = (current_qs == bk.query)
  84. if self.has_change_permission(bk):
  85. change_or_detail = 'change'
  86. else:
  87. change_or_detail = 'detail'
  88. bookmarks.append({'title': bk.title, 'selected': selected, 'url': bk.url, 'edit_url':
  89. reverse('xadmin:%s_%s_%s' % (bk_model_info[0], bk_model_info[1], change_or_detail),
  90. args=(bk.id,))})
  91. if selected:
  92. menu_title = bk.title
  93. has_selected = True
  94. post_url = reverse('xadmin:%s_%s_bookmark' % model_info,
  95. current_app=self.admin_site.name)
  96. new_context = {
  97. 'bk_menu_title': menu_title,
  98. 'bk_bookmarks': bookmarks,
  99. 'bk_current_qs': current_qs,
  100. 'bk_has_selected': has_selected,
  101. 'bk_list_base_url': list_base_url,
  102. 'bk_post_url': post_url,
  103. 'has_add_permission_bookmark': self.admin_view.request.user.has_perm('xadmin.add_bookmark'),
  104. 'has_change_permission_bookmark': self.admin_view.request.user.has_perm('xadmin.change_bookmark')
  105. }
  106. context.update(new_context)
  107. return context
  108. # Media
  109. def get_media(self, media):
  110. return media + self.vendor('xadmin.plugin.bookmark.js')
  111. # Block Views
  112. def block_nav_menu(self, context, nodes):
  113. if self.show_bookmarks:
  114. nodes.insert(0, loader.render_to_string('xadmin/blocks/model_list.nav_menu.bookmarks.html',
  115. context=get_context_dict(context)))
  116. class BookmarkView(ModelAdminView):
  117. @csrf_protect_m
  118. @transaction.atomic
  119. def post(self, request):
  120. model_info = (self.opts.app_label, self.opts.model_name)
  121. url_name = 'xadmin:%s_%s_changelist' % model_info
  122. bookmark = Bookmark(
  123. content_type=ContentType.objects.get_for_model(self.model),
  124. title=request.POST[
  125. 'title'], user=self.user, query=request.POST.get('query', ''),
  126. is_share=request.POST.get('is_share', 0), url_name=url_name)
  127. bookmark.save()
  128. content = {'title': bookmark.title, 'url': bookmark.url}
  129. return self.render_response(content)
  130. class BookmarkAdmin(object):
  131. model_icon = 'fa fa-book'
  132. list_display = ('title', 'user', 'url_name', 'query')
  133. list_display_links = ('title',)
  134. user_fields = ['user']
  135. hidden_menu = True
  136. def queryset(self):
  137. if self.user.is_superuser:
  138. return Bookmark.objects.all()
  139. return Bookmark.objects.filter(Q(user=self.user) | Q(is_share=True))
  140. def get_list_display(self):
  141. list_display = super(BookmarkAdmin, self).get_list_display()
  142. if not self.user.is_superuser:
  143. list_display.remove('user')
  144. return list_display
  145. def has_change_permission(self, obj=None):
  146. if not obj or self.user.is_superuser:
  147. return True
  148. else:
  149. return obj.user == self.user
  150. @widget_manager.register
  151. class BookmarkWidget(PartialBaseWidget):
  152. widget_type = _('bookmark')
  153. widget_icon = 'fa fa-bookmark'
  154. description = _(
  155. 'Bookmark Widget, can show user\'s bookmark list data in widget.')
  156. template = "xadmin/widgets/list.html"
  157. bookmark = ModelChoiceField(
  158. label=_('Bookmark'), queryset=Bookmark.objects.all(), required=False)
  159. def setup(self):
  160. BaseWidget.setup(self)
  161. bookmark = self.cleaned_data['bookmark']
  162. model = bookmark.content_type.model_class()
  163. data = QueryDict(bookmark.query)
  164. self.bookmark = bookmark
  165. if not self.title:
  166. self.title = smart_text(bookmark)
  167. req = self.make_get_request("", data.items())
  168. self.list_view = self.get_view_class(
  169. ListAdminView, model, list_per_page=10, list_editable=[])(req)
  170. def has_perm(self):
  171. return True
  172. def context(self, context):
  173. list_view = self.list_view
  174. list_view.make_result_list()
  175. base_fields = list_view.base_list_display
  176. if len(base_fields) > 5:
  177. base_fields = base_fields[0:5]
  178. context['result_headers'] = [c for c in list_view.result_headers(
  179. ).cells if c.field_name in base_fields]
  180. context['results'] = [
  181. [o for i, o in enumerate(filter(
  182. lambda c: c.field_name in base_fields,
  183. r.cells
  184. ))]
  185. for r in list_view.results()
  186. ]
  187. context['result_count'] = list_view.result_count
  188. context['page_url'] = self.bookmark.url
  189. site.register(Bookmark, BookmarkAdmin)
  190. site.register_plugin(BookmarkPlugin, ListAdminView)
  191. site.register_modelview(r'^bookmark/$', BookmarkView, name='%s_%s_bookmark')