mirror of
https://github.com/PokeAPI/pokeapi
synced 2024-11-10 06:04:18 +00:00
Optimisations (#174)
* removed all the things causing slow times on data * fixup look sharp * use ujson * bep
This commit is contained in:
parent
5b94cff6c8
commit
422d98fff2
7 changed files with 16 additions and 244 deletions
|
@ -95,6 +95,7 @@ DATABASES = {
|
|||
'PASSWORD': 'pokeapi',
|
||||
'HOST': 'localhost',
|
||||
'PORT': '',
|
||||
'CONN_MAX_AGE': 30
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,10 +104,6 @@ CACHES = {
|
|||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||
'TIMEOUT': 30
|
||||
},
|
||||
'resources': {
|
||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||
'TIMEOUT': 360
|
||||
}
|
||||
}
|
||||
|
||||
SECRET_KEY = os.environ.get(
|
||||
|
@ -148,10 +145,10 @@ CORS_URLS_REGEX = r'^/api/.*$'
|
|||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_RENDERER_CLASSES': (
|
||||
'rest_framework.renderers.JSONRenderer',
|
||||
'drf_ujson.renderers.UJSONRenderer',
|
||||
),
|
||||
'DEFAULT_PARSER_CLASSES': (
|
||||
'rest_framework.parsers.JSONParser',
|
||||
'drf_ujson.renderers.UJSONRenderer',
|
||||
),
|
||||
|
||||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
|
||||
|
|
217
config/views.py
217
config/views.py
|
@ -10,224 +10,10 @@ from hits.models import ResourceView
|
|||
|
||||
import stripe
|
||||
|
||||
from pokemon_v2.models import * # NOQA
|
||||
|
||||
|
||||
def _total_site_data():
|
||||
|
||||
"""
|
||||
Compute the total count of objects on the site
|
||||
|
||||
Using count() is drastically cheaper than len(objects.all())
|
||||
"""
|
||||
|
||||
# v2 Sorry for the brute force. Theres probably a better way to do this.
|
||||
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(),
|
||||
characteristics=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_chains=EvolutionChain.objects.count(),
|
||||
evolution_triggers=EvolutionTrigger.objects.count(),
|
||||
evolution_trigger_names=EvolutionTriggerName.objects.count(),
|
||||
experiences=Experience.objects.count(),
|
||||
generations=Generation.objects.count(),
|
||||
generation_names=GenerationName.objects.count(),
|
||||
genders=Gender.objects.count(),
|
||||
growth_rates=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(),
|
||||
nature_names=NatureName.objects.count(),
|
||||
nature_pokeathlon_stats=NaturePokeathlonStat.objects.count(),
|
||||
nature_battle_style_preference=NatureBattleStylePreference.objects.count(),
|
||||
pal_park_areas=PalParkArea.objects.count(),
|
||||
pal_park_area_names=PalParkAreaName.objects.count(),
|
||||
pal_parks=PalPark.objects.count(),
|
||||
pokeathlon_stat_names=PokeathlonStatName.objects.count(),
|
||||
pokeathlon_stats=PokeathlonStat.objects.count(),
|
||||
pokedexes=PokedexVersionGroup.objects.count(),
|
||||
pokedex_descriptions=PokedexDescription.objects.count(),
|
||||
pokedex_version_groups=PokedexVersionGroup.objects.count(),
|
||||
pokemon=Pokemon.objects.count(),
|
||||
pokemon_abilities=PokemonAbility.objects.count(),
|
||||
pokemon_colors=PokemonColor.objects.count(),
|
||||
pokemon_names=PokemonColorName.objects.count(),
|
||||
pokemon_dex_numbers=PokemonDexNumber.objects.count(),
|
||||
pokemon_egg_groups=PokemonEggGroup.objects.count(),
|
||||
pokemon_evolutions=PokemonEvolution.objects.count(),
|
||||
pokemon_forms=PokemonForm.objects.count(),
|
||||
pokemon_form_names=PokemonFormName.objects.count(),
|
||||
pokemon_form_generations=PokemonFormGeneration.objects.count(),
|
||||
pokemon_game_indices=PokemonGameIndex.objects.count(),
|
||||
pokemon_habitats=PokemonHabitat.objects.count(),
|
||||
pokemon_habitat_names=PokemonHabitatName.objects.count(),
|
||||
pokemon_items=PokemonItem.objects.count(),
|
||||
pokemon_moves=PokemonMove.objects.count(),
|
||||
pokemon_shapes=PokemonShape.objects.count(),
|
||||
pokemon_shape_names=PokemonShapeName.objects.count(),
|
||||
pokemon_species=PokemonSpecies.objects.count(),
|
||||
pokemon_species_names=PokemonSpeciesName.objects.count(),
|
||||
pokemon_descriptions=PokemonSpeciesDescription.objects.count(),
|
||||
pokemon_flavor_texts=PokemonSpeciesFlavorText.objects.count(),
|
||||
pokemon_stat=PokemonStat.objects.count(),
|
||||
pokemon_type=PokemonType.objects.count(),
|
||||
regions=Region.objects.count(),
|
||||
region_names=RegionName.objects.count(),
|
||||
stats=Stat.objects.count(),
|
||||
stat_names=StatName.objects.count(),
|
||||
super_contest_effects=SuperContestEffect.objects.count(),
|
||||
super_contest_combos=SuperContestCombo.objects.count(),
|
||||
super_contest_effect_flavor_texts=SuperContestEffectFlavorText.objects.count(),
|
||||
types=Type.objects.count(),
|
||||
type_names=TypeName.objects.count(),
|
||||
type_game_indices=TypeGameIndex.objects.count(),
|
||||
type_efficacy=TypeEfficacy.objects.count(),
|
||||
versions=Version.objects.count(),
|
||||
version_names=VersionName.objects.count(),
|
||||
version_groups=VersionGroup.objects.count(),
|
||||
version_group_move_learn_methods=VersionGroupMoveLearnMethod.objects.count(),
|
||||
version_group_regions=VersionGroupRegion.objects.count(),
|
||||
)
|
||||
|
||||
lines = 0
|
||||
for i in data.iteritems():
|
||||
lines += i[1]
|
||||
|
||||
resources = 0
|
||||
resources += data['abilities']
|
||||
resources += data['berries']
|
||||
resources += data['berry_flavors']
|
||||
resources += data['berry_firmnesses']
|
||||
resources += data['characteristics']
|
||||
resources += data['contest_types']
|
||||
resources += data['contest_effects']
|
||||
resources += data['egg_groups']
|
||||
resources += data['encounter_methods']
|
||||
resources += data['encounter_conditions']
|
||||
resources += data['encounter_condition_values']
|
||||
resources += data['evolution_chains']
|
||||
resources += data['evolution_triggers']
|
||||
resources += data['generations']
|
||||
resources += data['genders']
|
||||
resources += data['growth_rates']
|
||||
resources += data['items']
|
||||
resources += data['item_attributes']
|
||||
resources += data['item_categories']
|
||||
resources += data['item_fling_effects']
|
||||
resources += data['item_pockets']
|
||||
resources += data['languages']
|
||||
resources += data['locations']
|
||||
resources += data['location_areas']
|
||||
resources += data['moves']
|
||||
resources += data['move_ailments']
|
||||
resources += data['move_categories']
|
||||
resources += data['move_battle_styles']
|
||||
resources += data['move_damage_classes']
|
||||
resources += data['move_learn_methods']
|
||||
resources += data['move_targets']
|
||||
resources += data['natures']
|
||||
resources += data['pal_park_areas']
|
||||
resources += data['pokedexes']
|
||||
resources += data['pokemon']
|
||||
resources += data['pokemon_colors']
|
||||
resources += data['pokemon_forms']
|
||||
resources += data['pokemon_habitats']
|
||||
resources += data['pokemon_shapes']
|
||||
resources += data['pokemon_species']
|
||||
resources += data['pokeathlon_stats']
|
||||
resources += data['regions']
|
||||
resources += data['stats']
|
||||
resources += data['super_contest_effects']
|
||||
resources += data['types']
|
||||
resources += data['versions']
|
||||
resources += data['version_groups']
|
||||
|
||||
data['total_lines'] = lines
|
||||
data['total_resources'] = resources
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def about(request):
|
||||
|
||||
site_data = _total_site_data()
|
||||
|
||||
total_views = ResourceView.objects.total_count()
|
||||
total_v1_views = ResourceView.objects.total_count(version=1)
|
||||
total_v2_views = ResourceView.objects.total_count(version=2)
|
||||
|
||||
average_day = int(round(total_views / ResourceView.objects.count()))
|
||||
|
||||
|
@ -235,10 +21,7 @@ def about(request):
|
|||
'pages/about.html',
|
||||
{
|
||||
'total': total_views,
|
||||
'total_v1': total_v1_views,
|
||||
'total_v2': total_v2_views,
|
||||
'average_day': average_day,
|
||||
'site_data': site_data,
|
||||
},
|
||||
context_instance=RequestContext(request)
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@ from django.db import models
|
|||
from datetime import date
|
||||
|
||||
|
||||
class ViewManager(models.Manager):
|
||||
class ResourceViewManager(models.Manager):
|
||||
|
||||
def increment_view_count(self, version):
|
||||
|
||||
|
@ -14,30 +14,21 @@ class ViewManager(models.Manager):
|
|||
|
||||
view.count = view.count + 1
|
||||
|
||||
print view
|
||||
|
||||
view.save()
|
||||
|
||||
def total_count(self, version=0):
|
||||
|
||||
if version:
|
||||
objects = ResourceView.objects.filter(version=version)
|
||||
else:
|
||||
objects = ResourceView.objects.all()
|
||||
all_hits = ResourceView.objects.all().values_list('count', flat=True)
|
||||
|
||||
t = 0
|
||||
for v in objects:
|
||||
t += v.count
|
||||
|
||||
return t
|
||||
return sum(all_hits)
|
||||
|
||||
|
||||
class ResourceView(models.Model):
|
||||
|
||||
objects = ViewManager()
|
||||
objects = ResourceViewManager()
|
||||
|
||||
def __unicode__(self):
|
||||
return str(self.date) + ' - ' + str(self.count)
|
||||
return '{} - {}'.format(str(self.date), str(self.count))
|
||||
|
||||
count = models.IntegerField(max_length=1000, default=0)
|
||||
version = models.IntegerField(max_length=1, default=1)
|
||||
|
|
|
@ -9,7 +9,7 @@ from hits.models import ResourceView
|
|||
|
||||
|
||||
###########################
|
||||
# BEHAVOIR ABSTRACTIONS #
|
||||
# BEHAVIOR ABSTRACTIONS #
|
||||
###########################
|
||||
|
||||
class ListOrDetailSerialRelation():
|
||||
|
|
|
@ -2974,7 +2974,7 @@ class PokedexDetailSerializer(serializers.ModelSerializer):
|
|||
|
||||
def get_pokedex_entries(self, obj):
|
||||
|
||||
results = PokemonDexNumber.objects.order_by('pokedex_number').filter(pokedex=obj)
|
||||
results = PokemonDexNumber.objects.filter(pokedex=obj).order_by('pokedex_number')
|
||||
serializer = PokemonDexNumberSerializer(results, many=True, context=self.context)
|
||||
data = serializer.data
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ django-imagekit==3.2.4
|
|||
django-tastypie==0.12.1
|
||||
django-markdown-deux==1.0.5
|
||||
djangorestframework>=3.1.0
|
||||
drf-ujson==1.2.0
|
||||
gunicorn==0.17.0
|
||||
markdown2==2.3.0
|
||||
mimeparse==0.1.3
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<section id="about">
|
||||
|
||||
<div class="header">
|
||||
|
||||
|
||||
<h1>The RESTful Pokémon Data API</h1>
|
||||
|
||||
</div>
|
||||
|
@ -37,7 +37,7 @@
|
|||
<div class="container">
|
||||
|
||||
<div class="row pad_top">
|
||||
|
||||
|
||||
<div class="col-md-10 center-block">
|
||||
|
||||
<p class="lead">
|
||||
|
@ -45,7 +45,7 @@
|
|||
</p>
|
||||
<div class="well">
|
||||
<p>
|
||||
This website provides a RESTful API interface to <b>{{ site_data.total_resources|intcomma }}</b> highly detailed objects built from <b>{{ site_data.total_lines|intcomma }}</b> lines of data
|
||||
This website provides a RESTful API interface to highly detailed objects built from thousands of lines of data
|
||||
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>
|
||||
|
@ -57,7 +57,7 @@
|
|||
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.
|
||||
In this instance; the application is a database of thousands oc pokemon-related objects.
|
||||
</p>
|
||||
</div>
|
||||
<p class="lead">
|
||||
|
@ -126,7 +126,7 @@
|
|||
<div class="well">
|
||||
<p>
|
||||
Pokémon V1 was created by <a href="http://github.com/phalt">Paul Hallett</a> as a weekend project but it quickly became more than a weekend's
|
||||
worth of work. In <a href="http://phalt.co/if-you-have-data-they-will-consume-it/" target="none">December of 2014</a> Paul deprecated V1 in favor of working on V2.
|
||||
worth of work. In <a href="http://phalt.co/if-you-have-data-they-will-consume-it/" target="none">December of 2014</a> Paul deprecated V1 in favor of working on V2.
|
||||
This is where <a href="http://github.com/zaneadix">Zane Adickes</a> jumped in. 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="http://github.com/eevee">Veekun's</a> data related to the main series of games.
|
||||
</p>
|
||||
|
|
Loading…
Reference in a new issue