You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

views.py 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. # -*- coding: utf-8 -*-
  2. from django.contrib import messages
  3. from django.core.exceptions import (
  4. ObjectDoesNotExist, MultipleObjectsReturned, PermissionDenied)
  5. from django.core.urlresolvers import reverse
  6. from django.db.models import get_model
  7. from django.http import Http404, HttpResponseRedirect
  8. from django.shortcuts import get_object_or_404
  9. from django.views.generic import ListView, CreateView, UpdateView, DeleteView, View, FormView
  10. from django.utils.translation import ugettext_lazy as _
  11. from oscar.apps.customer.mixins import PageTitleMixin
  12. from oscar.core.loading import get_classes
  13. WishList = get_model('wishlists', 'WishList')
  14. Line = get_model('wishlists', 'Line')
  15. Product = get_model('catalogue', 'Product')
  16. WishListForm, LineFormset = get_classes('wishlists.forms',
  17. ['WishListForm', 'LineFormset'])
  18. class WishListListView(PageTitleMixin, ListView):
  19. context_object_name = active_tab = "wishlists"
  20. template_name = 'customer/wishlists/wishlists_list.html'
  21. page_title = _('Wish Lists')
  22. def get_queryset(self):
  23. return self.request.user.wishlists.all()
  24. class WishListDetailView(PageTitleMixin, FormView):
  25. """
  26. This view acts as a DetailView for a wish list and allows updating the
  27. quantities of products.
  28. It is implemented as FormView because it's easier to adapt a FormView to
  29. display a product then adapt a DetailView to handle form validation.
  30. """
  31. template_name = 'customer/wishlists/wishlists_detail.html'
  32. active_tab = "wishlists"
  33. form_class = LineFormset
  34. def dispatch(self, request, *args, **kwargs):
  35. self.object = self.get_wishlist_or_404(kwargs['key'], request.user)
  36. return super(WishListDetailView, self).dispatch(request, *args, **kwargs)
  37. def get_wishlist_or_404(self, key, user):
  38. wishlist = get_object_or_404(WishList, key=key)
  39. if wishlist.is_allowed_to_see(user):
  40. return wishlist
  41. else:
  42. raise Http404
  43. def get_page_title(self):
  44. return self.object.name
  45. def get_form_kwargs(self):
  46. kwargs = super(WishListDetailView, self).get_form_kwargs()
  47. kwargs['instance'] = self.object
  48. return kwargs
  49. def get_context_data(self, **kwargs):
  50. ctx = super(WishListDetailView, self).get_context_data(**kwargs)
  51. ctx['wishlist'] = self.object
  52. other_wishlists = self.request.user.wishlists.exclude(
  53. pk=self.object.pk)
  54. ctx['other_wishlists'] = other_wishlists
  55. return ctx
  56. def form_valid(self, form):
  57. for subform in form:
  58. if subform.cleaned_data['quantity'] <= 0:
  59. subform.instance.delete()
  60. else:
  61. subform.save()
  62. messages.success(self.request, _('Quantities updated.'))
  63. return HttpResponseRedirect(reverse('customer:wishlists-detail',
  64. kwargs= {'key': self.object.key}))
  65. class WishListCreateView(PageTitleMixin, CreateView):
  66. """
  67. Create a new wishlist
  68. If a product ID is assed as a kwargs, then this product will be added to
  69. the wishlist.
  70. """
  71. model = WishList
  72. template_name = 'customer/wishlists/wishlists_form.html'
  73. active_tab = "wishlists"
  74. page_title = _('Create a new wish list')
  75. form_class = WishListForm
  76. product = None
  77. def dispatch(self, request, *args, **kwargs):
  78. if 'product_pk' in kwargs:
  79. try:
  80. self.product = Product.objects.get(pk=kwargs['product_pk'])
  81. except ObjectDoesNotExist:
  82. messages.error(
  83. request, _("The requested product no longer exists"))
  84. return HttpResponseRedirect(reverse('wishlists-create'))
  85. return super(WishListCreateView, self).dispatch(
  86. request, *args, **kwargs)
  87. def get_context_data(self, **kwargs):
  88. ctx = super(WishListCreateView, self).get_context_data(**kwargs)
  89. ctx['product'] = self.product
  90. return ctx
  91. def get_form_kwargs(self):
  92. kwargs = super(WishListCreateView, self).get_form_kwargs()
  93. kwargs['user'] = self.request.user
  94. return kwargs
  95. def form_valid(self, form):
  96. wishlist = form.save()
  97. if self.product:
  98. wishlist.add(self.product)
  99. msg = _("Your wishlist has been created and '%(name)s "
  100. "has been added") % {
  101. 'name': self.product.get_title()}
  102. else:
  103. msg = _("Your wishlist has been created")
  104. messages.success(self.request, msg)
  105. return HttpResponseRedirect(wishlist.get_absolute_url())
  106. class WishListCreateWithProductView(View):
  107. """
  108. Create a wish list and immediately add a product to it
  109. """
  110. def post(self, request, *args, **kwargs):
  111. product = get_object_or_404(Product, pk=kwargs['product_pk'])
  112. wishlists = request.user.wishlists.all()
  113. if len(wishlists) == 0:
  114. wishlist = request.user.wishlists.create()
  115. else:
  116. # This shouldn't really happen but we default to using the first
  117. # wishlist for a user if one already exists when they make this
  118. # request.
  119. wishlist = wishlists[0]
  120. wishlist.add(product)
  121. messages.success(
  122. request, _("%(title)s has been added to your wishlist") % {
  123. 'title': product.get_title()})
  124. return HttpResponseRedirect(request.META.get(
  125. 'HTTP_REFERER', wishlist.get_absolute_url()))
  126. class WishListUpdateView(PageTitleMixin, UpdateView):
  127. model = WishList
  128. template_name = 'customer/wishlists/wishlists_form.html'
  129. active_tab = "wishlists"
  130. form_class = WishListForm
  131. context_object_name = 'wishlist'
  132. def get_page_title(self):
  133. return self.object.name
  134. def get_object(self, queryset=None):
  135. return get_object_or_404(WishList, owner=self.request.user,
  136. key=self.kwargs['key'])
  137. def get_form_kwargs(self):
  138. kwargs = super(WishListUpdateView, self).get_form_kwargs()
  139. kwargs['user'] = self.request.user
  140. return kwargs
  141. def get_success_url(self):
  142. messages.success(
  143. self.request, _("Your '%s' wishlist has been updated") % self.object.name)
  144. return reverse('customer:wishlists-list')
  145. class WishListDeleteView(PageTitleMixin, DeleteView):
  146. model = WishList
  147. template_name = 'customer/wishlists/wishlists_delete.html'
  148. active_tab = "wishlists"
  149. def get_page_title(self):
  150. return u'Delete %s' % self.object.name
  151. def get_object(self, queryset=None):
  152. return get_object_or_404(WishList, owner=self.request.user,
  153. key=self.kwargs['key'])
  154. def get_success_url(self):
  155. messages.success(
  156. self.request, _("Your '%s' wish list has been deleted") % self.object.name)
  157. return reverse('customer:wishlists-list')
  158. class WishListAddProduct(View):
  159. """
  160. Adds a product to a wish list.
  161. - If the user doesn't already have a wishlist then it will be created for
  162. them.
  163. - If the product is already in the wish list, its quantity is increased.
  164. """
  165. def dispatch(self, request, *args, **kwargs):
  166. self.product = get_object_or_404(Product, pk=kwargs['product_pk'])
  167. self.wishlist = self.get_or_create_wishlist(request, *args, **kwargs)
  168. return super(WishListAddProduct, self).dispatch(request)
  169. def get_or_create_wishlist(self, request, *args, **kwargs):
  170. wishlists = request.user.wishlists.all()
  171. num_wishlists = len(wishlists)
  172. if num_wishlists == 0:
  173. return request.user.wishlists.create()
  174. wishlist = wishlists[0]
  175. if not wishlist.is_allowed_to_edit(request.user):
  176. raise PermissionDenied
  177. return wishlist
  178. def get(self, request, *args, **kwargs):
  179. # This is nasty as we shouldn't be performing write operations on a GET
  180. # request. It's only included as the UI of the product detail page
  181. # allows a wishlist to be selected from a dropdown.
  182. return self.add_product()
  183. def post(self, request, *args, **kwargs):
  184. return self.add_product()
  185. def add_product(self):
  186. self.wishlist.add(self.product)
  187. msg = _("'%s' was added to your wish list." % self.product.get_title())
  188. messages.success(self.request, msg)
  189. return HttpResponseRedirect(
  190. self.request.META.get('HTTP_REFERER',
  191. self.product.get_absolute_url()))
  192. class LineMixin(object):
  193. """
  194. Handles fetching both a wish list and a product
  195. Views using this mixin must be passed two keyword arguments:
  196. * key: The key of a wish list
  197. * line_pk: The primary key of the wish list line
  198. or
  199. * product_pk: The primary key of the product
  200. """
  201. def dispatch(self, request, *args, **kwargs):
  202. self.wishlist = get_object_or_404(
  203. WishList, owner=request.user, key=kwargs['key'])
  204. try:
  205. if 'line_pk' in kwargs:
  206. self.line = self.wishlist.lines.get(pk=kwargs['line_pk'])
  207. elif 'product_pk' in kwargs:
  208. self.line = self.wishlist.lines.get(
  209. product_id=kwargs['product_pk'])
  210. except (ObjectDoesNotExist, MultipleObjectsReturned):
  211. raise Http404
  212. self.product = self.line.product
  213. return super(LineMixin, self).dispatch(request, *args, **kwargs)
  214. class WishListRemoveProduct(LineMixin, View):
  215. def post(self, request, *args, **kwargs):
  216. self.line.delete()
  217. msg = _("'%(title)s' was removed from your '%(name)s' wish list") % {
  218. 'title': self.product.get_title(),
  219. 'name': self.wishlist.name}
  220. messages.success(self.request, msg)
  221. default_url = reverse(
  222. 'customer:wishlists-detail', kwargs={'key': self.wishlist.key})
  223. return HttpResponseRedirect(self.request.META.get(
  224. 'HTTP_REFERER', default_url))
  225. class WishListMoveProductToAnotherWishList(LineMixin, View):
  226. def get(self, request, *args, **kwargs):
  227. to_wishlist = get_object_or_404(
  228. WishList, owner=request.user, key=kwargs['to_key'])
  229. self.line.wishlist = to_wishlist
  230. self.line.save()
  231. msg = _("'%(title)s' moved to '%(name)s' wishlist") % {
  232. 'title': self.product.get_title(),
  233. 'name': to_wishlist.name}
  234. messages.success(self.request, msg)
  235. default_url = reverse(
  236. 'customer:wishlists-detail', kwargs={'key': self.wishlist.key})
  237. return HttpResponseRedirect(self.request.META.get(
  238. 'HTTP_REFERER', default_url))