Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. import itertools
  2. from django.views import generic
  3. from django.contrib.contenttypes.models import ContentType
  4. from django.utils.translation import ugettext_lazy as _
  5. from django.core.urlresolvers import reverse
  6. from django.conf import settings
  7. from django.contrib import messages
  8. from django.http import HttpResponseRedirect
  9. from django.db.models import Count
  10. from django.shortcuts import HttpResponse
  11. from oscar.core.loading import get_classes
  12. from oscar.apps.promotions.conf import PROMOTION_CLASSES
  13. SingleProduct, RawHTML, Image, MultiImage, \
  14. AutomaticProductList, PagePromotion, \
  15. HandPickedProductList = get_classes('promotions.models',
  16. ['SingleProduct', 'RawHTML', 'Image', 'MultiImage', 'AutomaticProductList',
  17. 'PagePromotion', 'HandPickedProductList'])
  18. SelectForm, RawHTMLForm, PagePromotionForm, HandPickedProductListForm, OrderedProductFormSet = get_classes('dashboard.promotions.forms',
  19. ['PromotionTypeSelectForm', 'RawHTMLForm', 'PagePromotionForm',
  20. 'HandPickedProductListForm', 'OrderedProductFormSet'])
  21. class ListView(generic.TemplateView):
  22. template_name = 'dashboard/promotions/promotion_list.html'
  23. def get_context_data(self):
  24. # Need to load all promotions of all types and chain them together
  25. # no pagination required for now.
  26. data = []
  27. num_promotions = 0
  28. for klass in PROMOTION_CLASSES:
  29. objects = klass.objects.all()
  30. num_promotions += objects.count()
  31. data.append(objects)
  32. promotions = itertools.chain(*data)
  33. ctx = {
  34. 'num_promotions': num_promotions,
  35. 'promotions': promotions,
  36. 'select_form': SelectForm(),
  37. }
  38. return ctx
  39. class CreateRedirectView(generic.RedirectView):
  40. permanent = True
  41. def get_redirect_url(self, **kwargs):
  42. code = self.request.GET.get('promotion_type', None)
  43. urls = {}
  44. for klass in PROMOTION_CLASSES:
  45. urls[klass.classname()] = reverse('dashboard:promotion-create-%s' %
  46. klass.classname())
  47. return urls.get(code, None)
  48. class PageListView(generic.TemplateView):
  49. template_name = 'dashboard/promotions/pagepromotion_list.html'
  50. def get_context_data(self, *args, **kwargs):
  51. pages = PagePromotion.objects.all().values(
  52. 'page_url').distinct().annotate(freq=Count('id'))
  53. return {'pages': pages}
  54. class PageDetailView(generic.TemplateView):
  55. template_name = 'dashboard/promotions/page_detail.html'
  56. def get_context_data(self, *args, **kwargs):
  57. path = self.kwargs['path']
  58. return {'page_url': path,
  59. 'positions': self.get_positions_context_data(path), }
  60. def get_positions_context_data(self, path):
  61. ctx = []
  62. for code, name in settings.OSCAR_PROMOTION_POSITIONS:
  63. promotions = PagePromotion._default_manager.select_related() \
  64. .filter(page_url=path,
  65. position=code) \
  66. .order_by('display_order')
  67. ctx.append({
  68. 'code': code,
  69. 'name': name,
  70. 'promotions': promotions,
  71. })
  72. return ctx
  73. def post(self, request, **kwargs):
  74. """
  75. When called with a post request, try and get 'promo[]' from
  76. the post data and use it to reorder the page content blocks.
  77. """
  78. data = dict(request.POST).get('promo[]')
  79. self._save_page_order(data)
  80. return HttpResponse(status=200)
  81. def _save_page_order(self, data):
  82. """
  83. Save the order of the pages. This gets used when an ajax request
  84. posts backa new order for promotions within page regions.
  85. """
  86. for index, item in enumerate(data):
  87. page = PagePromotion.objects.get(pk=item)
  88. if page.display_order != index:
  89. page.display_order = index
  90. page.save()
  91. class PromotionMixin(object):
  92. def get_template_names(self):
  93. return ['dashboard/promotions/%s_form.html' % self.model.classname(),
  94. 'dashboard/promotions/form.html']
  95. class DeletePagePromotionView(generic.DeleteView):
  96. template_name = 'dashboard/promotions/delete_pagepromotion.html'
  97. model = PagePromotion
  98. def get_success_url(self):
  99. messages.info(self.request, _("Content block removed successfully"))
  100. return reverse('dashboard:promotion-list-by-url',
  101. kwargs={'path': self.object.page_url})
  102. # ============
  103. # CREATE VIEWS
  104. # ============
  105. class CreateView(PromotionMixin, generic.CreateView):
  106. def get_success_url(self):
  107. messages.success(self.request, _("Content block created successfully"))
  108. return reverse('dashboard:promotion-update',
  109. kwargs={'ptype': self.model.classname(),
  110. 'pk': self.object.id})
  111. def get_context_data(self, *args, **kwargs):
  112. ctx = super(CreateView, self).get_context_data(*args, **kwargs)
  113. ctx['heading'] = self.get_heading()
  114. return ctx
  115. def get_heading(self):
  116. if hasattr(self, 'heading'):
  117. return getattr(self, 'heading')
  118. return _('Create a new %s content block') % self.model._type
  119. class CreateRawHTMLView(CreateView):
  120. model = RawHTML
  121. form_class = RawHTMLForm
  122. class CreateSingleProductView(CreateView):
  123. model = SingleProduct
  124. class CreateImageView(CreateView):
  125. model = Image
  126. class CreateAutomaticProductListView(CreateView):
  127. model = AutomaticProductList
  128. class CreateHandPickedProductListView(CreateView):
  129. model = HandPickedProductList
  130. form_class = HandPickedProductListForm
  131. def get_context_data(self, **kwargs):
  132. ctx = super(CreateHandPickedProductListView,
  133. self).get_context_data(**kwargs)
  134. if 'product_formset' not in kwargs:
  135. ctx['product_formset'] = OrderedProductFormSet(instance=self.object)
  136. return ctx
  137. def form_valid(self, form):
  138. promotion = form.save(commit=False)
  139. product_formset = OrderedProductFormSet(self.request.POST,
  140. instance=promotion)
  141. if product_formset.is_valid():
  142. promotion.save()
  143. product_formset.save()
  144. self.object = promotion
  145. messages.success(self.request, _('Product list content block created'))
  146. return HttpResponseRedirect(self.get_success_url())
  147. ctx = self.get_context_data(product_formset=product_formset)
  148. return self.render_response(ctx)
  149. # ============
  150. # UPDATE VIEWS
  151. # ============
  152. class UpdateView(PromotionMixin, generic.UpdateView):
  153. actions = ('add_to_page', 'remove_from_page')
  154. link_form_class = PagePromotionForm
  155. def get_context_data(self, *args, **kwargs):
  156. ctx = super(UpdateView, self).get_context_data(*args, **kwargs)
  157. ctx['heading'] = _("Update content block")
  158. ctx['promotion'] = self.get_object()
  159. ctx['link_form'] = self.link_form_class()
  160. content_type = ContentType.objects.get_for_model(self.model)
  161. ctx['links'] = PagePromotion.objects.filter(content_type=content_type,
  162. object_id=self.object.id)
  163. return ctx
  164. def post(self, request, *args, **kwargs):
  165. action = request.POST.get('action', None)
  166. if action in self.actions:
  167. self.object = self.get_object()
  168. return getattr(self, action)(self.object, request, *args, **kwargs)
  169. return super(UpdateView, self).post(request, *args, **kwargs)
  170. def get_success_url(self):
  171. messages.info(self.request, _("Content block updated successfully"))
  172. return reverse('dashboard:promotion-list')
  173. def add_to_page(self, promotion, request, *args, **kwargs):
  174. instance = PagePromotion(content_object=self.get_object())
  175. form = self.link_form_class(request.POST, instance=instance)
  176. if form.is_valid():
  177. form.save()
  178. page_url = form.cleaned_data['page_url']
  179. messages.success(request, _("Content block '%(block)s' added to page '%(page)s'") % {
  180. 'block': promotion.name,
  181. 'page': page_url})
  182. return HttpResponseRedirect(reverse('dashboard:promotion-update', kwargs=kwargs))
  183. main_form = self.get_form_class()(instance=self.object)
  184. ctx = self.get_context_data(form=main_form)
  185. ctx['link_form'] = form
  186. return self.render_to_response(ctx)
  187. def remove_from_page(self, promotion, request, *args, **kwargs):
  188. link_id = request.POST['pagepromotion_id']
  189. try:
  190. link = PagePromotion.objects.get(id=link_id)
  191. except PagePromotion.DoesNotExist:
  192. messages.error(request, _("No link found to delete"))
  193. else:
  194. page_url = link.page_url
  195. link.delete()
  196. messages.success(request, _("Content block removed from page '%s'") % page_url)
  197. return HttpResponseRedirect(reverse('dashboard:promotion-update', kwargs=kwargs))
  198. class UpdateRawHTMLView(UpdateView):
  199. model = RawHTML
  200. form_class = RawHTMLForm
  201. class UpdateSingleProductView(UpdateView):
  202. model = SingleProduct
  203. class UpdateImageView(UpdateView):
  204. model = Image
  205. class UpdateAutomaticProductListView(UpdateView):
  206. model = AutomaticProductList
  207. class UpdateHandPickedProductListView(UpdateView):
  208. model = HandPickedProductList
  209. form_class = HandPickedProductListForm
  210. def get_context_data(self, **kwargs):
  211. ctx = super(UpdateHandPickedProductListView,
  212. self).get_context_data(**kwargs)
  213. if 'product_formset' not in kwargs:
  214. ctx['product_formset'] = OrderedProductFormSet(instance=self.object)
  215. return ctx
  216. def form_valid(self, form):
  217. promotion = form.save(commit=False)
  218. product_formset = OrderedProductFormSet(self.request.POST,
  219. instance=promotion)
  220. if product_formset.is_valid():
  221. promotion.save()
  222. product_formset.save()
  223. self.object = promotion
  224. messages.success(self.request, _('Product list promotion updated'))
  225. return HttpResponseRedirect(self.get_success_url())
  226. ctx = self.get_context_data(product_formset=product_formset)
  227. return self.render_to_response(ctx)
  228. # ============
  229. # DELETE VIEWS
  230. # ============
  231. class DeleteView(generic.DeleteView):
  232. template_name = 'dashboard/promotions/delete.html'
  233. def get_success_url(self):
  234. messages.info(self.request, _("Content block deleted successfully"))
  235. return reverse('dashboard:promotion-list')
  236. class DeleteRawHTMLView(DeleteView):
  237. model = RawHTML
  238. class DeleteSingleProductView(DeleteView):
  239. model = SingleProduct
  240. class DeleteImageView(DeleteView):
  241. model = Image
  242. class DeleteAutomaticProductListView(DeleteView):
  243. model = AutomaticProductList
  244. class DeleteHandPickedProductListView(DeleteView):
  245. model = HandPickedProductList