from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.core.exceptions import SuspiciousOperation
from django.utils.decorators import classonlymethod
from django.utils.decorators import method_decorator
from django.utils.translation import ugettext_lazy as _
from django.shortcuts import render_to_response, get_object_or_404
from django.contrib.auth.models import User
from django.template import RequestContext
from django.core.cache import cache
from django.conf import settings
from django import forms
from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
from django.contrib.admin.views.decorators import staff_member_required
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import (ListView, TemplateView, View, FormView,
DetailView, UpdateView)
from django.views.generic.edit import FormMixin
from django.core.urlresolvers import reverse
from pyspreedly.api import Client
from spreedly.models import Plan, Subscription
import spreedly.settings as spreedly_settings
from spreedly.forms import SubscribeForm, SubscribeUpdateForm
from spreedly import signals
[docs]class SubscribeMixin(FormMixin):
"""
inherits from FormMixin, handles, get_success_url, form valid, invalid and
post. Needs to be integerated into get context data and get_success_url
"""
form_class = SubscribeForm
success_url = 'spreedly_email_sent'
def get_success_url(self):
return reverse(self.success_url, args=[self.request.user_id])
def form_valid(self, form):
form.save()
super(SubscribeMixin, self).form_valid(form)
def form_invalid(self, form):
self.render_to_response(self.get_context_data(
object_list=self.object_list, form=form))
def post(self):
form_class = self.get_form_class()
form = self.get_form(form_class)
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
[docs]class PlanList(SubscribeMixin, ListView):
"""
inherits from :py:class:`ListView` and :py:class:`FormMixin`, hybrid list and
subscription entry view.
default template name is `spreedly_plan_list.html`,
object_list name is `plans`
cache's plans for 24 hours
"""
template_name = "spreedly/plan_list.html"
model = Plan
context_object_name = 'plans'
[docs] def get_context_data(self, object_list, **kwargs):
"""
Adds form and object list plus whatever else is passed as a kwarg
to the context.
:param object_list: list of :py:class:`Plan`s (actually queryset)
"""
context = ListView.get_context_data(self, object_list=object_list)
context.update(SubscribeMixin.get_context_data(self, **kwargs))
if self.request.user.is_authenticated():
try:
context['current_user_subscription'] = self.request.user.subscription
except Subscription.DoesNotExist:
context['current_user_subscription'] = None
return context
[docs] def get_queryset(self):
"""
Gets and caches the plan list for 1 day
"""
cache_key = 'spreedly_plans_list'
plans = cache.get(cache_key)
if not plans:
Plan.objects.sync_plans()
plans = Plan.objects.enabled()
cache.set(cache_key, plans, 60*60*24)
return plans
[docs] def get(self, *args, **kwargs):
"""
Gets the form and object list and returns a rendered template
"""
form_class = self.get_form_class()
form = self.get_form(form_class)
self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty()
if not allow_empty and len(self.object_list) == 0:
raise Http404(_(u"Empty list and '%(class_name)s.allow_empty' is False.")
% {'class_name': self.__class__.__name__})
context = self.get_context_data(object_list=self.object_list, form=form, **kwargs)
return self.render_to_response(context)
[docs]class EmailSent(TemplateView):
"""
A thankyou page for after registration saying an email has been sent
"""
template_name = 'spreedly/email_sent.html'
def get_context_data(self, *args, **kwargs):
self.context_data = super(EmailSent, self).get_context_data(*args, **kwargs)
self.context_data['user'] = get_object_or_404(User, pk=self.kwargs['user_id'])
return self.context_data
class SpreedlyReturn(TemplateView):
template_name = 'spreedly/return.html'
def create_subscription(self, user, plan):
if self.request.GET.has_key('trial') or plan.plan_type == 'free_trial':
if plan.trial_eligible(user):
subscription = plan.start_trial(user)
else:
raise SuspiciousOperation("Trial asked for - but you are not eligibile for a free trial")
else:
subscription = Subscription.objects.create_local(user, plan)
return subscription
def get_context_data(self, plan, subscription, *args, **kwargs):
# removed gift, request and login url
self.context_data = super(SpreedlyReturn,self).get_context_data(*args, **kwargs)
self.context_data['plan'] = plan
if self.request.GET.has_key('next'):
self.context_data['next'] = self.request.GET['next']
self.context_data['subscription'] = subscription
return self.context_data
def get(self,request, *args, **kwargs):
user = get_object_or_404(User, pk=self.kwargs['user_id'])
plan = get_object_or_404(Plan, pk=self.kwargs['plan_pk'])
subscription = self.create_subscription(user, plan)
context_data = self.get_context_data(plan, subscription, **kwargs)
return self.render_to_response(context_data)
@csrf_exempt
def spreedly_listener(request):
if request.method == 'POST':
# Try to extract customers' IDs
if request.POST.has_key('subscriber_ids'):
subscriber_ids = request.POST['subscriber_ids'].split(',')
if len(subscriber_ids):
client = Client(settings.SPREEDLY_AUTH_TOKEN, settings.SPREEDLY_SITE_NAME)
for id in subscriber_ids:
# Now let's query Spreedly API for the actual changes
data = client.get_info(int(id))
try:
user = User.objects.get(pk=id)
subscription, created = Subscription.objects.get_or_create(user=user)
for k, v in data.items():
if hasattr(subscription, k):
setattr(subscription, k, v)
subscription.save()
signals.subscription_update.send(sender=subscription, user=User.objects.get(id=id))
except User.DoesNotExist:
# TODO not sure what exactly to do here. Delete the subscripton on spreedly?
pass
return HttpResponse() #200 OK
[docs]class SubscriptionDetails(DetailView):
"""
view to see subscription details. takes subscription id as an optional
parameter. if it is not there return the user's subscription if available,
if not 404. if user.is_staff() - then you can see any Subscription details.
"""
model = Subscription
context_object_name = 'subscription'
template_name = 'spreedly/subscription_details.html'
pk_url_kwarg = 'user_id'
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
if not kwargs or not kwargs.get('user_id'):
kwargs['user_id'] = request.user.id
return super(SubscriptionDetails, self).dispatch(request, *args, **kwargs)
class PlanDetails(DetailView, SubscribeMixin):
model = Plan
pk_url_kwarg = 'plan_pk'
slug_url_kwarg = 'plan_pk'
context_object_name = 'plan'
template_name = 'spreedly/plan_details.html'
def get_context_data(self, **kwargs):
context = DetailView.get_context_data(self, **kwargs)
if self.request.user.is_authenticated():
context['current_user_subscription'] = getattr(self.request.user, 'subscription', None)
else:
context['current_user_subscription'] = None
return context
def get(self, *args, **kwargs):
self.object = self.get_object()
kwargs['object'] = self.object
form_class = self.get_form_class()
form = self.get_form(form_class)
form.fields['subscription'].widget = forms.HiddenInput()
form.fields['subscription'].initial = self.object
kwargs['form'] = form
context = self.get_context_data(**kwargs)
return self.render_to_response(context)
class EditSubscriber(UpdateView):
model = Subscription
form = SubscribeUpdateForm
def dispatch(self, *args, **kwargs):
raise NotImplementedError