From d5c605e4ade39eaa67f8633a3eb5646bfb229f6d Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Wed, 27 Oct 2010 14:53:51 -0400 Subject: [PATCH] Initial commit --- __init__.py | 0 fixtures/categories_default.json | 1 + manage.py | 11 + redditors/.models.py.swp | Bin 0 -> 12288 bytes redditors/.views.py.swp | Bin 0 -> 12288 bytes redditors/__init__.py | 0 redditors/admin.py | 16 ++ redditors/models.py | 62 +++++ redditors/tests.py | 23 ++ redditors/views.py | 242 +++++++++++++++++ settings.py | 78 ++++++ templates/base.html | 291 +++++++++++++++++++++ templates/locations/add.html | 95 +++++++ templates/locations/checkin.html | 32 +++ templates/locations/get_coords_nearby.html | 100 +++++++ templates/locations/home.html | 45 ++++ templates/locations/search.html | 66 +++++ templates/locations/show_nearby.html | 44 ++++ templates/locations/view.html | 197 ++++++++++++++ templates/registration/login.html | 28 ++ templates/registration/register.html | 14 + urls.py | 27 ++ 22 files changed, 1372 insertions(+) create mode 100644 __init__.py create mode 100644 fixtures/categories_default.json create mode 100644 manage.py create mode 100644 redditors/.models.py.swp create mode 100644 redditors/.views.py.swp create mode 100644 redditors/__init__.py create mode 100644 redditors/admin.py create mode 100644 redditors/models.py create mode 100644 redditors/tests.py create mode 100644 redditors/views.py create mode 100644 settings.py create mode 100644 templates/base.html create mode 100644 templates/locations/add.html create mode 100644 templates/locations/checkin.html create mode 100644 templates/locations/get_coords_nearby.html create mode 100644 templates/locations/home.html create mode 100644 templates/locations/search.html create mode 100644 templates/locations/show_nearby.html create mode 100644 templates/locations/view.html create mode 100644 templates/registration/login.html create mode 100644 templates/registration/register.html create mode 100644 urls.py diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fixtures/categories_default.json b/fixtures/categories_default.json new file mode 100644 index 0000000..d0c7c37 --- /dev/null +++ b/fixtures/categories_default.json @@ -0,0 +1 @@ +[{"pk": 1, "model": "redditors.locationcategory", "fields": {"name": "Dive Bar"}}, {"pk": 2, "model": "redditors.locationcategory", "fields": {"name": "Lounge"}}, {"pk": 3, "model": "redditors.locationcategory", "fields": {"name": "Restaurant"}}, {"pk": 4, "model": "redditors.locationcategory", "fields": {"name": "Drunk Food"}}, {"pk": 5, "model": "redditors.locationcategory", "fields": {"name": "Open Area"}}, {"pk": 6, "model": "redditors.locationcategory", "fields": {"name": "House"}}, {"pk": 7, "model": "redditors.locationcategory", "fields": {"name": "Store"}}] \ No newline at end of file diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..5e78ea9 --- /dev/null +++ b/manage.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python +from django.core.management import execute_manager +try: + import settings # Assumed to be in the same directory. +except ImportError: + import sys + sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) + sys.exit(1) + +if __name__ == "__main__": + execute_manager(settings) diff --git a/redditors/.models.py.swp b/redditors/.models.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..0500c393685fca212e7317af17f4bd17c324430b GIT binary patch literal 12288 zcmeI2J#W-77{^^ChDa0;6$7xCqDohZ%Uxf@OQl<&DnhgpLRS`s$Vq%T_Z&Oej@nz` z3n0OWDn0>Btgyqt2ofU`d7u~`FJeK})694@?kAL=ZI*0B1w>Rije~~~t zP007%ck54If0%mymJl;!s`xyqgp-lm@my< zq%&tWC(lC%5>EW9fPi>e9!e1fQJ+Tx zp==%PhSriZRR#olESGLvUBpxn@}Q@46$jz4p0vNxYBi(iJPw2kn5*5Z%<-;Bd6|Rd zP6tYF|4Nb@19!jW@V7aK!_5I<9e0oC5Vj?Zd!t+A+8iWu)Jak-J^CQ&aCAMruHhEf z8%(i;n+9xW!gb1>*+c5C7OL7*Yed{xURt~Y#v(}_WYUg~kJo`k^o&kvyv039= literal 0 HcmV?d00001 diff --git a/redditors/.views.py.swp b/redditors/.views.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..3dde1767f3f435bc59be613c9fcf74e12f2daa8a GIT binary patch literal 12288 zcmeI2&x;&I6vu1hk2uC?(1Tu-%7$fTakh6&5M?1~$ghngCTtR;(J<-huIZ`Wo~lVz z^{%6Cga}4Y9u0`#KcFNY^q>eLh#)8kBIF`?5kZ0ny@~j(n(5h|ne1kBOsItqz1>~) z-mC9>^=d=9KJ&t%BlM|YC&AA)Le75l?cpzf{eJAy7lf!zDD2}K{nVLQ2wPlCwW36Y zrm3e|VN{oLajLCkkjf}bor&|-;PgHjWi2L*p2ph+7U7qAs8}3xGu^#NrKguTTh>9l zb0gpWy;s01umJ@!)0ldCE7`U4i5WY3$M|;o(1Ry8Fwqb33U~#)0$u^HfLFjP;1%!+ zcm-}31x$O4yotqZ>MiKS-gRu~+Pn1^uYgy;E8rFI3U~#)0$u^HfLFjP;1%!+cm-}j z1;Ut+ckd+RuDcOD{{KJ!_y6w?5ONu0U_aOn{<)u!ufav|Hkbnk!3=mDYzCXaUt0rOK9tDqpzqb(b6Ziyt3_b)GzzTQ{%z-<= zfALl?Zp(0y&@fHuy!$>2A7)W5Xh;*j#BfzCq{~f76^rmeSK6UblSPXx z#-N~UE@lnd;3BT|zwD|gb}nPuOwJNA;CG&xObJa5Z)@6+3T||pMZCdbup5jlnzdhu z)$HIkE$)e97!hpQ+N5D!W(N1yF%`zKwNxVOtE9wI&1S6|=WFB6s`T|TQ%b7xEXB2@lND#-rUQWM?tH9k{3V&u zn8%`QD6>UWm!`=SHIkx)@CyBJ=c=X*^>Kw8R@!NCO3&M8UD6$4|W6 zUwh3?FQ0J>F1S6#=rV(5a2wWBX8k41&`3%Za}gR8ysf!q#KLF?F`~Gs;z`rM*K$Dj zNsPdAMcYj&7{%C_Epgr9y`8XY@sQiu~V)SwtZ!T?PsYc@0>C1`CewR`%s0E zsg$QzQ#_%k%XETjqbexzTK*#7@uW-Bz(b87E2EDSCR@y?4iZy7cJ$EmCn^(~PUuM( z&Py(r*Tz{L(Oe|uGoxl*26vAPw*5qkUV>~Qiy;2<;Q~dH*G(`*n;IVBWWLUG zX~TrbLpJfG+wu;CT-olGX(L-`5DAZ}bP;Wf$_CAnv{R)|&hDDobEHZS(OB9diU#Y0 zl(3%Fev>D|mRX$@+M>PhP*?K0&?0RE%ID<5qd|^zA=^$}k40}99Zy{w@3-81K%qgd zju0$V^-kZ&$QWk|YjVlmaDTEb!*)b;4100?Vx4xOSi(`it}O8Fuf1Wa*S9E~TN|j0 zlbWf$IBRV69Ka)6AN}p(0=&7VHXPx4Ep@#RZ3*w7uA$kMkVx6UQL*8zTy~+`J&<96 zSf`CESly{Rs9Q91>v!e8kcmauM;W`JT-TPul*bj6%GzQTcM&|UwFl-4xuDjO>xbRr z)5ce*);v>%N+k`2os)mZ9rRE8pe19Zit<)lD%0QLReFNAt2pHBSKm^R?(}#e6p0LM zwJBZ?!pt;-m_-r=;{NjJ+88>So#Wn2!&>bWy*zg}c!*YM?=)T8+hDY|?gqwYhOe$g zV@)Yr&{7PH(M>Eg%1nRFqX+fC_$K;%9&fSdS84GsKLG}&4hUr{qVIEf#}udK&fEm@ EKd6>> 1 + 1 == 2 +True +"""} + diff --git a/redditors/views.py b/redditors/views.py new file mode 100644 index 0000000..a84fbe9 --- /dev/null +++ b/redditors/views.py @@ -0,0 +1,242 @@ +from datetime import datetime, timedelta + +from django.contrib.gis.geos import * +from django.contrib.gis.measure import D + +from django import forms +from django.contrib.auth.forms import UserCreationForm +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import render_to_response +from django.utils import simplejson +from django.contrib.auth.models import User +from django.template import RequestContext, Context +from django.contrib.auth.decorators import login_required +from django.core.paginator import Paginator, InvalidPage, EmptyPage + +from drinkkit.redditors.models import LocationCategory, Location, Tip, Checkin + +def home(request): + """ + Main page shows the checkins that have occured over the past day or so. Paginate it + so we don't completely crush things. + """ + queryset = Checkin.objects.filter(timestamp__gte = datetime.now() + timedelta(days=-1)) + paginator = Paginator(queryset, 15) + + try: + page = int(request.GET.get('page', '1')) + except ValueError: + page = 1 + + try: + checkins = paginator.page(page) + except (EmptyPage, InvalidPage): + checkins = paginator.page(paginator.num_pages) + + return render_to_response('locations/home.html', + context_instance = RequestContext(request, {'checkins': checkins}) + ) + +def register(request): + """ + Registration junk for a new user. + """ + if request.POST: + form = UserCreationForm(request.POST) + if form.is_valid(): + # Create User and junk + new_user = form.save() + return HttpResponseRedirect('/') + else: + # You done goofed + return render_to_response('registration/register.html', + context_instance = RequestContext(request, {'form': form}) + ) + else: + form = UserCreationForm() + return render_to_response('registration/register.html', + context_instance = RequestContext(request, {'form': form}) + ) + +def nearby_locations(request): + """ + This is a bit of an interesting method. To deal with older phones, + we employ a somewhat odd trick here. + + We first direct the phone to a page that grabs their coordinates (whether + by geolocation API, or IP location). We do this for phones where we can go ahead and + get the IP location, but they might not support AJAX requests or some shit like that. + + The page then submits automatically with JS after it gets the coordinates, with a button + for the user to hit if the browser is also gonna hang on stupid shit like that. + """ + if request.POST: + if not request.POST['lat'] or not request.POST['long']: + return render_to_response('locations/get_coords_nearby.html', + context_instance = RequestContext(request, { + 'error': "Seems we're unable to get ahold of the GPS/location for where you are. Try again in a few minutes!" + }) + ) + + searchpnts = fromstr('POINT(%s %s)' % (request.POST['lat'], request.POST['long']), srid=4326) + nearby = Location.objects.filter(geometry__distance_lte=(searchpnts, D(mi=2))) + return render_to_response('locations/show_nearby.html', + context_instance = RequestContext(request, {'nearby': nearby}) + ) + else: + return render_to_response('locations/get_coords_nearby.html', + context_instance = RequestContext(request) + ) + +def find_locations(request): + """ + A weak and very basic search. Should be rewritten down the road if this goes anywhere. + """ + if request.POST: + queryset = Location.objects.filter(name__icontains = request.POST['search_query']) + paginator = Paginator(queryset, 10) + performed_search = False + + try: + page = int(request.GET.get('page', '1')) + except ValueError: + page = 1 + + try: + results = paginator.page(page) + performed_search = True + except (EmptyPage, InvalidPage): + results = paginator.page(paginator.num_pages) + + return render_to_response('locations/search.html', + context_instance = RequestContext(request, { + 'search_query': request.POST['search_query'], + 'results': results, + 'performed_search': performed_search # sucks, but whatever for now + }) + ) + else: + return render_to_response('locations/search.html', + context_instance = RequestContext(request) + ) + +@login_required +def checkin_location(request, location_id): + """ + Check a user into a location. + """ + try: + location = Location.objects.get(id = location_id) + except Location.DoesNotExist: + return HttpResponse(status=400) + + if request.POST: + new_checkin = Checkin() + new_checkin.user = request.user + new_checkin.location = location + new_checkin.estimated_time_here = request.POST['estimated_time_here'] + new_checkin.identify_by = request.POST['identify_by'] + new_checkin.save() + return HttpResponseRedirect('/locations/%s/' % location_id) + else: + return render_to_response('locations/checkin.html', + context_instance = RequestContext(request, {'location': location}) + ) + +@login_required +def add_location(request): + """ + Add a new location to be checked into by others. + + Fairly custom logic, kind of ugly, 5:30AM, I don't care right now. None of these form fields are bound, + but considering that only two of them are mandatory, I'm fine with this for a first release. It should be + fixed at some point. ;P + """ + if request.POST: + if request.POST['location_name'] and request.POST['lat'] and request.POST['long']: + new_location = Location() + new_location.name = request.POST['location_name'] + new_location.geometry = 'POINT(%s %s)' %(request.POST['lat'], request.POST['long']) + + # If they've supplied a street address, sweet, use it. + if request.POST['street_address']: + new_location.street_address = request.POST['street_address'] + + # If they set a location, let's record it... (5AM code) + if request.POST['location_type']: + try: + category = LocationCategory.objects.get(id = request.POST['location_type']) + new_location.category = category + except LocationCategory.DoesNotExist: + pass + + new_location.save() + return HttpResponseRedirect('/locations/%s/' % str(new_location.id)) + else: + if not request.POST['lat'] or not request.POST['lat']: + errmsg = "We weren't able to get coordinates for where you are right now. Does your phone or device have GPS?" + if not request.POST['location_name']: + errmsg = "You didn't even bother to enter a name for this location. Wtf?" + return render_to_response('locations/add.html', + context_instance = RequestContext(request, {'error': errmsg, 'category_choices': LocationCategory.objects.all()}) + ) + else: + return render_to_response('locations/add.html', + context_instance = RequestContext(request, {'category_choices': LocationCategory.objects.all()}) + ) + +def view_location(request, location_id): + """ + Serve up information about a location. + + Note: this could probably be more efficient. + """ + try: + location = Location.objects.get(id = location_id) + + checkins = location.checkin_set + recent_checkins = checkins.all().reverse()[:5] + + allow_checkin = True + + # Only one checkin in a day long period. + if request.user.is_authenticated(): + if checkins.filter(user = request.user).filter(timestamp__gte = datetime.now() + timedelta(days=-1)): + allow_checkin = False + + return render_to_response('locations/view.html', + context_instance = RequestContext(request, { + 'location': location, + 'recent_checkins': recent_checkins, + 'allow_checkin': allow_checkin + }) + ) + except Location.DoesNotExist: + return HttpResponse(status=404) + +@login_required +def add_tip(request, location_id): + """ + Add a new tip about a location. + """ + if request.POST: + try: + location = Location.objects.get(id = location_id) + + new_tip = Tip() + new_tip.tip = request.POST['tip_body'] + new_tip.user = request.user + new_tip.location = location + new_tip.save() + + return HttpResponseRedirect('/locations/%s/' % location.id) + except Location.DoesNotExist: + return HttpResponse(status=404) + else: + return HttpResponse(status=404) + +def find_redditors(request): + """ + Handles locating all Redditors in a given area who recently checked in. + """ + pass diff --git a/settings.py b/settings.py new file mode 100644 index 0000000..d5e3139 --- /dev/null +++ b/settings.py @@ -0,0 +1,78 @@ +import os.path +# Django settings for drinkkit project. + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + ('You', 'you@you.com'), +) + +FIXTURE_DIRS = ( + 'fixtures', +) + +if DEBUG: + CACHE_BACKEND = 'dummy:///' +else: + CACHE_BACKEND = 'memcached://127.0.0.1:11211/' + +AUTH_PROFILE_MODULE = 'redditors.Redditor' +LOGIN_REDIRECT_URL = '/' +LOGIN_URL = '/auth/' +LOGOUT_URL = '/' + +MANAGERS = ADMINS + +DATABASES = { + 'default': { + 'ENGINE': 'django.contrib.gis.db.backends.postgis', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. + 'NAME': '', # Or path to database file if using sqlite3. + 'USER': '', # Not used with sqlite3. + 'PASSWORD': '', # Not used with sqlite3. + 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. + 'PORT': '', # Set to empty string for default. Not used with sqlite3. + } +} + +TIME_ZONE = 'America/New_York' +LANGUAGE_CODE = 'en-us' +SITE_ID = 1 +USE_I18N = True +USE_L10N = True +MEDIA_ROOT = '' +MEDIA_URL = '' +ADMIN_MEDIA_PREFIX = '/media/' +SECRET_KEY = '-2_vd&w^n^3l2+jg3bxrqv8$7w4%lolnok(hf_dl5-()a=3xl5' + +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.cache.UpdateCacheMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.cache.FetchFromCacheMiddleware', +) + +ROOT_URLCONF = 'drinkkit.urls' + +TEMPLATE_DIRS = ( + os.path.join(os.path.dirname(__file__), 'templates'), +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.messages', + 'django.contrib.gis', + 'django.contrib.admin', + 'redditors', +) diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..5f36405 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,291 @@ + + + + Drinkkit - Find other drinking Redditors! {% block title %}{% endblock %} + + + + + {% block extra_head %}{% endblock %} + + + + + +
+ {% if not user.is_authenticated %} + Login + Register + {% else %} + About + Logout + {% endif %} + drinkkit +
+
+ + Home + Nearby + Search + {% if user.is_authenticated %} + Add Location + {% endif %} +
+ +
+

What the hell is drinkkit?

+

+ On October 30th, 2010, two figures are planning to hold some rallies in Washington DC. Much of this was spurred on by Reddit.com. + Washington DC has its own awesome sauce group of Redditors, and we happen to know all the appropriately awesome bars. This is an app + for smartphones that lets Reddit users "check in" to bars and places in DC during the rally, much like Foursquare or Gowalla. +

+ +

+ The difference is that this is limited to just Redditors. If you check out venues here, you're guaranteed to find a + Redditor hanging out there if you drop by. Redditors can also leave tips on venues for other Redditors - hold a scavenger hunt, + awkward conversations and marriage proposals, whatever. To get started, just log in or register! +

+ +

Disclaimer

+

+ This is meant to be for fun, but you should always exercise caution when meeting people from the internet. In case you haven't noticed, + they're sometimes... odd. By using this app, you waive all rights to come back at me if you lack the common sense to be aware of your + surroundings and not take candy from strangers. +

+ +

+ This app is in no way affiliated with Reddit.com, Conde Nast, Wired, or any of the DC locations listed on here. We just like beer. +

+
+ +
+ {% block content %}{% endblock %} +
+ + diff --git a/templates/locations/add.html b/templates/locations/add.html new file mode 100644 index 0000000..7f0c95f --- /dev/null +++ b/templates/locations/add.html @@ -0,0 +1,95 @@ +{% extends "base.html" %} + +{% block extra_head %} + + + + + + +{% endblock %} + + +{% block content %} + {% if error %} +
+

{{ error }}

+
+ {% endif %} + +
+ {% csrf_token %} + +

What's the name?

+

+ + +

+ +

Know the street address?

+

+ + +

+ +

What type of location is this?

+ +

+ + +

+ + + + +
+ +
+
+ +{% endblock %} diff --git a/templates/locations/checkin.html b/templates/locations/checkin.html new file mode 100644 index 0000000..f1c532e --- /dev/null +++ b/templates/locations/checkin.html @@ -0,0 +1,32 @@ +{% extends "base.html" %} + +{% block extra_head %} +{% endblock %} + +{% block content %} +

Checkin To: {{ location.name }}

+

+ The following two questions are optional, but helpful + if you want to be found by other Redditors. If you don't want to answer them, just hit the checkin button below. +

+ +
+ {% csrf_token %} + +

How long do you think you'll be here?

+

+ + +

+ +

How can other Redditors identify you?

+

+ + +

+ +
+ +
+
+{% endblock %} diff --git a/templates/locations/get_coords_nearby.html b/templates/locations/get_coords_nearby.html new file mode 100644 index 0000000..aa74fc6 --- /dev/null +++ b/templates/locations/get_coords_nearby.html @@ -0,0 +1,100 @@ +{% extends "base.html" %} + +{% block extra_head %} + + + + + + +{% endblock %} + + +{% block content %} + +
+ {% if error %} +
+

{{ error }}

+
+ {% endif %} + +
+ {% csrf_token %} + +

Getting your current position...

+

+ This should automagically redirect you to nearby results. +

+ +

+ If it doesn't, please wait until the "loading..." text below disappears, + and then click the button below to force your browser to get results (older phones may need to do this). +

+ + + + +
+ +
+ +
+ Loading... +
+
+
+{% endblock %} diff --git a/templates/locations/home.html b/templates/locations/home.html new file mode 100644 index 0000000..1b0470f --- /dev/null +++ b/templates/locations/home.html @@ -0,0 +1,45 @@ +{% extends "base.html" %} + +{% block extra_head %} +{% endblock %} + + +{% block content %} +

Where all the DC Redditors at?

+

+ Check out where other DC Redditors are drinking! If you'd like to join in, register or log in using the buttons + at the top right of the screen. +

+ +

+ By using this, you should be fully aware that other Redditors can find out where you're at. Consider this a little "social experiment". + This was built out of boredom by Ryan McGrath; if you have questions or comments, feel free + to message him on Reddit. +

+ +

Redditors around DC

+ + + + +{% endblock %} diff --git a/templates/locations/search.html b/templates/locations/search.html new file mode 100644 index 0000000..8e692f0 --- /dev/null +++ b/templates/locations/search.html @@ -0,0 +1,66 @@ +{% extends "base.html" %} + +{% block extra_head %} + +{% endblock %} + + +{% block content %} +
+ {% csrf_token %} + +

Find Locations in DC

+

+ + +

+ +
+ +
+
+ + {% if performed_search %} + {% if results.object_list %} +

Results for {{ search_query }}

+ + + + + {% else %} +

No Results for {{ search_query }}

+

+ No locations in the Drinkkit database match what you're looking for. If where you are isn't listed, + you should feel free to add it so other Redditors can find it! +

+ {% endif %} + {% endif %} + +{% endblock %} diff --git a/templates/locations/show_nearby.html b/templates/locations/show_nearby.html new file mode 100644 index 0000000..cacfe65 --- /dev/null +++ b/templates/locations/show_nearby.html @@ -0,0 +1,44 @@ +{% extends "base.html" %} + +{% block extra_head %} + +{% endblock %} + + +{% block content %} + {% if nearby %} +

Nearby you right now

+ + {% else %} +

All's quiet on the Eastern Front :(

+

+ We couldn't find anything going on near you. The GPS in your device might not be accurate enough for this feature, or we + may be experiencing some difficulty. If you think it's the former (you know your device better than I do (that's what she said)), + please feel free to retry this feature in a few minutes. +

+ +

+ The third option, of course, is that it's very possible nobody's out and about. They are Redditors, after all. ;) +

+ {% endif %} + +{% endblock %} diff --git a/templates/locations/view.html b/templates/locations/view.html new file mode 100644 index 0000000..dfcffa6 --- /dev/null +++ b/templates/locations/view.html @@ -0,0 +1,197 @@ +{% extends "base.html" %} + +{% block extra_head %} + + + + + +{% endblock %} + +{% block content %} +

{{ location.name }}

+ +
+
    +
  • Category: {{ location.category|default:"Not Specified :(" }}
  • +
  • Address: {{ location.street_address|default:"Not Specified :(" }}
  • +
+ + {% if user.is_authenticated %} + {% if allow_checkin %} + Check In Here + {% else %} +
Already Checked In
+ {% endif %} + {% endif %} +
+ +

Map of the area

+
+ {% if location.street_address %} + + {% else %} + + {% endif %} +
+ + + +

Recently checked in here

+ {% if recent_checkins %} +
    + {% for checkin in recent_checkins %} +
  • + {{ checkin.user.username }} {{ checkin.timestamp|timesince }} ago + Can be identified by: {{ checkin.identify_by|default:"Doesn't want to be found. :(" }}
    + Estimated time spent here: {{ checkin.estimated_time_here|default:"They're flying by the seat of their vintage pants (no idea)."}} +
  • + {% endfor %} +
+ {% else %} +

No checkins yet. You could be the first!

+ {% endif %} + + {% if user.is_authenticated %} +

Leave a Tip or Todo

+
+ {% csrf_token %} + + + +
+ {% endif %} + +

Tips & Todos from Redditors

+ {% if location.tip_set.all %} +
    + {% for tip in location.tip_set.all %} +
  • + {{ tip.user.username }} {{ tip.timestamp|timesince }} ago + {{ tip.tip }} +
  • + {% endfor %} +
+ {% else %} +

No tips yet. Be the first and add one!

+ {% endif %} +{% endblock %} diff --git a/templates/registration/login.html b/templates/registration/login.html new file mode 100644 index 0000000..25c9b84 --- /dev/null +++ b/templates/registration/login.html @@ -0,0 +1,28 @@ +{% extends "base.html" %} + +{% block content %} + +{% if form.errors %} +

Your username and password didn't match. Please try again.

+{% endif %} + +
+ {% csrf_token %} + +

Your Username

+

+ {{ form.username }} +

+ +

Your Password

+

+ {{ form.password }} +

+ +
+ + +
+
+ +{% endblock %} diff --git a/templates/registration/register.html b/templates/registration/register.html new file mode 100644 index 0000000..a14b513 --- /dev/null +++ b/templates/registration/register.html @@ -0,0 +1,14 @@ +{% extends "base.html" %} + +{% block content %} +

Create an account

+ +
+ {% csrf_token %} + {{ form.as_p }} + +
+ +
+
+{% endblock %} diff --git a/urls.py b/urls.py new file mode 100644 index 0000000..947a397 --- /dev/null +++ b/urls.py @@ -0,0 +1,27 @@ +from django.conf.urls.defaults import * +from django.contrib import admin + +# Set up the admin shit +admin.autodiscover() + +urlpatterns = patterns('', + (r'^admin/', include(admin.site.urls)), + + # Viewing and adding tips/locations + (r'^locations/add/$', 'drinkkit.redditors.views.add_location'), + (r'^locations/search/$', 'drinkkit.redditors.views.find_locations'), + (r'^locations/nearby/$', 'drinkkit.redditors.views.nearby_locations'), + + (r'^locations/(?P[a-zA-Z0-9_.-]+)/add_tip/$', 'drinkkit.redditors.views.add_tip'), + (r'^locations/(?P[a-zA-Z0-9_.-]+)/checkin/$', 'drinkkit.redditors.views.checkin_location'), + (r'^locations/(?P[a-zA-Z0-9_.-]+)/$', 'drinkkit.redditors.views.view_location'), + + # Registration + (r'^register/$', 'drinkkit.redditors.views.register'), + + # User forms - password, logout, login, etc. + (r'^password_reset/$', 'django.contrib.auth.views.password_reset'), + (r'^unauth/$', 'django.contrib.auth.views.logout_then_login'), + (r'^auth/$', 'django.contrib.auth.views.login'), + (r'^/*', 'drinkkit.redditors.views.home'), +)