Skip to content

Instantly share code, notes, and snippets.

@melinath
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save melinath/2827bf779045dc330849 to your computer and use it in GitHub Desktop.
Save melinath/2827bf779045dc330849 to your computer and use it in GitHub Desktop.
View spec example

These are example view specs for brambling's UserDashboardView and InviteAcceptView.

User dashboard

template: brambling/dashboard.html

Context

  • upcoming_events: A list of public Events that haven't started yet, ordered by how soon they start
  • upcoming_events_interest: A list of public Events in the user's interest groups that haven't started yet, ordered by how soon they start
  • admin_events: A list of Events that the user can edit, ordered by how recently they were edited
  • registered_events: A list of upcoming Events that the user has bought (or started buying) a ticket for, ordered by when the event will start
  • past_events: A list of Events that have already started and which the user has bought tickets for, even if that ticket was later refunded, ordered from earliest start date to latest.

Note: This represents the current functionality, not necessarily what it should be. :-p Right now, an event that is happening will disappear from registered_events, upcoming_events, and upcoming_events_interest the day after it starts. If the user is registered for the event, it will then start showing up in past_events. We should probably add an ongoing_events category, or else keep things in upcoming_events until they end.

class UserDashboardView(TemplateView):
template_name = "brambling/dashboard.html"
def get_context_data(self):
user = self.request.user
today = timezone.now().date()
upcoming_events = Event.objects.filter(
privacy=Event.PUBLIC,
is_published=True,
).annotate(start_date=Min('dates__date'), end_date=Max('dates__date')
).filter(start_date__gte=today).order_by('start_date')
upcoming_events_interest = Event.objects.filter(
privacy=Event.PUBLIC,
dance_styles__person=user,
is_published=True,
).annotate(start_date=Min('dates__date'), end_date=Max('dates__date')
).filter(start_date__gte=today).order_by('start_date')
admin_events = Event.objects.filter(
(Q(owner=user) | Q(editors=user)),
).annotate(start_date=Min('dates__date'), end_date=Max('dates__date')
).order_by('-last_modified')
# Registered events is upcoming things you are / might be going to.
# So you've paid for something or you're going to.
registered_events = list(Event.objects.filter(
order__person=user,
order__bought_items__status__in=(BoughtItem.PAID, BoughtItem.RESERVED),
).annotate(start_date=Min('dates__date'), end_date=Max('dates__date')
).filter(start_date__gte=today).order_by('start_date'))
re_dict = dict((e.pk, e) for e in registered_events)
orders = Order.objects.filter(
person=user,
bought_items__status=BoughtItem.RESERVED,
event__in=registered_events
)
for order in orders:
order.event = re_dict[order.event_id]
order.event.order = order
# Past events is things you at one point paid for.
# So you've paid for something, even if it was later refunded.
past_events = Event.objects.filter(
order__person=user,
order__bought_items__status__in=(BoughtItem.PAID, BoughtItem.REFUNDED),
).annotate(start_date=Min('dates__date'), end_date=Max('dates__date')
).filter(start_date__lt=today).order_by('-start_date')
return {
'upcoming_events': upcoming_events,
'upcoming_events_interest': upcoming_events_interest,
'admin_events': admin_events,
'registered_events': registered_events,
'past_events': past_events,
}
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(UserDashboardView, self).dispatch(*args, **kwargs)

Accepting invitation

template: brambling/invite.html

Context

  • invite: The invitation that the user is accepting (or None)
  • signup_form: an instance of the dancerfly signup form, with the email autofilled from the invitation (if there is one)
  • login_form: an instance of the dancerfly login form, with the username autofilled from the invitation (if there is one)

Note: there is a bug in this view. Since self.invite might be None, accessing self.invite.email could easily raise an AttributeError.

Functionality

Note: This part doesn't have as much to do with the templates / design, but it can be useful for having an understanding of what's happening if it's more complex than just rendering a template.

If the user is already logged in and the invitation was sent to their email address, check what type of invite it was and fulfill the invitation, then redirect them accordingly. Otherwise, render the template with the necessary context.

class InviteAcceptView(TemplateView):
template_name = 'brambling/invite.html'
def get(self, request, *args, **kwargs):
try:
invite = Invite.objects.get(code=kwargs['code'])
except Invite.DoesNotExist:
invite = None
else:
if request.user.is_authenticated() and request.user.email == invite.email:
if invite.kind == Invite.EDITOR:
event = Event.objects.get(pk=invite.content_id)
event.editors.add(request.user)
url = reverse('brambling_event_update', kwargs={'slug': event.slug})
elif invite.kind == Invite.HOME:
old_home = request.user.home
home = Home.objects.get(pk=invite.content_id)
request.user.home = home
request.user.save()
if old_home and not old_home.residents.exists():
old_home.delete()
url = reverse('brambling_home')
invite.delete()
return HttpResponseRedirect(url)
self.invite = invite
return super(InviteAcceptView, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(InviteAcceptView, self).get_context_data(**kwargs)
context.update({
'invite': self.invite,
'signup_form': SignUpForm(self.request),
'login_form': FloppyAuthenticationForm(),
})
context['signup_form'].initial['email'] = self.invite.email
context['login_form'].initial['username'] = self.invite.email
return context
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment