ui using django templates

This commit is contained in:
Zane Adickes 2016-01-06 17:10:05 -05:00
parent 90a0066f33
commit 66370dad44
24 changed files with 6992 additions and 525 deletions

View file

@ -1,6 +1,89 @@
@font-face {
font-family: 'Lato';
src: url('/static/pokemon/fonts/lato-regular/lato-regular.eot');
src: url('/static/pokemon/fonts/lato-regular/lato-regular.eot?#iefix') format('embedded-opentype'),
url('/static/pokemon/fonts/lato-regular/lato-regular.woff2') format('woff2'),
url('/static/pokemon/fonts/lato-regular/lato-regular.woff') format('woff'),
url('/static/pokemon/fonts/lato-regular/lato-regular.ttf') format('truetype'),
url('/static/pokemon/fonts/lato-regular/lato-regular.svg#svgFontName') format('svg');
}
@font-face {
font-family: 'Lato';
font-weight: 300;
src: url('/static/pokemon/fonts/lato-regular/lato-light.eot');
src: url('/static/pokemon/fonts/lato-regular/lato-light.eot?#iefix') format('embedded-opentype'),
url('/static/pokemon/fonts/lato-regular/lato-light.woff2') format('woff2'),
url('/static/pokemon/fonts/lato-regular/lato-light.woff') format('woff'),
url('/static/pokemon/fonts/lato-regular/lato-light.ttf') format('truetype'),
url('/static/pokemon/fonts/lato-regular/lato-light.svg#svgFontName') format('svg');
}
@font-face {
font-family: 'Lato';
font-weight: 900;
src: url('/static/pokemon/fonts/lato-regular/lato-black.eot');
src: url('/static/pokemon/fonts/lato-regular/lato-black.eot?#iefix') format('embedded-opentype'),
url('/static/pokemon/fonts/lato-regular/lato-black.woff2') format('woff2'),
url('/static/pokemon/fonts/lato-regular/lato-black.woff') format('woff'),
url('/static/pokemon/fonts/lato-regular/lato-black.ttf') format('truetype'),
url('/static/pokemon/fonts/lato-regular/lato-black.svg#svgFontName') format('svg');
}
html { padding-top: 50px; }
body, h1, h2, h3, h4, h5, h6, p {
font-family: 'Lato', sans-serif;
color: #263238;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
}
h1, h2 { font-weight: 900; }
h2 { margin-bottom: 10px; }
a { color: #1b95e0; }
p, pre, table {
margin-bottom: 30px;
}
pre {
position: relative;
}
hr {
border-width: 1px;
border-color: #CCC;
margin: 8px 0;
/*height: 1px;*/
}
.center-block {
float: none;
margin: 0 auto;
}
.header {
text-align: center;
padding-top:120px;
height: 200px;
background-color: #263238;
}
.header,
.header h1,
.header h2,
.header h3,
.header h4,
.header h5 {
color: #FFF;
}
.footer {
@ -8,13 +91,62 @@
}
.navbar {
background: #c0392b;
background: #EF5350;
border-width: 0px;
-webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.2);
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.2);
}
.navbar-header {
width: 300px;
}
.navbar-count {
color: #FFF;
width: 100px;
}
.navbar-collapse {
padding: 0;
}
.navbar-inverse .navbar-nav li a {
color: #FFF;
}
.navbar-inverse .navbar-nav .active a,
.navbar-inverse .navbar-nav .active a:hover,
.navbar-inverse .navbar-nav .active a:focus {
background-color: #C62828!important;
}
.navbar-brand {
width: 100px;
}
.center {
text-align: center;
}
.input-group-addon {
background-color: #F5F5F5;
}
.input-group-addon,
.btn,
.well,
pre {
border-radius: 0px;
}
.well p:last-child{
margin-bottom: 0px;
}
.pad_top {
padding-top: 15px;
}
@ -34,23 +166,179 @@
float: left!important;
}
.navbar-brand {
width:100px;
.cta {
background-color: #F5F5F5;
text-align: center;
padding: 30px 0 30px;
font-size: 21px;
font-weight: 300;
margin-bottom: 30px;
}
.navbar-inverse .navbar-nav > .active > a,
.navbar-inverse .navbar-nav > .active > a:hover,
.navbar-inverse .navbar-nav > .active > a:focus {
color: #ffffff;
background: #c0392b!important;
.cta p:last-child {
margin-bottom: 0;
}
hr {
border-top: 1px solid #95a5a6;
border-bottom: 1px solid #2c3e50;
/*
* HOME
*/
#home .header {
padding-top: 38px;
/*margin-bottom: 30px;*/
}
hr .light {
border-top: 1px solid #ecf0f1;
border-bottom: 1px solid #bdc3c7;
#home .header h1 {
position: relative;
display: inline-block;
}
#home .header h1:before {
content: "V2";
position: absolute;
font-size: 14px;
top: 0;
right: -22px;
}
#home .header h1:after {
content: "BETA";
position: absolute;
font-size: 14px;
color: #EF5350;
top: 0;
right: -63px;
}
#home .header h2 {
font-weight: 300;
margin-bottom: 20px;
}
#home .header h4 {
font-weight: 300;
}
#home .header h4 .count {
font-weight: 900;
/*color: #EF5350;*/
}
#home .btn-primary {
background-color: #1b95e0;
color: #FFF
}
#home pre {
margin-bottom: 30px;
}
/*
* ABOUT
*/
#about .header {
padding-top: 80px;
}
/*
* DOCS
*/
#docs h1:first-of-type, #docs table:first-of-type {
display: none;
}
#docs table {
width: 100%;
}
#docs table th:first-child,
#docs table tr:first-child {
width: 140px;
}
#docs table th:last-child,
#docs table tr:last-child {
width: 180px;
}
#docs table th, #docs table td {
border: 1px solid #CCC;
padding: 8px;
}
#docs h2, #docs h4, #docs #resourcename {
margin-top: -50px;
padding-top: 50px;
}
#docs h3 {
font-weight: 300;
}
#docs h6 {
display: none;
}
#docs ul {
list-style: none;
margin: 0;
padding: 0;
}
#docs ul.version-select li {
display: inline-block;
float: left;
padding: 13px;
background-color: #EF5350;
width: 50%;
text-align: center;
margin-bottom: 15px;
}
#docs ul.version-select li.active {
background-color: #C62828;
}
#docs ul.version-select li a {
color: #FFF;
}
#docs pre:before {
font-size: 12px;
font-style: italic;
font-weight: 300;
display: inline-block;
content: "example response";
position: absolute;
top: 5px;
right: 10px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -84,7 +84,7 @@ WSGI_APPLICATION = 'config.wsgi.application'
TEMPLATE_DIRS = (
PROJECT_ROOT.child('templates'),
PROJECT_ROOT + 'pokemon/templates'
# PROJECT_ROOT + 'pokemon/templates'
)
DATABASES = {
@ -129,7 +129,8 @@ INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.humanize',
'corsheaders',
'rest_framework',
'rest_framework',
'markdown_deux'
) + CUSTOM_APPS
@ -157,3 +158,15 @@ REST_FRAMEWORK = {
'PAGE_SIZE': 20,
}
MARKDOWN_DEUX_STYLES = {
"default": {
"extras": {
"code-friendly": None,
"tables": None,
"fenced-code-blocks": None,
"header-ids": None
},
"safe_mode": False,
},
}

View file

@ -5,11 +5,12 @@ from django.conf import settings
from django.conf.urls import url, include
from django.conf.urls.static import static
from django.contrib import admin
from django.views.generic import TemplateView
from pokemon import urls as pokemon_urls
from pokemon_v2 import urls as pokemon_v2_urls
# need to make sure v2 urls resolve last so angular routes have control
v2 = [ url(r'^', include(pokemon_v2_urls)) ]
# v2 = [ url(r'^', include(pokemon_v2_urls)) ]
urlpatterns = [
@ -23,6 +24,22 @@ urlpatterns = [
'django.views.static.serve',
{'document_root': settings.STATIC_ROOT}),
url(r'^', include(pokemon_urls)),
url(r'^$', 'config.views.home'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + v2
url(r'^docs/$',
TemplateView.as_view(template_name='docs.html'),
name="documentation"
),
url(r'^docs2/$',
TemplateView.as_view(template_name='docs2.html'),
name="documentation_v2"
),
url(r'^about/$', 'config.views.about'),
url(r'^', include(pokemon_urls)),
url(r'^', include(pokemon_v2_urls)),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # + v2

223
config/views.py Executable file
View file

@ -0,0 +1,223 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.auth.decorators import login_required
# from pokemon.models import (
# Pokemon, Sprite, Move, Description, Game,
# EggGroup, Type, Ability, MovePokemon
# )
from pokemon_v2.models import *
from hits.models import ResourceView
def _total_site_data():
"""
Compute the total count of objects on the site
Using count() is drastically cheaper than len(objects.all())
"""
# v1
# data = dict(
# pokemon=Pokemon.objects.count(),
# sprites=Sprite.objects.count(),
# moves=Move.objects.count(),
# descriptions=Description.objects.count(),
# games=Game.objects.count(),
# egg_groups=EggGroup.objects.count(),
# types=Type.objects.count(),
# abilities=Ability.objects.count(),
# move_pokes=MovePokemon.objects.count()
# )
# v2
data = dict (
abilities=Ability.objects.count(),
abilitie_names=AbilityName.objects.count(),
abilitie_effect_texts=AbilityEffectText.objects.count(),
abilities_flavor_texts=AbilityFlavorText.objects.count(),
abilities_changes=AbilityChange.objects.count(),
abilities_change_effect_texts=AbilityChangeEffectText.objects.count(),
berries=Berry.objects.count(),
berry_flavors=BerryFlavor.objects.count(),
berry_firmnesses=BerryFirmness.objects.count(),
berry_firmness_names=BerryFirmnessName.objects.count(),
characteristic=Characteristic.objects.count(),
characteristic_descriptions=CharacteristicDescription.objects.count(),
contest_combos=ContestCombo.objects.count(),
contest_types=ContestType.objects.count(),
contest_type_names=ContestTypeName.objects.count(),
contest_effects=ContestEffect.objects.count(),
contest_effect_texts=ContestEffectEffectText.objects.count(),
contest_effect_flavor_texts=ContestEffectFlavorText.objects.count(),
egg_groups=EggGroup.objects.count(),
egg_group_names=EggGroupName.objects.count(),
encounter_methods=EncounterMethod.objects.count(),
encounter_method_names=EncounterMethodName.objects.count(),
encounter_conditions=EncounterCondition.objects.count(),
encounter_condition_names=EncounterConditionName.objects.count(),
encounter_condition_values=EncounterConditionValue.objects.count(),
encounter_condition_value_names=EncounterConditionValueName.objects.count(),
encounter_condition_value_maps=EncounterConditionValueMap.objects.count(),
encounter_slots=EncounterSlot.objects.count(),
encounters=Encounter.objects.count(),
evolution_chain=EvolutionChain.objects.count(),
evolution_trigger=EvolutionTrigger.objects.count(),
evolution_trigger_names=EvolutionTriggerName.objects.count(),
experiences=Experience.objects.count(),
generations=Generation.objects.count(),
generation_names=GenerationName.objects.count(),
gender=Gender.objects.count(),
growth_rate=GrowthRate.objects.count(),
growth_rate_descriptions=GrowthRateDescription.objects.count(),
items=Item.objects.count(),
item_names=ItemName.objects.count(),
item_effect_texts=ItemEffectText.objects.count(),
item_categories=ItemCategory.objects.count(),
item_category_names=ItemCategoryName.objects.count(),
item_attributes=ItemAttribute.objects.count(),
item_attribute_maps=ItemAttributeMap.objects.count(),
item_attribute_descriptions=ItemAttributeDescription.objects.count(),
item_flavor_texts=ItemFlavorText.objects.count(),
item_fling_effects=ItemFlingEffect.objects.count(),
item_fling_effect_effect_texts=ItemFlingEffectEffectText.objects.count(),
item_pockets=ItemPocket.objects.count(),
item_pocket_names=ItemPocketName.objects.count(),
item_game_indexes=ItemGameIndex.objects.count(),
languages=Language.objects.count(),
language_names=LanguageName.objects.count(),
locations=Location.objects.count(),
location_game_indexes=LocationGameIndex.objects.count(),
location_names=LocationName.objects.count(),
location_areas=LocationArea.objects.count(),
location_area_names=LocationAreaName.objects.count(),
location_area_encounter_rates=LocationAreaEncounterRate.objects.count(),
machines=Machine.objects.count(),
moves=Move.objects.count(),
move_names=MoveName.objects.count(),
move_changes=MoveChange.objects.count(),
move_flavor_text=MoveFlavorText.objects.count(),
move_effects=MoveEffect.objects.count(),
move_effect_changes=MoveEffectChange.objects.count(),
move_effect_change_effect_texts=MoveEffectChangeEffectText.objects.count(),
move_effect_effect_texts=MoveEffectEffectText.objects.count(),
move_attributes=MoveAttribute.objects.count(),
move_attribute_names=MoveAttributeName.objects.count(),
move_attribute_maps=MoveAttributeMap.objects.count(),
move_attribute_descriptions=MoveAttributeDescription.objects.count(),
move_metas=MoveMeta.objects.count(),
move_ailments=MoveMetaAilment.objects.count(),
move_ailment_names=MoveMetaAilmentName.objects.count(),
move_battle_styles=MoveBattleStyle.objects.count(),
move_battle_style_names=MoveBattleStyleName.objects.count(),
move_categories=MoveMetaCategory.objects.count(),
move_damage_classes=MoveDamageClass.objects.count(),
move_damage_class_descriptions=MoveDamageClassDescription.objects.count(),
move_learn_methods=MoveLearnMethod.objects.count(),
move_learn_method_names=MoveLearnMethodName.objects.count(),
move_targets=MoveTarget.objects.count(),
move_target_descriptions=MoveTargetDescription.objects.count(),
move_state_changes=MoveMetaStatChange.objects.count(),
natures=Nature.objects.count(),
pal_park_areas=PalParkArea.objects.count(),
pokedexes=Pokedex.objects.count(),
pokemon=Pokemon.objects.count(),
pokemon_colors=PokemonColor.objects.count(),
pokemon_forms=PokemonForm.objects.count(),
pokemon_habitats=PokemonHabitat.objects.count(),
pokemon_shapes=PokemonShape.objects.count(),
pokemon_species=PokemonSpecies.objects.count(),
pokeathlon_stats=PokeathlonStat.objects.count(),
region=Region.objects.count(),
stat=Stat.objects.count(),
super_contest_effects=SuperContestEffect.objects.count(),
types=Type.objects.count(),
versions=Version.objects.count(),
version_groups=VersionGroup.objects.count()
)
t = 0
for i in data.iteritems():
t += i[1]
data['total_items'] = t
return data
@login_required
def moderate(request):
return render_to_response(
'pages/moderate.html',
{}, context_instance=RequestContext(request))
def about(request):
site_data = _total_site_data()
total_views = ResourceView.objects.total_count()
# average_day = int(round(total_views / ResourceView.objects.count()))
average_day = 0;
return render_to_response(
'about.html',
{
'total': total_views,
'average_day': average_day,
'site_data': site_data,
},
context_instance=RequestContext(request)
)
def home(request):
total_views = ResourceView.objects.total_count()
if total_views > 100:
total_views = int(round(total_views, -2))
return render_to_response(
'home.html',
{
'total_views': total_views,
},
context_instance=RequestContext(request)
)
def twilio(request):
return render_to_response(
'pages/twilio.html',
{}, context_instance=RequestContext(request))

View file

@ -1,168 +0,0 @@
{% extends "base-v1.html" %}
{% load humanize %}
{% block mainbody %}
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-brand">
<a href="https://twitter.com/share" class="twitter-share-button" data-url="http://pokeapi.co" data-text="Pokéapi - the Pokémon RESTful API " data-via="phalt_" data-related="phalt_">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
</div>
<div class="collapse navbar-collapse navbar-right">
<ul class="nav navbar-nav">
<li><a href="/v1/">Home</a></li>
<li class="active"><a href="#">About</a></li>
<li><a href="/v1/docs/">Documentation</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-2">
</div>
<div class="header col-md-8">
<h1>Pokéapi - The Pokémon RESTful API</h1>
</div>
<div class="col-md-2">
</div>
</div><!-- /.header row -->
<div class="row pad_top">
<div class="col-md-2">
</div>
<div class="col-md-8">
<p class="lead">
What is this?
</p>
<div class="well">
<p>
This website provides a RESTful API interface to <b>{{ site_data.total_items|intcomma }}</b> objects
related to <a href="https://en.wikipedia.org/wiki/Pokemon">Pokémon</a>. We specifically cover the video game franchise, though we'd like to cover the card game too. Using this website you can consume information on Pokémon, their moves, abilities, types, egg groups and much much more.
</p>
</div>
<p class="lead">
What exactly is an API?
</p>
<div class="well">
<p>
This is probably worth clearing up very quickly for those who don't know.<br />
An API (Application Programming Interface) is a set of interfaces (in this case, url links)
that are publicly available, that allow developers to interact with an application.<br />
In this instance; the application is a database of <b>{{ site_data.total_items|intcomma }}</b> pokemon-related objects.
</p>
</div>
<p class="lead">
Isn't there 101 other Pokémon websites already?
</p>
<div class="well">
<p>
Yes and that's exactly the problem!
</p>
<p>
101 instances of the same website means 101 instances of the <b>same data</b>.
</p>
<p>
We aim to provide a <b>single database</b> that any number of other websites
can consume and use.
</p>
<p>
Often, and especially when new Pokémon games or updates are released, the 101+ websites
take <b>weeks</b> to update as people have to enter the same information in all those different places.
</p>
<p>This solves that problem.
</p>
<p>
If all those sites consumed their data from here, they would have the exact same information that is updated at exactly the same time, with no errors between each website.
</p>
<p>
The overall benefit is a better collaboration and consistency across all the different Pokémon
websites and applications. It's good for all!
</p>
</div>
<p class="lead">
How much information is stored here?
</p>
<div class="well">
<p>
I'm glad you asked because we've got an impressive amount of data!
</p>
<p>
We currently have <b>{{ site_data.total_items|intcomma }}</b> individual items in our database:
</p>
<ul>
<li>{{ site_data.pokemon }} Pokémon</li>
<li>{{ site_data.moves }} Moves</li>
<li>{{site_data.move_pokes|intcomma }} Pokémon<->move links</li>
<li>{{ site_data.abilities }} Abilities</li>
<li>{{ site_data.types }} Types</li>
<li>{{ site_data.egg_groups }} Egg groups</li>
<li>{{ site_data.descriptions }} Descriptions</li>
<li>{{ site_data.sprites }} Sprites</li>
<li>{{ site_data.games }} Games</li>
</ul>
<p class="lead">The server has processed <b>{{ total|intcomma }}</b> api calls at an average of <b>{{ average_day|intcomma }}</b> calls per day.</p>
</div>
<p class="lead">
The API is missing stuff!
</p>
<div class="well">
<p>
I know! Feel free to contribute to open issues on <a href="https://github.com/phalt/pokeapi/">GitHub</a>.
</p>
</div>
<p class="lead">
So who built this?
</p>
<div class="well">
<p>
I'm Paul Hallett, a software engineer obsessed with creating things
that benefit people. This was a weekend project of mine that has since grown
beyond a single weekend's worth of work.
<br />
Find out more about me <a href="http://phalt.co">here</a>
</p>
<p>
I gathered the information on this site from various resources:
</p>
<ul>
<li><a href="https://github.com/veekun">Veekun</a> had a huge bunch of CSV's that
I used to build most of the data on the site.</li>
<li><a href="http://bulbapedia.bulbagarden.net/wiki/Main_Page">Bulbapedia</a> has a tonne of extra information that proved useful when designing the data model.</li>
</ul>
<p>
I'd also like to thank:
</p>
<ul>
<li>Laven Pillay, who scraped together most of the sprites used on the site.</li>
</ul>
</div>
<p class="lead">
What's the technology stack?
</p>
<div class="well">
<p>
The website framework is <a href="http://djangoproject.com">Django</a>,
a super awesome framework built around <a hre="http://python.org">Python</a>.<br />
We use a <a href="www.postgresql.org">Postgres</a> database to store all our data.<br />
We use <a href="http://django-tastypie.readthedocs.org/en/latest/">Django-tastypie</a> to expose our data through a RESTful API.<br />
We're hosted on <a href="https://www.digitalocean.com/?refcode=eab2fea41bc6
">DigitalOcean</a> servers, click the link to help keep the site running!.
</p>
</div>
</div>
<div class="col-md-2">
</div>
</div><!--row-->
</div><!-- /.container -->
{% endblock %}

View file

@ -1,225 +0,0 @@
{% extends "base-v1.html" %}
{% load humanize %}
{% block mainbody %}
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<div class="navbar-brand">
<a href="https://twitter.com/share" class="twitter-share-button" data-url="http://pokeapi.co" data-text="Pokéapi - the Pokémon RESTful API " data-via="phalt_" data-related="phalt_">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
</div>
</div>
<div class="collapse navbar-collapse navbar-right">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="/v1/about/">About</a></li>
<li><a href="/v1/docs/">Documentation</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
<div class="container">
{% if update %}
<div class="row" style="padding-top:80px;text-align:center;">
<div class="col-md-2">
</div>
<div class="col-md-8">
<div class="alert alert-success">{{update.content|safe}}</div>
</div>
<div class="col-md-2">
</div>
</div><!-- /.header row -->
{% endif %}
<div class="row">
<div class="col-md-2">
</div>
<div class="{% if not update %}header{% endif %} col-md-8">
<h1>Pokéapi - The Pokémon RESTful API</h1>
<p class="lead center">Finally; all the Pokémon data you'll ever need, in one place,<br /> and easily accessible through a modern RESTful API.</p>
<p class="center">Over <b>{{ total_views|intcomma }}</b> API calls received!</p>
</div>
<div class="col-md-2">
</div>
</div><!-- /.header row -->
<div class="row">
<div class="col-md-2">
</div>
<div class="col-md-8">
<div class="center">
<h1>
Try it now!
</h1>
<div class="input-group pad_top">
<span class="input-group-addon">http://pokeapi.co/api/v1/</span>
<input id="interactive" type="text" class="form-control" placeholder="pokemon/1/">
<span class="input-group-btn"><button onClick="interactive_call();return false;" class="btn btn-primary">submit</button></span>
</div>
</div>
<small>Need a hint? try <a href="#" onClick="update('pokemon/1/');return false;"><i>pokemon/1/</i></a> or <a href="#" onClick="update('type/3/');return false;"><i>type/3/</i></a> or <a href="#" onClick="update('ability/4/');return false;"><i>ability/4/</i></a></small>
<p class="lead pad_top">Resource for <span id="interactive_name">Bulbasaur</span></p>
<div class="well">
<pre id="interactive_output" class="pre-scrollable">
{
"abilities": [
{
"name": "overgrow",
"resource_uri": "/api/v1/ability/1/"
},
{
"name": "chlorophyll",
"resource_uri": "/api/v1/ability/2/"
}
],
"attack": 49,
"catch_rate": 45,
"created": "2013-11-02T12:08:25.745455",
"defense": 49,
"egg_cycles": 21,
"egg_groups": [
{
"name": "Monster",
"resource_uri": "/api/v1/egg/1/"
},
{
"name": "Grass",
"resource_uri": "/api/v1/egg/8/"
}
],
"ev_yield": "1 Sp Atk",
"evolutions": {
"level": 16,
"method": "level up",
"resource_uri": "/api/v1/pokemon/2/",
"to": "Ivysaur"
},
"exp": 64,
"growth_rate": "ms",
"happiness": 70,
"height": "2'4",
"hp": 45,
"male_female_ratio": "87.5/12.5",
"modified": "2013-11-02T13:28:04.914889",
"moves": [
{
"learn_type": "other",
"name": "Tackle",
"resource_uri": "/api/v1/move/1/"
},
{
"learn_type": "other",
"name": "Growl",
"resource_uri": "/api/v1/move/2/"
},
{
"learn_type": "level up",
"level": 10,
"name": "Vine whip",
"resource_uri": "/api/v1/move/3/"
}
],
"name": "Bulbasaur",
"national_id": 1,
"resource_uri": "/api/v1/pokemon/4/",
"sp_atk": 65,
"sp_def": 65,
"species": "seed pokemon",
"speed": 45,
"total": 318,
"types": [
{
"name": "grass",
"resource_uri": "/api/v1/type/5/"
},
{
"name": "poison",
"resource_uri": "/api/v1/type/8/"
}
],
"weight": "15.2lbs"
}
</pre>
</div>
</div>
<div class="col-md-2">
</div>
</div><!--interactive row-->
<div class="row">
<div class="col-md-1">
</div>
<div class="col-md-3">
<p class="lead center">
What is this?
</p>
<div class="well">
<p>
This is a full RESTful API linked to an extensive database
detailing everything about the Pokémon main game series.</p><p>
We've covered Pokémon, types, abilities, moves, egg groups and more.
</p>
</div>
</div>
<div class="col-md-4">
<p class="lead center">
How can I start using the API?
</p>
<div class="well">
<p>
We have awesome <a href="/v1/docs/">documentation</a> on
how to use this API. It takes minutes to get started.
</p>
<p>
This API will always be publicly available and will
never require any extensive setup process to consume.
</p>
</div>
</div>
<div class="col-md-3">
<p class="lead center">
I want to help.
</p>
<div class="well">
<p>Amazing!</p>
<p>Head over to <a href="https://github.com/phalt/pokeapi">GitHub</a> and read some of the issues and feature requests. If you can contribute then go ahead and start making pull requests :)</p>
</div>
</div>
<div class="col-md-1">
</div>
</div><!-- end bottom -->
<script>
function update(call){
jQuery('#interactive').val(call);
interactive_call();
}
function interactive_call(){
var content = jQuery('#interactive').val()
if(content == ''){
content = 'pokemon/1/';
}
var call_url = 'api/v1/' + content;
jQuery.ajax({
dataType: 'json',
url: call_url,
context: document.body
}).complete(function(data) {
if(data['status'] == 200){
var d = jQuery.parseJSON(data['responseText']);
jQuery('#interactive_name').html(d['name']);
jQuery('#interactive_output').text(JSON.stringify(d, null, '\t'));
}
else if (data['status'] == 404) {
jQuery('#interactive_output').text(data['status'] + ' ' + data['statusText']);
}
});
}
</script>
</div><!-- /.container -->
{% endblock %}

View file

@ -3,7 +3,7 @@
from __future__ import unicode_literals
from django.conf.urls import patterns, include, url
from django.views.generic import TemplateView
from django.contrib import admin
admin.autodiscover()
@ -34,17 +34,6 @@ api_resources.register(MoveResource())
api_resources.register(PokedexResource())
urlpatterns = [
# url(r'^v1$', 'pokemon.views.home'),
url(r'^v1/?$', 'pokemon.views.home'),
url(r'^v1/docs/$',
TemplateView.as_view(template_name='docs-v1.html'),
name="documentation"
),
url(r'^v1/about/$', 'pokemon.views.about'),
url(r'^api/', include(api_resources.urls)),
]

View file

@ -1,91 +0,0 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.auth.decorators import login_required
from pokemon.models import (
Pokemon, Sprite, Move, Description, Game,
EggGroup, Type, Ability, MovePokemon
)
from hits.models import ResourceView
def _total_site_data():
"""
Compute the total count of objects on the site
Using count() is drastically cheaper than len(objects.all())
"""
data = dict(
pokemon=Pokemon.objects.count(),
sprites=Sprite.objects.count(),
moves=Move.objects.count(),
descriptions=Description.objects.count(),
games=Game.objects.count(),
egg_groups=EggGroup.objects.count(),
types=Type.objects.count(),
abilities=Ability.objects.count(),
move_pokes=MovePokemon.objects.count()
)
t = 0
for i in data.iteritems():
t += i[1]
data['total_items'] = t
return data
@login_required
def moderate(request):
return render_to_response(
'pages/moderate.html',
{}, context_instance=RequestContext(request))
def about(request):
site_data = _total_site_data()
total_views = ResourceView.objects.total_count()
average_day = int(round(total_views / ResourceView.objects.count()))
return render_to_response(
'about-v1.html',
{
'total': total_views,
'average_day': average_day,
'site_data': site_data,
},
context_instance=RequestContext(request)
)
def home(request):
total_views = ResourceView.objects.total_count()
if total_views > 100:
total_views = int(round(total_views, -2))
return render_to_response(
'home-v1.html',
{
'total_views': total_views,
},
context_instance=RequestContext(request)
)
def twilio(request):
return render_to_response(
'pages/twilio.html',
{}, context_instance=RequestContext(request))

View file

@ -74,8 +74,8 @@ urlpatterns = [
url(r'^api/v2/', include(router.urls)),
url(r'^.*$',
TemplateView.as_view(template_name='home.html'),
name="home"
)
# url(r'^.*$',
# TemplateView.as_view(template_name='home.html'),
# name="home"
# )
]

View file

@ -8,8 +8,10 @@ django-cors-headers==1.0.0
django-discover-runner==0.4
django-imagekit==3.2.4
django-tastypie==0.12.1
django-markdown-deux==1.0.5
djangorestframework>=3.0.0
gunicorn==0.17.0
markdown2==2.3.0
mimeparse==0.1.3
pilkit==1.1.12
psycopg2==2.5.4

View file

@ -1,4 +1,4 @@
{% extends "base-v1.html" %}
{% extends "base.html" %}
{% block mainbody %}
<div class="navbar navbar-inverse navbar-fixed-top">

View file

@ -1,4 +1,4 @@
{% extends "base-v1.html" %}
{% extends "base.html" %}
{% block title %}Page Not found{% endblock %}

170
templates/about.html Executable file
View file

@ -0,0 +1,170 @@
{% extends "base.html" %}
{% load humanize %}
{% block mainbody %}
<section id="about">
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-brand">
<a href="https://twitter.com/share" class="twitter-share-button" data-url="http://pokeapi.co" data-text="Pokéapi - the Pokémon RESTful API " data-via="phalt_" data-related="phalt_">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
</div>
<div class="collapse navbar-collapse navbar-right">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
<li class="active"><a href="#">About</a></li>
<li><a href="/docs/">Documentation</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
<div class="header">
<h1>The RESTful Pokémon Data API</h1>
</div>
<div class="container">
<div class="row pad_top">
<div class="col-md-10 center-block">
<p class="lead">
What is this?
</p>
<div class="well">
<p>
This website provides a RESTful API interface to <b>{{ site_data.total_items|intcomma }}</b> objects
related to <a href="https://en.wikipedia.org/wiki/Pokemon">Pokémon</a>. We specifically cover the video game franchise, though we'd like to cover the card game too. Using this website you can consume information on Pokémon, their moves, abilities, types, egg groups and much much more.
</p>
</div>
<p class="lead">
What exactly is an API?
</p>
<div class="well">
<p>
This is probably worth clearing up very quickly for those who don't know.<br />
An API (Application Programming Interface) is a set of interfaces (in this case, url links)
that are publicly available, that allow developers to interact with an application.<br />
In this instance; the application is a database of <b>{{ site_data.total_items|intcomma }}</b> pokemon-related objects.
</p>
</div>
<p class="lead">
Isn't there 101 other Pokémon websites already?
</p>
<div class="well">
<p>
Yes and that's exactly the problem!
</p>
<p>
101 instances of the same website means 101 instances of the <b>same data</b>.
</p>
<p>
We aim to provide a <b>single database</b> that any number of other websites
can consume and use.
</p>
<p>
Often, and especially when new Pokémon games or updates are released, the 101+ websites
take <b>weeks</b> to update as people have to enter the same information in all those different places.
</p>
<p>This solves that problem.
</p>
<p>
If all those sites consumed their data from here, they would have the exact same information that is updated at exactly the same time, with no errors between each website.
</p>
<p>
The overall benefit is a better collaboration and consistency across all the different Pokémon
websites and applications. It's good for all!
</p>
</div>
<p class="lead">
How much information is stored here?
</p>
<div class="well">
<p>
I'm glad you asked because we've got an impressive amount of data!
</p>
<p>
We currently have <b>{{ site_data.total_items|intcomma }}</b> individual items in our database:
</p>
<ul>
<li>{{ site_data.pokemon }} Pokémon</li>
<li>{{ site_data.moves }} Moves</li>
<li>{{site_data.move_pokes|intcomma }} Pokémon<->move links</li>
<li>{{ site_data.abilities }} Abilities</li>
<li>{{ site_data.types }} Types</li>
<li>{{ site_data.egg_groups }} Egg groups</li>
<li>{{ site_data.descriptions }} Descriptions</li>
<li>{{ site_data.sprites }} Sprites</li>
<li>{{ site_data.games }} Games</li>
</ul>
<p class="lead">The server has processed <b>{{ total|intcomma }}</b> api calls at an average of <b>{{ average_day|intcomma }}</b> calls per day.</p>
</div>
<p class="lead">
The API is missing stuff!
</p>
<div class="well">
<p>
I know! Feel free to contribute to open issues on <a href="https://github.com/phalt/pokeapi/">GitHub</a>.
</p>
</div>
<p class="lead">
So who built this?
</p>
<div class="well">
<p>
Pokémon V1 was created by <a href="">Paul Hallett</a> as a weekend project but it quickly became more than a weekend's
worth of work. In December of 2014 Paul went open source with the project to begin work on V2.
Enter <a href="">Zane Adickes</a>. Zane thought the original project was a fantastic idea and wanted to help it grow.
With direction from Paul, Zane created the V2 api using an exact mirror of <a href="">Veekun's</a> data
from their <a href="">pokedex</a> project. That's not to say there hasn't been any help from others. Don't shy away
from jumping in and helping the project in any way you can!
<br>
Contributors:
</p>
<p>
I gathered the information on this site from various resources:
</p>
<ul>
<li><a href="https://github.com/veekun">Veekun</a> had a huge bunch of CSV's that
I used to build most of the data on the site.</li>
<li><a href="http://bulbapedia.bulbagarden.net/wiki/Main_Page">Bulbapedia</a> has a tonne of extra information that proved useful when designing the data model.</li>
</ul>
<p>
I'd also like to thank:
</p>
<ul>
<li>Laven Pillay, who scraped together most of the sprites used on the site.</li>
</ul>
</div>
<p class="lead">
What's the technology stack?
</p>
<div class="well">
<p>
The website framework is <a href="http://djangoproject.com">Django</a>,
a super awesome framework built around <a hre="http://python.org">Python</a>.<br />
We use a <a href="www.postgresql.org">Postgres</a> database to store all our data.<br />
We use <a href="http://django-tastypie.readthedocs.org/en/latest/">Django-tastypie</a> to expose our data through a RESTful API.<br />
We're hosted on <a href="https://www.digitalocean.com/?refcode=eab2fea41bc6
">DigitalOcean</a> servers, click the link to help keep the site running!.
</p>
</div>
</div>
</div><!--row-->
</div><!-- /.container -->
</section>
{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends "base-v1.html" %}
{% extends "base.html" %}
{% block mainbody %}
@ -17,8 +17,8 @@
</div>
<div class="collapse navbar-collapse navbar-right">
<ul class="nav navbar-nav">
<li><a href="/v1/">Home</a></li>
<li><a href="/v1/about/">About</a></li>
<li><a href="/">Home</a></li>
<li><a href="/about/">About</a></li>
<li class="active"><a href="#">Documentation</a></li>
</ul>
</div><!--/.nav-collapse -->

3039
templates/docs.md Normal file

File diff suppressed because it is too large Load diff

96
templates/docs2.html Normal file
View file

@ -0,0 +1,96 @@
{% extends "base.html" %}
{% load markdown_deux_tags %}
{% block mainbody %}
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-brand">
<a href="https://twitter.com/share" class="twitter-share-button" data-url="http://pokeapi.co" data-text="Pokéapi - the Pokémon RESTful API " data-via="phalt_" data-related="phalt_">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
</div>
<div class="collapse navbar-collapse navbar-right">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
<li><a href="/about/">About</a></li>
<li class="active"><a href="#">Documentation</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
<div class="header">
<h1>Pokeapi Version 2 API Documentation</h1>
</div>
<div id="docs" class="container">
<div class="row pad_top">
<div class="col-md-2">
<ul class="version-select">
<li><a href="">V1</a></li>
<li class="active"><a href="">V2</a></li>
</ul>
<ul class="side-nav hidden-sm">
<li><a href="">Information</a></li>
<li><a href="">Wrappers</a></li>
<hr>
<li><a href="">Resource Lists</a></li>
<hr>
<li><a href="">Berries</a></li>
<li>Contests</li>
<li>Encounters</li>
<li>Evolution</li>
<li>Games</li>
<li><a href="">Items</a></li>
<li><a href="#languages">Language</a></li>
<li><a href="">Locations</a></li>
<li><a href="">Moves</a></li>
<li><a href="#pokedexes">Pokedexes</a></li>
<li><a href="">Pokemon</a></li>
<hr>
<li><a href="#common-models">Common Models</a></li>
</ul>
</div>
<div class="col-md-10">
{% markdown %}
{% include "docs.md" %}
{% endmarkdown %}
</div>
</div>
</div>
{% endblock %}

278
templates/home.html Executable file
View file

@ -0,0 +1,278 @@
{% extends "base.html" %}
{% load humanize %}
{% block mainbody %}
<section id="home">
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<div class="navbar-brand">
<a href="https://twitter.com/share" class="twitter-share-button" data-url="http://pokeapi.co" data-text="Pokéapi - the Pokémon RESTful API " data-via="phalt_" data-related="phalt_">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
</div>
</div>
<div class="collapse navbar-collapse navbar-right">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="/about/">About</a></li>
<li><a href="/docs/">Documentation</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
<div class="header">
<h1>Pokéapi</h1>
<h2>The RESTful Pokémon API</h2>
<h4>Over <span class="count">{{ total_views|intcomma }}</span> API calls received!</h4>
</div>
<div class="container">
{% if update %}
<div class="row" style="padding-top:80px;text-align:center;">
<div class="col-md-2">
</div>
<div class="col-md-8">
<div class="alert alert-success">{{update.content|safe}}</div>
</div>
<div class="col-md-2">
</div>
</div><!-- /.header row -->
{% endif %}
</div>
<div class="cta">
<p>Finally; all the Pokémon data you'll ever need, in one place,<br /> and easily accessible through a modern RESTful API.</p>
<p>Whats new in V2? Check out the <a href="/docs2/">docs</a>!</p>
</div>
<div class="container">
<div class="row">
<div class="col-md-10 center-block">
<div class="center">
<h1>
Try it now!
</h1>
<div class="input-group pad_top">
<span class="input-group-addon url">http://pokeapi.co/api/v2/</span>
<input id="interactive" type="text" class="form-control" placeholder="pokemon/1/">
<span class="input-group-btn"><button onClick="interactive_call();return false;" class="btn btn-primary">submit</button></span>
</div>
</div>
<small>Need a hint? try <a href="#" onClick="update('pokemon/1/');return false;"><i>pokemon/1/</i></a> or <a href="#" onClick="update('type/3/');return false;"><i>type/3/</i></a> or <a href="#" onClick="update('ability/4/');return false;"><i>ability/4/</i></a></small>
<p class="lead pad_top">Resource for <span id="interactive_name">Bulbasaur</span></p>
<pre id="interactive_output" class="pre-scrollable">
{
"id": 1,
"name": "bulbasaur",
"base_experience": 64,
"height": 7,
"is_default": true,
"order": 1,
"weight": 69,
"abilities": [
{
"is_hidden": true,
"slot": 3,
"ability": {
"name": "chlorophyll",
"url": "http://localhost:8000/api/v2/ability/34/"
}
}
],
"forms": [
{
"name": "bulbasaur",
"url": "http://localhost:8000/api/v2/pokemon-form/1/"
}
],
"game_indices": [
{
"game_index": 1,
"version": {
"name": "white-2",
"url": "http://localhost:8000/api/v2/version/22/"
}
}
],
"held_items": [],
"location_area_encounters": [],
"moves": [
{
"move": {
"name": "captivate",
"url": "http://localhost:8000/api/v2/move/445/"
},
"version_group_details": [
{
"level_learned_at": 0,
"version_group": {
"name": "heartgold-soulsilver",
"url": "http://localhost:8000/api/v2/version-group/10/"
},
"move_learn_method": {
"name": "machine",
"url": "http://localhost:8000/api/v2/move-learn-method/4/"
}
},
{
"level_learned_at": 0,
"version_group": {
"name": "platinum",
"url": "http://localhost:8000/api/v2/version-group/9/"
},
"move_learn_method": {
"name": "machine",
"url": "http://localhost:8000/api/v2/move-learn-method/4/"
}
},
{
"level_learned_at": 0,
"version_group": {
"name": "diamond-pearl",
"url": "http://localhost:8000/api/v2/version-group/8/"
},
"move_learn_method": {
"name": "machine",
"url": "http://localhost:8000/api/v2/move-learn-method/4/"
}
}
]
}
],
"species": {
"name": "bulbasaur",
"url": "http://localhost:8000/api/v2/pokemon-species/1/"
},
"stats": [
{
"base_stat": 45,
"effort": 0,
"stat": {
"name": "speed",
"url": "http://localhost:8000/api/v2/stat/6/"
}
}
],
"types": [
{
"slot": 2,
"type": {
"name": "poison",
"url": "http://localhost:8000/api/v2/type/4/"
}
}
]
}
</pre>
</div>
</div><!--interactive row-->
<div class="row">
<div class="col-md-10 center-block">
<div class="row">
<div class="col-md-4">
<p class="lead center">
What is this?
</p>
<div class="well">
<p>
This is a full RESTful API linked to an extensive database
detailing everything about the Pokémon main game series.
</p>
<p>
We've covered everything from Pokémon, Berry Flavors.
</p>
</div>
</div>
<div class="col-md-4">
<p class="lead center">
Where do I start?
</p>
<div class="well">
<p>
We have awesome <a href="/v1/docs/">documentation</a> on
how to use this API. It takes minutes to get started.
</p>
<p>
This API will always be publicly available and will
never require any extensive setup process to consume.
</p>
</div>
</div>
<div class="col-md-4">
<p class="lead center">
I want to help.
</p>
<div class="well">
<p>Amazing!</p>
<p>Head over to <a href="https://github.com/phalt/pokeapi">GitHub</a> and read some of the issues and feature requests. If you can contribute then go ahead and start making pull requests :)</p>
</div>
</div>
</div>
</div>
</div><!-- end bottom -->
</div><!-- /.container -->
</section>
<script>
function update (call) {
jQuery('#interactive').val(call);
interactive_call();
}
function interactive_call() {
var content = jQuery('#interactive').val() || 'pokemon/1/';;
var call_url = 'api/v2/' + content;
jQuery.ajax({
dataType: 'json',
url: call_url,
context: document.body
}).complete( function(data) {
if(data['status'] == 200){
var d = jQuery.parseJSON(data['responseText']);
jQuery('#interactive_name').html(d['name']);
jQuery('#interactive_output').text(JSON.stringify(d, null, '\t'));
} else if (data['status'] == 404) {
jQuery('#interactive_output').text(data['status'] + ' ' + data['statusText']);
}
});
}
</script>
{% endblock %}