Snipt for Teams beta program.

master
Nick Sergeant 2015-07-22 14:01:27 -04:00
parent 82c3fa39e4
commit 66d0ea7a05
15 changed files with 351 additions and 18 deletions

View File

@ -0,0 +1,85 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'UserProfile.teams_beta_seen'
db.add_column(u'accounts_userprofile', 'teams_beta_seen',
self.gf('django.db.models.fields.BooleanField')(default=False),
keep_default=False)
def backwards(self, orm):
# Deleting field 'UserProfile.teams_beta_seen'
db.delete_column(u'accounts_userprofile', 'teams_beta_seen')
models = {
u'accounts.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'blog_domain': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'blog_theme': ('django.db.models.fields.CharField', [], {'default': "'A'", 'max_length': '1'}),
'blog_title': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'default_editor': ('django.db.models.fields.CharField', [], {'default': "'C'", 'max_length': '250'}),
'disqus_shortname': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'editor_theme': ('django.db.models.fields.CharField', [], {'default': "'default'", 'max_length': '250'}),
'gauges_site_id': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'gittip_username': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'google_ad_client': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'google_ad_height': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'google_ad_slot': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'google_ad_width': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'google_analytics_tracking_id': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'has_gravatar': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_pro': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'list_view': ('django.db.models.fields.CharField', [], {'default': "'N'", 'max_length': '1'}),
'pro_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'stripe_id': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'teams_beta_seen': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'})
},
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['accounts']

View File

@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'UserProfile.teams_beta_applied'
db.add_column(u'accounts_userprofile', 'teams_beta_applied',
self.gf('django.db.models.fields.BooleanField')(default=False),
keep_default=False)
def backwards(self, orm):
# Deleting field 'UserProfile.teams_beta_applied'
db.delete_column(u'accounts_userprofile', 'teams_beta_applied')
models = {
u'accounts.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'blog_domain': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'blog_theme': ('django.db.models.fields.CharField', [], {'default': "'A'", 'max_length': '1'}),
'blog_title': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'default_editor': ('django.db.models.fields.CharField', [], {'default': "'C'", 'max_length': '250'}),
'disqus_shortname': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'editor_theme': ('django.db.models.fields.CharField', [], {'default': "'default'", 'max_length': '250'}),
'gauges_site_id': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'gittip_username': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'google_ad_client': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'google_ad_height': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'google_ad_slot': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'google_ad_width': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'google_analytics_tracking_id': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'has_gravatar': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_pro': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'list_view': ('django.db.models.fields.CharField', [], {'default': "'N'", 'max_length': '1'}),
'pro_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'stripe_id': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'teams_beta_applied': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'teams_beta_seen': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'})
},
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['accounts']

View File

@ -44,6 +44,8 @@ class UserProfile(models.Model):
# User # User
user = models.ForeignKey(User, unique=True) user = models.ForeignKey(User, unique=True)
is_pro = models.BooleanField(default=False) is_pro = models.BooleanField(default=False)
teams_beta_seen = models.BooleanField(default=False)
teams_beta_applied = models.BooleanField(default=False)
pro_date = models.DateTimeField(blank=True, null=True) pro_date = models.DateTimeField(blank=True, null=True)
stripe_id = models.CharField(max_length=100, null=True, blank=True) stripe_id = models.CharField(max_length=100, null=True, blank=True)
has_gravatar = models.BooleanField(default=False) has_gravatar = models.BooleanField(default=False)

File diff suppressed because one or more lines are too long

View File

@ -2222,6 +2222,24 @@ div.info {
} }
} }
} }
body.pro-signup {
div.info {
padding: 49px 0;
}
form ul.features {
margin: 20px auto 0 auto;
padding: 0;
width: 328px;
li {
font-size: 16px;
font-weight: normal;
line-height: 22px;
margin: 10px 20px;
text-align: left;
}
}
}
body.pro-signup-complete { body.pro-signup-complete {
div.info { div.info {
margin-bottom: 0; margin-bottom: 0;

View File

@ -50,7 +50,7 @@
<section class="snipts" id="snipts"> <section class="snipts" id="snipts">
{% if not request.user.is_authenticated %} {% if not request.user.is_authenticated %}
{% include 'ad-leaderboard.html' %} {% include 'ad-leaderboard.html' %}
{% elif not request.user.profile.is_pro %} {% elif not request.user.profile.teams_beta_seen %}
{% include 'ad-leaderboard-pro.html' %} {% include 'ad-leaderboard-pro.html' %}
{% endif %} {% endif %}
{% with 'true' as detail %} {% with 'true' as detail %}

View File

@ -18,7 +18,7 @@
{% endif %}> {% endif %}>
{% if not request.user.is_authenticated %} {% if not request.user.is_authenticated %}
{% include 'ad-leaderboard.html' %} {% include 'ad-leaderboard.html' %}
{% elif not request.user.profile.is_pro %} {% elif not request.user.profile.teams_beta_seen %}
{% include 'ad-leaderboard-pro.html' %} {% include 'ad-leaderboard-pro.html' %}
{% endif %} {% endif %}
{% autopaginate snipts 10 %} {% autopaginate snipts 10 %}

View File

@ -1,4 +1,4 @@
<a href="/pro/" class="snipt-promo"> <a href="/for-teams/" class="snipt-promo">
<button class="btn btn-success btn-large pull-right">Go Pro &raquo;</button> <button class="btn btn-success btn-large pull-right">More info &raquo;</button>
Go <span class="pro">Pro</span> today for only five bucks a month. Announcing Snipt for Teams! <br />Starting at just $49/month.
</a> </a>

View File

@ -41,7 +41,7 @@
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/highlightjs-themes/tomorrow.css" /> <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/highlightjs-themes/tomorrow.css" />
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/blog-themes/default/style.css" /> <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/blog-themes/default/style.css" />
{% else %} {% else %}
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/snipt.css?113" /> <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/snipt.css?114" />
{% endif %} {% endif %}
{% if has_snipts and not detail %} {% if has_snipts and not detail %}
@ -104,6 +104,9 @@
<li> <li>
<a href="/public/" {% if '/public/' in request.path or public %} class="active"{% endif %}>Public snipts</a> <a href="/public/" {% if '/public/' in request.path or public %} class="active"{% endif %}>Public snipts</a>
</li> </li>
<li>
<a href="/for-teams/" {% if '/for-teams/' in request.path %} class="active"{% endif %}>Teams</a>
</li>
{% block add-snipt %}{% endblock %} {% block add-snipt %}{% endblock %}
{% endif %} {% endif %}
</ul> </ul>
@ -151,6 +154,12 @@
</a> </a>
</li> </li>
{% endif %} {% endif %}
<li>
<a href="/for-teams/">
<i class="icon-star-empty icon-white"></i>
For Teams
</a>
</li>
{% if request.user.is_superuser %} {% if request.user.is_superuser %}
<li> <li>
<a href="/admin/"> <a href="/admin/">
@ -208,6 +217,9 @@
<a href="/pro/"><span>Go Pro</span></a> <a href="/pro/"><span>Go Pro</span></a>
</li> </li>
{% endif %} {% endif %}
<li class="pro">
<a href="/for-teams/"><span>For Teams</span></a>
</li>
<li class="blog"> <li class="blog">
<a href="https://blog.snipt.net/"><span>Snipt Blog</span></a> <a href="https://blog.snipt.net/"><span>Snipt Blog</span></a>
</li> </li>

View File

@ -0,0 +1,30 @@
{% extends "base.html" %}
{% block page-title %}Sign up for Snipt Pro{% endblock %}
{% block body-class %}{{ block.super }} static pro signup pro-signup pro-signup-complete{% endblock %}
{% block breadcrumb %}
<li><a href="/for-teams/">For Teams</a></li>
<li><span class="prompt">/</span> <a href="#">Complete</a></li>
{% endblock %}
{% block content %}
<form class="form-horizontal static-box" id="pro-signup" method="post" action="/pro/complete/">
<fieldset>
<div class="info">
You rock.
<p class="sub" style="padding: 0 120px;">
We'll email you to arrange the beta program payment of $49, and help you get your first team created!<br /><br />
If you ever need anything at all, <a href="mailto:support@snipt.net">email support</a>, or use the chat in the bottom right.
</p>
</div>
</fieldset>
</form>
{% endblock %}
{% block analytics %}
{% if not debug %}
window.ll('tagScreen', 'Pro signup complete view');
{% endif %}
{% endblock %}

61
templates/for-teams.html Normal file
View File

@ -0,0 +1,61 @@
{% extends "base.html" %}
{% block page-title %}Request beta access to Snipt for Teams{% endblock %}
{% block body-class %}{{ block.super }} static signup pro pro-signup{% endblock %}
{% block breadcrumb %}
<li><a href="/for-teams/">Snipt for Teams</a></li>
{% endblock %}
{% block content %}
{% if request.user.profile.teams_beta_applied %}
<div class="alert alert-success" style="margin: 30px;">
You've successfully applied for the beta program - we'll email you as soon as we're ready!
</div>
{% else %}
<form class="form-horizontal static-box" id="pro-signup" method="post" action="/for-teams/complete/">
<fieldset>
<div class="info">
Snipt for Teams private beta!
<ul class="features">
<li>Team profile at snipt.net/{team-name}.</li>
<li>Members can create public or private snipts on a team.</li>
<li>Public team posts are public to the world, as they are now.</li>
<li>Private team posts are editable by all team members.</li>
<li>All team members are automatically granted personal <span class="pro">Pro</span> accounts.</li>
<li>Beta period is a one-time fee of $49, then plans starting at $49/month.</li>
</ul>
</div>
<div class="control-group">
<label class="control-label" for="name">Team name:</label>
<div class="controls">
<input required type="text" class="input-xlarge" name="name" id="name" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="members">How many users?</label>
<div class="controls">
<input required type="number" class="input-medium" name="members" id="members" />
</div>
</div>
<div class="control-group">
<label style="float: none; width: auto; text-align: left; padding-left: 180px; margin-bottom: 10px;" class="control-label" for="members">Tell us a bit about your organization and how<br />you'd like to use Snipt for your team:</label>
<div class="controls">
<textarea required name="info" name="info" id="info" class="input-xlarge" style="height: 100px;"></textarea>
</div>
</div>
<div class="form-actions">
{% csrf_token %}
<button type="submit" class="btn btn-success">Request beta access &raquo;</button>
</div>
</fieldset>
</form>
{% endif %}
{% endblock %}
{% block analytics %}
{% if not debug %}
window.ll('tagScreen', 'Team beta signup view');
{% endif %}
{% endblock %}

View File

@ -17,7 +17,7 @@
<p class="sub"> <p class="sub">
You're now a Snipt Pro.<br /><br /> You're now a Snipt Pro.<br /><br />
You should <a target="blank" href="http://twitter.com/intent/tweet?text=I'm now a @Snipt Pro. Are you? https://snipt.net/pro/">tell the world</a>. You should <a target="blank" href="http://twitter.com/intent/tweet?text=I'm now a @Snipt Pro. Are you? https://snipt.net/pro/">tell the world</a>.
If you ever need anything at all, <a href="mailto:nick@snipt.net">email Nick directly</a>, or use the support link in the bottom right. If you ever need anything at all, <a href="mailto:support@snipt.net">email support</a>, or use the chat in the bottom right.
</p> </p>
</div> </div>
</fieldset> </fieldset>

View File

@ -113,7 +113,7 @@
</div> </div>
<div class="form-actions"> <div class="form-actions">
{% csrf_token %} {% csrf_token %}
<button type="submit" class="btn btn-success">Subscribe</button> <button type="submit" class="btn btn-success">Subscribe &raquo;</button>
<div class="security"> <div class="security">
<a href="https://stripe.com/help/security">Secure</a> by default. Every Snipt page is secure. <a href="https://stripe.com/help/security">Secure</a> by default. Every Snipt page is secure.
</div> </div>

View File

@ -13,7 +13,7 @@ from tastypie.api import Api
from utils.views import SniptRegistrationView from utils.views import SniptRegistrationView
from jobs.views import jobs, jobs_json from jobs.views import jobs, jobs_json
from views import (homepage, lexers, login_redirect, pro, sitemap, tags, from views import (homepage, lexers, login_redirect, pro, sitemap, tags,
pro_complete, user_api_key) pro_complete, user_api_key, for_teams, for_teams_complete)
import admin as custom_admin import admin as custom_admin
import os import os
@ -50,6 +50,9 @@ urlpatterns = patterns('',
url(r'^pro/$', pro), url(r'^pro/$', pro),
url(r'^pro/complete/$', pro_complete), url(r'^pro/complete/$', pro_complete),
url(r'^for-teams/$', for_teams),
url(r'^for-teams/complete/$', for_teams_complete),
url(r'^account/', include('accounts.urls')), url(r'^account/', include('accounts.urls')),
url(r'^api/public/lexer/$', lexers), url(r'^api/public/lexer/$', lexers),

View File

@ -12,21 +12,47 @@ from django.contrib.auth.models import User
from django.db.models import Count from django.db.models import Count
from snipts.models import Snipt from snipts.models import Snipt
from taggit.models import Tag from taggit.models import Tag
from django.core.mail import send_mail
import datetime import datetime
import hashlib import hashlib
import os import os
import stripe import stripe
@ajax_request @render_to('for-teams.html')
def user_api_key(request): def for_teams(request):
if request.user.is_authenticated():
profile = request.user.profile
profile.teams_beta_seen = True
profile.save()
return {}
if not request.user.is_authenticated(): @login_required
return HttpResponseBadRequest() @render_to('for-teams-complete.html')
def for_teams_complete(request):
return { if request.method == 'POST':
'api_key': request.user.api_key.key name = request.POST['name']
} members = request.POST['members']
info = request.POST['info']
send_mail('[Snipt] New Snipt for Teams beta request.', """
User: %s (%s)
Team name: %s
Team members: %s
Info:
%s
""" % (request.user.username, request.user.email, name, members, info), 'support@snipt.net',
['nick@nicksergeant.com'], fail_silently=False)
profile = request.user.profile
profile.teams_beta_applied = True
profile.save()
return {}
else:
return HttpResponseBadRequest()
@render_to('homepage.html') @render_to('homepage.html')
def homepage(request): def homepage(request):
@ -156,3 +182,13 @@ def tags(request):
'all_tags': all_tags, 'all_tags': all_tags,
'tags': popular_tags 'tags': popular_tags
} }
@ajax_request
def user_api_key(request):
if not request.user.is_authenticated():
return HttpResponseBadRequest()
return {
'api_key': request.user.api_key.key
}