├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── Dockerfile ├── LICENCE ├── Makefile ├── Procfile ├── README.md ├── manage.py ├── requirements.txt ├── resources ├── __init__.py ├── admin.py ├── fixtures │ ├── films.json │ ├── people.json │ ├── planets.json │ ├── species.json │ ├── starships.json │ ├── transport.json │ └── vehicles.json ├── migrations │ ├── 0001_initial.py │ ├── 0001_squashed_0005_remove_transport_pilots.py │ ├── 0002_auto_20141213_1454.py │ ├── 0003_film_release_date.py │ ├── 0004_editablemodel.py │ └── __init__.py ├── models.py ├── renderers.py ├── schemas.py ├── schemas │ ├── films.json │ ├── people.json │ ├── planets.json │ ├── species.json │ ├── starships.json │ └── vehicles.json ├── serializers.py ├── tests.py ├── utils.py └── views.py ├── run.sh ├── runtime.txt └── swapi ├── __init__.py ├── settings.py ├── static ├── css │ ├── bootstrap.css │ └── custom.css ├── favicon.ico └── humans.txt ├── templates ├── 404.html ├── 500.html ├── about.html ├── about.md ├── base.html ├── docs.md ├── documentation.html ├── index.html ├── rest_framework │ └── api.html └── stats.html ├── urls.py ├── views.py └── wsgi.py /.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | *.pyc 3 | staticfiles 4 | .env 5 | db.sqlite3 6 | .DS_Store 7 | .idea 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Config file for automatic testing at travis-ci.org 2 | 3 | language: python 4 | 5 | python: 6 | - "2.7" 7 | 8 | install: pip install -r requirements.txt 9 | 10 | script: python manage.py test 11 | 12 | notifications: 13 | email: false 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | Make sure your contribution isn't already a planned feature or has already 4 | been fixed by checking the issues first. 5 | 6 | 1. Fork this project. 7 | 8 | 2. Find an issue to fix or create a new issue if you want to propose a feature. For 9 | the new features - check out on GitHub issues first before starting to code it. 10 | 11 | 3. **No changes in the current API** are accepted. Even backward-compatible ones. 12 | The only exception is extending database and fixing data issues. These are OK. For 13 | all other changes - please submit a request and we'll review the feature for v2 of API. 14 | Current version will remain the same for the sake of compatibility with all the 15 | example code that API enthusiasts created. 16 | 17 | ## Development 18 | 19 | An application was originally built with Python 2.7 and Django 1.x. This stack is outdated hence 20 | continuing with this code base is not adviced. The next version of SWAPI will likely be 21 | cloud native and serverless. 22 | 23 | If you insist, best use Docker for building and running the project (Dockerfile is included 24 | in the root folder) 25 | 26 | ```shell 27 | docker build -t myswapi . 28 | docker run -p 8000:8000 myswapi 29 | ``` 30 | 31 | The same image is available as `juriy/swapi` from DockerHub. 32 | 33 | # Django commands 34 | 35 | The commands below are already executed in Docker image, if you need to work with Django 36 | directly or from inside the docker image, the following commands may be useful 37 | 38 | ```shell 39 | # run DB migrations 40 | python manage.py migrate 41 | 42 | # load data from fixtures 43 | make load_data 44 | 45 | # run the server 46 | python manage.py runserver 0.0.0.0:8000 47 | ``` 48 | 49 | If you add new data then you can dump it out using the following command: 50 | 51 | ``` 52 | make dumpdata 53 | ``` 54 | 55 | To run tests: 56 | 57 | ``` 58 | make test 59 | ``` 60 | 61 | ## File structure 62 | 63 | ### /resources 64 | All API resource models, serializers and schemas are found here. 65 | 66 | ### /swapi 67 | All Django configuration, templates and static files are found here. 68 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | FROM python:2 3 | ENV PYTHONUNBUFFERED=1 4 | RUN apt-get update && apt-get install -y libmemcached-dev 5 | WORKDIR /code 6 | COPY . /code/ 7 | RUN pip install -r requirements.txt 8 | CMD ["sh", "-c", "./run.sh"] 9 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Paul Hallett 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | * Neither the name of swapi nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | install: 3 | pip install -r requirements.txt 4 | 5 | build: 6 | python manage.py migrate 7 | python manage.py createsuperuser 8 | 9 | load_data: 10 | python manage.py loaddata planets.json 11 | python manage.py loaddata people.json 12 | python manage.py loaddata species.json 13 | python manage.py loaddata transport.json 14 | python manage.py loaddata starships.json 15 | python manage.py loaddata vehicles.json 16 | python manage.py loaddata films.json 17 | 18 | serve: 19 | python manage.py runserver 20 | 21 | dump_data: 22 | python manage.py dumpdata resources.planet > resources/fixtures/planets.json --indent 4 23 | python manage.py dumpdata resources.people > resources/fixtures/people.json --indent 4 24 | python manage.py dumpdata resources.species > resources/fixtures/species.json --indent 4 25 | python manage.py dumpdata resources.starship > resources/fixtures/starships.json --indent 4 26 | python manage.py dumpdata resources.vehicle > resources/fixtures/vehicles.json --indent 4 27 | python manage.py dumpdata resources.transport > resources/fixtures/transport.json --indent 4 28 | python manage.py dumpdata resources.film > resources/fixtures/films.json --indent 4 29 | 30 | 31 | drop_db: 32 | python manage.py flush 33 | 34 | test: 35 | python manage.py test 36 | 37 | 38 | clear_cache: 39 | python manage.py clear_cache 40 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn swapi.wsgi --log-file - -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SWAPI 2 | ## The Star Wars API 3 | 4 | Source code for [swapi.dev](https://swapi.dev) 5 | 6 | 7 | ## What happened to swapi.co? 8 | Unfortunately swapi.co is not maintained anymore. 9 | 10 | ## What is swapi.dev? 11 | An "unofficial" branch of "swapi", supported by @juriy 12 | 13 | 14 | ## Will it be updated? 15 | Original swapi project is built on Python/Django stack that is quite outdated by now. It would be a great exercise to rewrite it in cloud-native manner, but this requires time and effort. I'm looking into doing that. There's no timelines yet, since "swapi" stopped its existence quite suddenly. Suggestions and help are always welcome! 16 | 17 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "swapi.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Django==1.7.4 2 | Padding==0.4 3 | SQLAlchemy==0.9.8 4 | dj-database-url==0.3.0 5 | dj-stripe==0.3.5 6 | django-braces==1.4.0 7 | django-clear-cache==0.3 8 | django-cors-headers==1.0.0 9 | django-heroku-memcacheify==0.8 10 | django-jsonfield==0.9.13 11 | django-keen==0.1.3 12 | django-markdown-deux==1.0.5 13 | django-model-utils==2.2 14 | django-postgrespool==0.3.0 15 | django-pylibmc==0.5.0 16 | djangorestframework==3.0.0 17 | drf-json-api==0.1.0 18 | gunicorn==19.1.1 19 | keen==0.3.0 20 | markdown2==2.3.0 21 | psycopg2==2.7.3.2 22 | pycrypto==2.6.1 23 | pylibmc==1.4.1 24 | requests==2.5.1 25 | six==1.8.0 26 | stripe==1.19.1 27 | whitenoise==1.0.3 28 | wsgiref==0.1.2 29 | -------------------------------------------------------------------------------- /resources/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Juriy/swapi/5413ffe76ccd449fbcd9b2379b18a6c2a14ff1a5/resources/__init__.py -------------------------------------------------------------------------------- /resources/admin.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.contrib import admin 4 | 5 | from .models import ( 6 | People, 7 | Planet, 8 | Film, 9 | Starship, 10 | Vehicle, 11 | Species 12 | 13 | ) 14 | 15 | classes = [People, Planet, Film, Starship, Vehicle, Species] 16 | 17 | for c in classes: 18 | admin.site.register(c) 19 | -------------------------------------------------------------------------------- /resources/fixtures/films.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "fields": { 4 | "starships": [ 5 | 2, 6 | 3, 7 | 5, 8 | 9, 9 | 10, 10 | 11, 11 | 12, 12 | 13 13 | ], 14 | "edited": "2014-12-20T19:49:45.256Z", 15 | "vehicles": [ 16 | 4, 17 | 6, 18 | 7, 19 | 8 20 | ], 21 | "planets": [ 22 | 1, 23 | 2, 24 | 3 25 | ], 26 | "producer": "Gary Kurtz, Rick McCallum", 27 | "title": "A New Hope", 28 | "created": "2014-12-10T14:23:31.880Z", 29 | "episode_id": 4, 30 | "director": "George Lucas", 31 | "release_date": "1977-05-25", 32 | "opening_crawl": "It is a period of civil war.\r\nRebel spaceships, striking\r\nfrom a hidden base, have won\r\ntheir first victory against\r\nthe evil Galactic Empire.\r\n\r\nDuring the battle, Rebel\r\nspies managed to steal secret\r\nplans to the Empire's\r\nultimate weapon, the DEATH\r\nSTAR, an armored space\r\nstation with enough power\r\nto destroy an entire planet.\r\n\r\nPursued by the Empire's\r\nsinister agents, Princess\r\nLeia races home aboard her\r\nstarship, custodian of the\r\nstolen plans that can save her\r\npeople and restore\r\nfreedom to the galaxy....", 33 | "characters": [ 34 | 1, 35 | 2, 36 | 3, 37 | 4, 38 | 5, 39 | 6, 40 | 7, 41 | 8, 42 | 9, 43 | 10, 44 | 12, 45 | 13, 46 | 14, 47 | 15, 48 | 16, 49 | 18, 50 | 19, 51 | 81 52 | ], 53 | "species": [ 54 | 1, 55 | 2, 56 | 3, 57 | 4, 58 | 5 59 | ] 60 | }, 61 | "model": "resources.film", 62 | "pk": 1 63 | }, 64 | { 65 | "fields": { 66 | "starships": [ 67 | 3, 68 | 10, 69 | 11, 70 | 12, 71 | 15, 72 | 17, 73 | 21, 74 | 22, 75 | 23 76 | ], 77 | "edited": "2014-12-15T13:07:53.386Z", 78 | "vehicles": [ 79 | 8, 80 | 14, 81 | 16, 82 | 18, 83 | 19, 84 | 20 85 | ], 86 | "planets": [ 87 | 4, 88 | 5, 89 | 6, 90 | 27 91 | ], 92 | "producer": "Gary Kurtz, Rick McCallum", 93 | "title": "The Empire Strikes Back", 94 | "created": "2014-12-12T11:26:24.656Z", 95 | "episode_id": 5, 96 | "director": "Irvin Kershner", 97 | "release_date": "1980-05-17", 98 | "opening_crawl": "It is a dark time for the\r\nRebellion. Although the Death\r\nStar has been destroyed,\r\nImperial troops have driven the\r\nRebel forces from their hidden\r\nbase and pursued them across\r\nthe galaxy.\r\n\r\nEvading the dreaded Imperial\r\nStarfleet, a group of freedom\r\nfighters led by Luke Skywalker\r\nhas established a new secret\r\nbase on the remote ice world\r\nof Hoth.\r\n\r\nThe evil lord Darth Vader,\r\nobsessed with finding young\r\nSkywalker, has dispatched\r\nthousands of remote probes into\r\nthe far reaches of space....", 99 | "characters": [ 100 | 1, 101 | 2, 102 | 3, 103 | 4, 104 | 5, 105 | 10, 106 | 13, 107 | 14, 108 | 18, 109 | 20, 110 | 21, 111 | 22, 112 | 23, 113 | 24, 114 | 25, 115 | 26 116 | ], 117 | "species": [ 118 | 1, 119 | 2, 120 | 3, 121 | 6, 122 | 7 123 | ] 124 | }, 125 | "model": "resources.film", 126 | "pk": 2 127 | }, 128 | { 129 | "fields": { 130 | "starships": [ 131 | 2, 132 | 3, 133 | 10, 134 | 11, 135 | 12, 136 | 15, 137 | 17, 138 | 22, 139 | 23, 140 | 27, 141 | 28, 142 | 29 143 | ], 144 | "edited": "2014-12-20T09:48:37.462Z", 145 | "vehicles": [ 146 | 8, 147 | 16, 148 | 18, 149 | 19, 150 | 24, 151 | 25, 152 | 26, 153 | 30 154 | ], 155 | "planets": [ 156 | 1, 157 | 5, 158 | 7, 159 | 8, 160 | 9 161 | ], 162 | "producer": "Howard G. Kazanjian, George Lucas, Rick McCallum", 163 | "title": "Return of the Jedi", 164 | "created": "2014-12-18T10:39:33.255Z", 165 | "episode_id": 6, 166 | "director": "Richard Marquand", 167 | "release_date": "1983-05-25", 168 | "opening_crawl": "Luke Skywalker has returned to\r\nhis home planet of Tatooine in\r\nan attempt to rescue his\r\nfriend Han Solo from the\r\nclutches of the vile gangster\r\nJabba the Hutt.\r\n\r\nLittle does Luke know that the\r\nGALACTIC EMPIRE has secretly\r\nbegun construction on a new\r\narmored space station even\r\nmore powerful than the first\r\ndreaded Death Star.\r\n\r\nWhen completed, this ultimate\r\nweapon will spell certain doom\r\nfor the small band of rebels\r\nstruggling to restore freedom\r\nto the galaxy...", 169 | "characters": [ 170 | 1, 171 | 2, 172 | 3, 173 | 4, 174 | 5, 175 | 10, 176 | 13, 177 | 14, 178 | 16, 179 | 18, 180 | 20, 181 | 21, 182 | 22, 183 | 25, 184 | 27, 185 | 28, 186 | 29, 187 | 30, 188 | 31, 189 | 45 190 | ], 191 | "species": [ 192 | 1, 193 | 2, 194 | 3, 195 | 5, 196 | 6, 197 | 8, 198 | 9, 199 | 10, 200 | 15 201 | ] 202 | }, 203 | "model": "resources.film", 204 | "pk": 3 205 | }, 206 | { 207 | "fields": { 208 | "starships": [ 209 | 31, 210 | 32, 211 | 39, 212 | 40, 213 | 41 214 | ], 215 | "edited": "2014-12-20T10:54:07.216Z", 216 | "vehicles": [ 217 | 33, 218 | 34, 219 | 35, 220 | 36, 221 | 37, 222 | 38, 223 | 42 224 | ], 225 | "planets": [ 226 | 1, 227 | 8, 228 | 9 229 | ], 230 | "producer": "Rick McCallum", 231 | "title": "The Phantom Menace", 232 | "created": "2014-12-19T16:52:55.740Z", 233 | "episode_id": 1, 234 | "director": "George Lucas", 235 | "release_date": "1999-05-19", 236 | "opening_crawl": "Turmoil has engulfed the\r\nGalactic Republic. The taxation\r\nof trade routes to outlying star\r\nsystems is in dispute.\r\n\r\nHoping to resolve the matter\r\nwith a blockade of deadly\r\nbattleships, the greedy Trade\r\nFederation has stopped all\r\nshipping to the small planet\r\nof Naboo.\r\n\r\nWhile the Congress of the\r\nRepublic endlessly debates\r\nthis alarming chain of events,\r\nthe Supreme Chancellor has\r\nsecretly dispatched two Jedi\r\nKnights, the guardians of\r\npeace and justice in the\r\ngalaxy, to settle the conflict....", 237 | "characters": [ 238 | 2, 239 | 3, 240 | 10, 241 | 11, 242 | 16, 243 | 20, 244 | 21, 245 | 32, 246 | 33, 247 | 34, 248 | 35, 249 | 36, 250 | 37, 251 | 38, 252 | 39, 253 | 40, 254 | 41, 255 | 42, 256 | 43, 257 | 44, 258 | 46, 259 | 47, 260 | 48, 261 | 49, 262 | 50, 263 | 51, 264 | 52, 265 | 53, 266 | 54, 267 | 55, 268 | 56, 269 | 57, 270 | 58, 271 | 59 272 | ], 273 | "species": [ 274 | 1, 275 | 2, 276 | 6, 277 | 11, 278 | 12, 279 | 13, 280 | 14, 281 | 15, 282 | 16, 283 | 17, 284 | 18, 285 | 19, 286 | 20, 287 | 21, 288 | 22, 289 | 23, 290 | 24, 291 | 25, 292 | 26, 293 | 27 294 | ] 295 | }, 296 | "model": "resources.film", 297 | "pk": 4 298 | }, 299 | { 300 | "fields": { 301 | "starships": [ 302 | 21, 303 | 32, 304 | 39, 305 | 43, 306 | 47, 307 | 48, 308 | 49, 309 | 52, 310 | 58 311 | ], 312 | "edited": "2014-12-20T20:18:48.516Z", 313 | "vehicles": [ 314 | 4, 315 | 44, 316 | 45, 317 | 46, 318 | 50, 319 | 51, 320 | 53, 321 | 54, 322 | 55, 323 | 56, 324 | 57 325 | ], 326 | "planets": [ 327 | 1, 328 | 8, 329 | 9, 330 | 10, 331 | 11 332 | ], 333 | "producer": "Rick McCallum", 334 | "title": "Attack of the Clones", 335 | "created": "2014-12-20T10:57:57.886Z", 336 | "episode_id": 2, 337 | "director": "George Lucas", 338 | "release_date": "2002-05-16", 339 | "opening_crawl": "There is unrest in the Galactic\r\nSenate. Several thousand solar\r\nsystems have declared their\r\nintentions to leave the Republic.\r\n\r\nThis separatist movement,\r\nunder the leadership of the\r\nmysterious Count Dooku, has\r\nmade it difficult for the limited\r\nnumber of Jedi Knights to maintain \r\npeace and order in the galaxy.\r\n\r\nSenator Amidala, the former\r\nQueen of Naboo, is returning\r\nto the Galactic Senate to vote\r\non the critical issue of creating\r\nan ARMY OF THE REPUBLIC\r\nto assist the overwhelmed\r\nJedi....", 340 | "characters": [ 341 | 2, 342 | 3, 343 | 6, 344 | 7, 345 | 10, 346 | 11, 347 | 20, 348 | 21, 349 | 22, 350 | 33, 351 | 35, 352 | 36, 353 | 40, 354 | 43, 355 | 46, 356 | 51, 357 | 52, 358 | 53, 359 | 58, 360 | 59, 361 | 60, 362 | 61, 363 | 62, 364 | 63, 365 | 64, 366 | 65, 367 | 66, 368 | 67, 369 | 68, 370 | 69, 371 | 70, 372 | 71, 373 | 72, 374 | 73, 375 | 74, 376 | 75, 377 | 76, 378 | 77, 379 | 78, 380 | 82 381 | ], 382 | "species": [ 383 | 1, 384 | 2, 385 | 6, 386 | 12, 387 | 13, 388 | 15, 389 | 28, 390 | 29, 391 | 30, 392 | 31, 393 | 32, 394 | 33, 395 | 34, 396 | 35 397 | ] 398 | }, 399 | "model": "resources.film", 400 | "pk": 5 401 | }, 402 | { 403 | "fields": { 404 | "starships": [ 405 | 2, 406 | 32, 407 | 48, 408 | 59, 409 | 61, 410 | 63, 411 | 64, 412 | 65, 413 | 66, 414 | 68, 415 | 74, 416 | 75 417 | ], 418 | "edited": "2014-12-20T20:47:52.073Z", 419 | "vehicles": [ 420 | 33, 421 | 50, 422 | 53, 423 | 56, 424 | 60, 425 | 62, 426 | 67, 427 | 69, 428 | 70, 429 | 71, 430 | 72, 431 | 73, 432 | 76 433 | ], 434 | "planets": [ 435 | 1, 436 | 2, 437 | 5, 438 | 8, 439 | 9, 440 | 12, 441 | 13, 442 | 14, 443 | 15, 444 | 16, 445 | 17, 446 | 18, 447 | 19 448 | ], 449 | "producer": "Rick McCallum", 450 | "title": "Revenge of the Sith", 451 | "created": "2014-12-20T18:49:38.403Z", 452 | "episode_id": 3, 453 | "director": "George Lucas", 454 | "release_date": "2005-05-19", 455 | "opening_crawl": "War! The Republic is crumbling\r\nunder attacks by the ruthless\r\nSith Lord, Count Dooku.\r\nThere are heroes on both sides.\r\nEvil is everywhere.\r\n\r\nIn a stunning move, the\r\nfiendish droid leader, General\r\nGrievous, has swept into the\r\nRepublic capital and kidnapped\r\nChancellor Palpatine, leader of\r\nthe Galactic Senate.\r\n\r\nAs the Separatist Droid Army\r\nattempts to flee the besieged\r\ncapital with their valuable\r\nhostage, two Jedi Knights lead a\r\ndesperate mission to rescue the\r\ncaptive Chancellor....", 456 | "characters": [ 457 | 1, 458 | 2, 459 | 3, 460 | 4, 461 | 5, 462 | 6, 463 | 7, 464 | 10, 465 | 11, 466 | 12, 467 | 13, 468 | 20, 469 | 21, 470 | 33, 471 | 35, 472 | 46, 473 | 51, 474 | 52, 475 | 53, 476 | 54, 477 | 55, 478 | 56, 479 | 58, 480 | 63, 481 | 64, 482 | 67, 483 | 68, 484 | 75, 485 | 78, 486 | 79, 487 | 80, 488 | 81, 489 | 82, 490 | 83 491 | ], 492 | "species": [ 493 | 1, 494 | 2, 495 | 3, 496 | 6, 497 | 15, 498 | 19, 499 | 20, 500 | 23, 501 | 24, 502 | 25, 503 | 26, 504 | 27, 505 | 28, 506 | 29, 507 | 30, 508 | 33, 509 | 34, 510 | 35, 511 | 36, 512 | 37 513 | ] 514 | }, 515 | "model": "resources.film", 516 | "pk": 6 517 | } 518 | ] 519 | -------------------------------------------------------------------------------- /resources/fixtures/planets.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "fields": { 4 | "edited": "2014-12-20T20:58:18.411Z", 5 | "climate": "arid", 6 | "surface_water": "1", 7 | "name": "Tatooine", 8 | "diameter": "10465", 9 | "rotation_period": "23", 10 | "created": "2014-12-09T13:50:49.641Z", 11 | "terrain": "desert", 12 | "gravity": "1 standard", 13 | "orbital_period": "304", 14 | "population": "200000" 15 | }, 16 | "model": "resources.planet", 17 | "pk": 1 18 | }, 19 | { 20 | "fields": { 21 | "edited": "2014-12-20T20:58:18.420Z", 22 | "climate": "temperate", 23 | "surface_water": "40", 24 | "name": "Alderaan", 25 | "diameter": "12500", 26 | "rotation_period": "24", 27 | "created": "2014-12-10T11:35:48.479Z", 28 | "terrain": "grasslands, mountains", 29 | "gravity": "1 standard", 30 | "orbital_period": "364", 31 | "population": "2000000000" 32 | }, 33 | "model": "resources.planet", 34 | "pk": 2 35 | }, 36 | { 37 | "fields": { 38 | "edited": "2014-12-20T20:58:18.421Z", 39 | "climate": "temperate, tropical", 40 | "surface_water": "8", 41 | "name": "Yavin IV", 42 | "diameter": "10200", 43 | "rotation_period": "24", 44 | "created": "2014-12-10T11:37:19.144Z", 45 | "terrain": "jungle, rainforests", 46 | "gravity": "1 standard", 47 | "orbital_period": "4818", 48 | "population": "1000" 49 | }, 50 | "model": "resources.planet", 51 | "pk": 3 52 | }, 53 | { 54 | "fields": { 55 | "edited": "2014-12-20T20:58:18.423Z", 56 | "climate": "frozen", 57 | "surface_water": "100", 58 | "name": "Hoth", 59 | "diameter": "7200", 60 | "rotation_period": "23", 61 | "created": "2014-12-10T11:39:13.934Z", 62 | "terrain": "tundra, ice caves, mountain ranges", 63 | "gravity": "1.1 standard", 64 | "orbital_period": "549", 65 | "population": "unknown" 66 | }, 67 | "model": "resources.planet", 68 | "pk": 4 69 | }, 70 | { 71 | "fields": { 72 | "edited": "2014-12-20T20:58:18.425Z", 73 | "climate": "murky", 74 | "surface_water": "8", 75 | "name": "Dagobah", 76 | "diameter": "8900", 77 | "rotation_period": "23", 78 | "created": "2014-12-10T11:42:22.590Z", 79 | "terrain": "swamp, jungles", 80 | "gravity": "N/A", 81 | "orbital_period": "341", 82 | "population": "unknown" 83 | }, 84 | "model": "resources.planet", 85 | "pk": 5 86 | }, 87 | { 88 | "fields": { 89 | "edited": "2014-12-20T20:58:18.427Z", 90 | "climate": "temperate", 91 | "surface_water": "0", 92 | "name": "Bespin", 93 | "diameter": "118000", 94 | "rotation_period": "12", 95 | "created": "2014-12-10T11:43:55.240Z", 96 | "terrain": "gas giant", 97 | "gravity": "1.5 (surface), 1 standard (Cloud City)", 98 | "orbital_period": "5110", 99 | "population": "6000000" 100 | }, 101 | "model": "resources.planet", 102 | "pk": 6 103 | }, 104 | { 105 | "fields": { 106 | "edited": "2014-12-20T20:58:18.429Z", 107 | "climate": "temperate", 108 | "surface_water": "8", 109 | "name": "Endor", 110 | "diameter": "4900", 111 | "rotation_period": "18", 112 | "created": "2014-12-10T11:50:29.349Z", 113 | "terrain": "forests, mountains, lakes", 114 | "gravity": "0.85 standard", 115 | "orbital_period": "402", 116 | "population": "30000000" 117 | }, 118 | "model": "resources.planet", 119 | "pk": 7 120 | }, 121 | { 122 | "fields": { 123 | "edited": "2014-12-20T20:58:18.430Z", 124 | "climate": "temperate", 125 | "surface_water": "12", 126 | "name": "Naboo", 127 | "diameter": "12120", 128 | "rotation_period": "26", 129 | "created": "2014-12-10T11:52:31.066Z", 130 | "terrain": "grassy hills, swamps, forests, mountains", 131 | "gravity": "1 standard", 132 | "orbital_period": "312", 133 | "population": "4500000000" 134 | }, 135 | "model": "resources.planet", 136 | "pk": 8 137 | }, 138 | { 139 | "fields": { 140 | "edited": "2014-12-20T20:58:18.432Z", 141 | "climate": "temperate", 142 | "surface_water": "unknown", 143 | "name": "Coruscant", 144 | "diameter": "12240", 145 | "rotation_period": "24", 146 | "created": "2014-12-10T11:54:13.921Z", 147 | "terrain": "cityscape, mountains", 148 | "gravity": "1 standard", 149 | "orbital_period": "368", 150 | "population": "1000000000000" 151 | }, 152 | "model": "resources.planet", 153 | "pk": 9 154 | }, 155 | { 156 | "fields": { 157 | "edited": "2014-12-20T20:58:18.434Z", 158 | "climate": "temperate", 159 | "surface_water": "100", 160 | "name": "Kamino", 161 | "diameter": "19720", 162 | "rotation_period": "27", 163 | "created": "2014-12-10T12:45:06.577Z", 164 | "terrain": "ocean", 165 | "gravity": "1 standard", 166 | "orbital_period": "463", 167 | "population": "1000000000" 168 | }, 169 | "model": "resources.planet", 170 | "pk": 10 171 | }, 172 | { 173 | "fields": { 174 | "edited": "2014-12-20T20:58:18.437Z", 175 | "climate": "temperate, arid", 176 | "surface_water": "5", 177 | "name": "Geonosis", 178 | "diameter": "11370", 179 | "rotation_period": "30", 180 | "created": "2014-12-10T12:47:22.350Z", 181 | "terrain": "rock, desert, mountain, barren", 182 | "gravity": "0.9 standard", 183 | "orbital_period": "256", 184 | "population": "100000000000" 185 | }, 186 | "model": "resources.planet", 187 | "pk": 11 188 | }, 189 | { 190 | "fields": { 191 | "edited": "2014-12-20T20:58:18.439Z", 192 | "climate": "temperate, arid, windy", 193 | "surface_water": "0.9", 194 | "name": "Utapau", 195 | "diameter": "12900", 196 | "rotation_period": "27", 197 | "created": "2014-12-10T12:49:01.491Z", 198 | "terrain": "scrublands, savanna, canyons, sinkholes", 199 | "gravity": "1 standard", 200 | "orbital_period": "351", 201 | "population": "95000000" 202 | }, 203 | "model": "resources.planet", 204 | "pk": 12 205 | }, 206 | { 207 | "fields": { 208 | "edited": "2014-12-20T20:58:18.440Z", 209 | "climate": "hot", 210 | "surface_water": "0", 211 | "name": "Mustafar", 212 | "diameter": "4200", 213 | "rotation_period": "36", 214 | "created": "2014-12-10T12:50:16.526Z", 215 | "terrain": "volcanoes, lava rivers, mountains, caves", 216 | "gravity": "1 standard", 217 | "orbital_period": "412", 218 | "population": "20000" 219 | }, 220 | "model": "resources.planet", 221 | "pk": 13 222 | }, 223 | { 224 | "fields": { 225 | "edited": "2014-12-20T20:58:18.442Z", 226 | "climate": "tropical", 227 | "surface_water": "60", 228 | "name": "Kashyyyk", 229 | "diameter": "12765", 230 | "rotation_period": "26", 231 | "created": "2014-12-10T13:32:00.124Z", 232 | "terrain": "jungle, forests, lakes, rivers", 233 | "gravity": "1 standard", 234 | "orbital_period": "381", 235 | "population": "45000000" 236 | }, 237 | "model": "resources.planet", 238 | "pk": 14 239 | }, 240 | { 241 | "fields": { 242 | "edited": "2014-12-20T20:58:18.444Z", 243 | "climate": "artificial temperate ", 244 | "surface_water": "0", 245 | "name": "Polis Massa", 246 | "diameter": "0", 247 | "rotation_period": "24", 248 | "created": "2014-12-10T13:33:46.405Z", 249 | "terrain": "airless asteroid", 250 | "gravity": "0.56 standard", 251 | "orbital_period": "590", 252 | "population": "1000000" 253 | }, 254 | "model": "resources.planet", 255 | "pk": 15 256 | }, 257 | { 258 | "fields": { 259 | "edited": "2014-12-20T20:58:18.446Z", 260 | "climate": "frigid", 261 | "surface_water": "unknown", 262 | "name": "Mygeeto", 263 | "diameter": "10088", 264 | "rotation_period": "12", 265 | "created": "2014-12-10T13:43:39.139Z", 266 | "terrain": "glaciers, mountains, ice canyons", 267 | "gravity": "1 standard", 268 | "orbital_period": "167", 269 | "population": "19000000" 270 | }, 271 | "model": "resources.planet", 272 | "pk": 16 273 | }, 274 | { 275 | "fields": { 276 | "edited": "2014-12-20T20:58:18.447Z", 277 | "climate": "hot, humid", 278 | "surface_water": "unknown", 279 | "name": "Felucia", 280 | "diameter": "9100", 281 | "rotation_period": "34", 282 | "created": "2014-12-10T13:44:50.397Z", 283 | "terrain": "fungus forests", 284 | "gravity": "0.75 standard", 285 | "orbital_period": "231", 286 | "population": "8500000" 287 | }, 288 | "model": "resources.planet", 289 | "pk": 17 290 | }, 291 | { 292 | "fields": { 293 | "edited": "2014-12-20T20:58:18.449Z", 294 | "climate": "temperate, moist", 295 | "surface_water": "unknown", 296 | "name": "Cato Neimoidia", 297 | "diameter": "0", 298 | "rotation_period": "25", 299 | "created": "2014-12-10T13:46:28.704Z", 300 | "terrain": "mountains, fields, forests, rock arches", 301 | "gravity": "1 standard", 302 | "orbital_period": "278", 303 | "population": "10000000" 304 | }, 305 | "model": "resources.planet", 306 | "pk": 18 307 | }, 308 | { 309 | "fields": { 310 | "edited": "2014-12-20T20:58:18.450Z", 311 | "climate": "hot", 312 | "surface_water": "unknown", 313 | "name": "Saleucami", 314 | "diameter": "14920", 315 | "rotation_period": "26", 316 | "created": "2014-12-10T13:47:46.874Z", 317 | "terrain": "caves, desert, mountains, volcanoes", 318 | "gravity": "unknown", 319 | "orbital_period": "392", 320 | "population": "1400000000" 321 | }, 322 | "model": "resources.planet", 323 | "pk": 19 324 | }, 325 | { 326 | "fields": { 327 | "edited": "2014-12-20T20:58:18.452Z", 328 | "climate": "temperate", 329 | "surface_water": "unknown", 330 | "name": "Stewjon", 331 | "diameter": "0", 332 | "rotation_period": "unknown", 333 | "created": "2014-12-10T16:16:26.566Z", 334 | "terrain": "grass", 335 | "gravity": "1 standard", 336 | "orbital_period": "unknown", 337 | "population": "unknown" 338 | }, 339 | "model": "resources.planet", 340 | "pk": 20 341 | }, 342 | { 343 | "fields": { 344 | "edited": "2014-12-20T20:58:18.454Z", 345 | "climate": "polluted", 346 | "surface_water": "unknown", 347 | "name": "Eriadu", 348 | "diameter": "13490", 349 | "rotation_period": "24", 350 | "created": "2014-12-10T16:26:54.384Z", 351 | "terrain": "cityscape", 352 | "gravity": "1 standard", 353 | "orbital_period": "360", 354 | "population": "22000000000" 355 | }, 356 | "model": "resources.planet", 357 | "pk": 21 358 | }, 359 | { 360 | "fields": { 361 | "edited": "2014-12-20T20:58:18.456Z", 362 | "climate": "temperate", 363 | "surface_water": "70", 364 | "name": "Corellia", 365 | "diameter": "11000", 366 | "rotation_period": "25", 367 | "created": "2014-12-10T16:49:12.453Z", 368 | "terrain": "plains, urban, hills, forests", 369 | "gravity": "1 standard", 370 | "orbital_period": "329", 371 | "population": "3000000000" 372 | }, 373 | "model": "resources.planet", 374 | "pk": 22 375 | }, 376 | { 377 | "fields": { 378 | "edited": "2014-12-20T20:58:18.458Z", 379 | "climate": "hot", 380 | "surface_water": "60", 381 | "name": "Rodia", 382 | "diameter": "7549", 383 | "rotation_period": "29", 384 | "created": "2014-12-10T17:03:28.110Z", 385 | "terrain": "jungles, oceans, urban, swamps", 386 | "gravity": "1 standard", 387 | "orbital_period": "305", 388 | "population": "1300000000" 389 | }, 390 | "model": "resources.planet", 391 | "pk": 23 392 | }, 393 | { 394 | "fields": { 395 | "edited": "2014-12-20T20:58:18.460Z", 396 | "climate": "temperate", 397 | "surface_water": "unknown", 398 | "name": "Nal Hutta", 399 | "diameter": "12150", 400 | "rotation_period": "87", 401 | "created": "2014-12-10T17:11:29.452Z", 402 | "terrain": "urban, oceans, swamps, bogs", 403 | "gravity": "1 standard", 404 | "orbital_period": "413", 405 | "population": "7000000000" 406 | }, 407 | "model": "resources.planet", 408 | "pk": 24 409 | }, 410 | { 411 | "fields": { 412 | "edited": "2014-12-20T20:58:18.461Z", 413 | "climate": "temperate", 414 | "surface_water": "unknown", 415 | "name": "Dantooine", 416 | "diameter": "9830", 417 | "rotation_period": "25", 418 | "created": "2014-12-10T17:23:29.896Z", 419 | "terrain": "oceans, savannas, mountains, grasslands", 420 | "gravity": "1 standard", 421 | "orbital_period": "378", 422 | "population": "1000" 423 | }, 424 | "model": "resources.planet", 425 | "pk": 25 426 | }, 427 | { 428 | "fields": { 429 | "edited": "2014-12-20T20:58:18.463Z", 430 | "climate": "temperate", 431 | "surface_water": "98", 432 | "name": "Bestine IV", 433 | "diameter": "6400", 434 | "rotation_period": "26", 435 | "created": "2014-12-12T11:16:55.078Z", 436 | "terrain": "rocky islands, oceans", 437 | "gravity": "unknown", 438 | "orbital_period": "680", 439 | "population": "62000000" 440 | }, 441 | "model": "resources.planet", 442 | "pk": 26 443 | }, 444 | { 445 | "fields": { 446 | "edited": "2014-12-20T20:58:18.464Z", 447 | "climate": "temperate", 448 | "surface_water": "10", 449 | "name": "Ord Mantell", 450 | "diameter": "14050", 451 | "rotation_period": "26", 452 | "created": "2014-12-15T12:23:41.661Z", 453 | "terrain": "plains, seas, mesas", 454 | "gravity": "1 standard", 455 | "orbital_period": "334", 456 | "population": "4000000000" 457 | }, 458 | "model": "resources.planet", 459 | "pk": 27 460 | }, 461 | { 462 | "fields": { 463 | "edited": "2014-12-20T20:58:18.466Z", 464 | "climate": "unknown", 465 | "surface_water": "unknown", 466 | "name": "unknown", 467 | "diameter": "0", 468 | "rotation_period": "0", 469 | "created": "2014-12-15T12:25:59.569Z", 470 | "terrain": "unknown", 471 | "gravity": "unknown", 472 | "orbital_period": "0", 473 | "population": "unknown" 474 | }, 475 | "model": "resources.planet", 476 | "pk": 28 477 | }, 478 | { 479 | "fields": { 480 | "edited": "2014-12-20T20:58:18.468Z", 481 | "climate": "arid", 482 | "surface_water": "unknown", 483 | "name": "Trandosha", 484 | "diameter": "0", 485 | "rotation_period": "25", 486 | "created": "2014-12-15T12:53:47.695Z", 487 | "terrain": "mountains, seas, grasslands, deserts", 488 | "gravity": "0.62 standard", 489 | "orbital_period": "371", 490 | "population": "42000000" 491 | }, 492 | "model": "resources.planet", 493 | "pk": 29 494 | }, 495 | { 496 | "fields": { 497 | "edited": "2014-12-20T20:58:18.469Z", 498 | "climate": "arid", 499 | "surface_water": "unknown", 500 | "name": "Socorro", 501 | "diameter": "0", 502 | "rotation_period": "20", 503 | "created": "2014-12-15T12:56:31.121Z", 504 | "terrain": "deserts, mountains", 505 | "gravity": "1 standard", 506 | "orbital_period": "326", 507 | "population": "300000000" 508 | }, 509 | "model": "resources.planet", 510 | "pk": 30 511 | }, 512 | { 513 | "fields": { 514 | "edited": "2014-12-20T20:58:18.471Z", 515 | "climate": "temperate", 516 | "surface_water": "100", 517 | "name": "Mon Cala", 518 | "diameter": "11030", 519 | "rotation_period": "21", 520 | "created": "2014-12-18T11:07:01.792Z", 521 | "terrain": "oceans, reefs, islands", 522 | "gravity": "1", 523 | "orbital_period": "398", 524 | "population": "27000000000" 525 | }, 526 | "model": "resources.planet", 527 | "pk": 31 528 | }, 529 | { 530 | "fields": { 531 | "edited": "2014-12-20T20:58:18.472Z", 532 | "climate": "temperate", 533 | "surface_water": "40", 534 | "name": "Chandrila", 535 | "diameter": "13500", 536 | "rotation_period": "20", 537 | "created": "2014-12-18T11:11:51.872Z", 538 | "terrain": "plains, forests", 539 | "gravity": "1", 540 | "orbital_period": "368", 541 | "population": "1200000000" 542 | }, 543 | "model": "resources.planet", 544 | "pk": 32 545 | }, 546 | { 547 | "fields": { 548 | "edited": "2014-12-20T20:58:18.474Z", 549 | "climate": "superheated", 550 | "surface_water": "5", 551 | "name": "Sullust", 552 | "diameter": "12780", 553 | "rotation_period": "20", 554 | "created": "2014-12-18T11:25:40.243Z", 555 | "terrain": "mountains, volcanoes, rocky deserts", 556 | "gravity": "1", 557 | "orbital_period": "263", 558 | "population": "18500000000" 559 | }, 560 | "model": "resources.planet", 561 | "pk": 33 562 | }, 563 | { 564 | "fields": { 565 | "edited": "2014-12-20T20:58:18.476Z", 566 | "climate": "temperate", 567 | "surface_water": "unknown", 568 | "name": "Toydaria", 569 | "diameter": "7900", 570 | "rotation_period": "21", 571 | "created": "2014-12-19T17:47:54.403Z", 572 | "terrain": "swamps, lakes", 573 | "gravity": "1", 574 | "orbital_period": "184", 575 | "population": "11000000" 576 | }, 577 | "model": "resources.planet", 578 | "pk": 34 579 | }, 580 | { 581 | "fields": { 582 | "edited": "2014-12-20T20:58:18.478Z", 583 | "climate": "arid, temperate, tropical", 584 | "surface_water": "unknown", 585 | "name": "Malastare", 586 | "diameter": "18880", 587 | "rotation_period": "26", 588 | "created": "2014-12-19T17:52:13.106Z", 589 | "terrain": "swamps, deserts, jungles, mountains", 590 | "gravity": "1.56", 591 | "orbital_period": "201", 592 | "population": "2000000000" 593 | }, 594 | "model": "resources.planet", 595 | "pk": 35 596 | }, 597 | { 598 | "fields": { 599 | "edited": "2014-12-20T20:58:18.480Z", 600 | "climate": "temperate", 601 | "surface_water": "unknown", 602 | "name": "Dathomir", 603 | "diameter": "10480", 604 | "rotation_period": "24", 605 | "created": "2014-12-19T18:00:40.142Z", 606 | "terrain": "forests, deserts, savannas", 607 | "gravity": "0.9", 608 | "orbital_period": "491", 609 | "population": "5200" 610 | }, 611 | "model": "resources.planet", 612 | "pk": 36 613 | }, 614 | { 615 | "fields": { 616 | "edited": "2014-12-20T20:58:18.481Z", 617 | "climate": "temperate, arid, subartic", 618 | "surface_water": "5", 619 | "name": "Ryloth", 620 | "diameter": "10600", 621 | "rotation_period": "30", 622 | "created": "2014-12-20T09:46:25.740Z", 623 | "terrain": "mountains, valleys, deserts, tundra", 624 | "gravity": "1", 625 | "orbital_period": "305", 626 | "population": "1500000000" 627 | }, 628 | "model": "resources.planet", 629 | "pk": 37 630 | }, 631 | { 632 | "fields": { 633 | "edited": "2014-12-20T20:58:18.483Z", 634 | "climate": "unknown", 635 | "surface_water": "unknown", 636 | "name": "Aleen Minor", 637 | "diameter": "unknown", 638 | "rotation_period": "unknown", 639 | "created": "2014-12-20T09:52:23.452Z", 640 | "terrain": "unknown", 641 | "gravity": "unknown", 642 | "orbital_period": "unknown", 643 | "population": "unknown" 644 | }, 645 | "model": "resources.planet", 646 | "pk": 38 647 | }, 648 | { 649 | "fields": { 650 | "edited": "2014-12-20T20:58:18.485Z", 651 | "climate": "temperate, artic", 652 | "surface_water": "unknown", 653 | "name": "Vulpter", 654 | "diameter": "14900", 655 | "rotation_period": "22", 656 | "created": "2014-12-20T09:56:58.874Z", 657 | "terrain": "urban, barren", 658 | "gravity": "1", 659 | "orbital_period": "391", 660 | "population": "421000000" 661 | }, 662 | "model": "resources.planet", 663 | "pk": 39 664 | }, 665 | { 666 | "fields": { 667 | "edited": "2014-12-20T20:58:18.487Z", 668 | "climate": "unknown", 669 | "surface_water": "unknown", 670 | "name": "Troiken", 671 | "diameter": "unknown", 672 | "rotation_period": "unknown", 673 | "created": "2014-12-20T10:01:37.395Z", 674 | "terrain": "desert, tundra, rainforests, mountains", 675 | "gravity": "unknown", 676 | "orbital_period": "unknown", 677 | "population": "unknown" 678 | }, 679 | "model": "resources.planet", 680 | "pk": 40 681 | }, 682 | { 683 | "fields": { 684 | "edited": "2014-12-20T20:58:18.489Z", 685 | "climate": "unknown", 686 | "surface_water": "unknown", 687 | "name": "Tund", 688 | "diameter": "12190", 689 | "rotation_period": "48", 690 | "created": "2014-12-20T10:07:29.578Z", 691 | "terrain": "barren, ash", 692 | "gravity": "unknown", 693 | "orbital_period": "1770", 694 | "population": "0" 695 | }, 696 | "model": "resources.planet", 697 | "pk": 41 698 | }, 699 | { 700 | "fields": { 701 | "edited": "2014-12-20T20:58:18.491Z", 702 | "climate": "temperate", 703 | "surface_water": "unknown", 704 | "name": "Haruun Kal", 705 | "diameter": "10120", 706 | "rotation_period": "25", 707 | "created": "2014-12-20T10:12:28.980Z", 708 | "terrain": "toxic cloudsea, plateaus, volcanoes", 709 | "gravity": "0.98", 710 | "orbital_period": "383", 711 | "population": "705300" 712 | }, 713 | "model": "resources.planet", 714 | "pk": 42 715 | }, 716 | { 717 | "fields": { 718 | "edited": "2014-12-20T20:58:18.493Z", 719 | "climate": "temperate", 720 | "surface_water": "20", 721 | "name": "Cerea", 722 | "diameter": "unknown", 723 | "rotation_period": "27", 724 | "created": "2014-12-20T10:14:48.178Z", 725 | "terrain": "verdant", 726 | "gravity": "1", 727 | "orbital_period": "386", 728 | "population": "450000000" 729 | }, 730 | "model": "resources.planet", 731 | "pk": 43 732 | }, 733 | { 734 | "fields": { 735 | "edited": "2014-12-20T20:58:18.495Z", 736 | "climate": "tropical, temperate", 737 | "surface_water": "80", 738 | "name": "Glee Anselm", 739 | "diameter": "15600", 740 | "rotation_period": "33", 741 | "created": "2014-12-20T10:18:26.110Z", 742 | "terrain": "lakes, islands, swamps, seas", 743 | "gravity": "1", 744 | "orbital_period": "206", 745 | "population": "500000000" 746 | }, 747 | "model": "resources.planet", 748 | "pk": 44 749 | }, 750 | { 751 | "fields": { 752 | "edited": "2014-12-20T20:58:18.497Z", 753 | "climate": "unknown", 754 | "surface_water": "unknown", 755 | "name": "Iridonia", 756 | "diameter": "unknown", 757 | "rotation_period": "29", 758 | "created": "2014-12-20T10:26:05.788Z", 759 | "terrain": "rocky canyons, acid pools", 760 | "gravity": "unknown", 761 | "orbital_period": "413", 762 | "population": "unknown" 763 | }, 764 | "model": "resources.planet", 765 | "pk": 45 766 | }, 767 | { 768 | "fields": { 769 | "edited": "2014-12-20T20:58:18.498Z", 770 | "climate": "unknown", 771 | "surface_water": "unknown", 772 | "name": "Tholoth", 773 | "diameter": "unknown", 774 | "rotation_period": "unknown", 775 | "created": "2014-12-20T10:28:31.117Z", 776 | "terrain": "unknown", 777 | "gravity": "unknown", 778 | "orbital_period": "unknown", 779 | "population": "unknown" 780 | }, 781 | "model": "resources.planet", 782 | "pk": 46 783 | }, 784 | { 785 | "fields": { 786 | "edited": "2014-12-20T20:58:18.500Z", 787 | "climate": "arid, rocky, windy", 788 | "surface_water": "unknown", 789 | "name": "Iktotch", 790 | "diameter": "unknown", 791 | "rotation_period": "22", 792 | "created": "2014-12-20T10:31:32.413Z", 793 | "terrain": "rocky", 794 | "gravity": "1", 795 | "orbital_period": "481", 796 | "population": "unknown" 797 | }, 798 | "model": "resources.planet", 799 | "pk": 47 800 | }, 801 | { 802 | "fields": { 803 | "edited": "2014-12-20T20:58:18.502Z", 804 | "climate": "unknown", 805 | "surface_water": "unknown", 806 | "name": "Quermia", 807 | "diameter": "unknown", 808 | "rotation_period": "unknown", 809 | "created": "2014-12-20T10:34:08.249Z", 810 | "terrain": "unknown", 811 | "gravity": "unknown", 812 | "orbital_period": "unknown", 813 | "population": "unknown" 814 | }, 815 | "model": "resources.planet", 816 | "pk": 48 817 | }, 818 | { 819 | "fields": { 820 | "edited": "2014-12-20T20:58:18.504Z", 821 | "climate": "temperate", 822 | "surface_water": "unknown", 823 | "name": "Dorin", 824 | "diameter": "13400", 825 | "rotation_period": "22", 826 | "created": "2014-12-20T10:48:36.141Z", 827 | "terrain": "unknown", 828 | "gravity": "1", 829 | "orbital_period": "409", 830 | "population": "unknown" 831 | }, 832 | "model": "resources.planet", 833 | "pk": 49 834 | }, 835 | { 836 | "fields": { 837 | "edited": "2014-12-20T20:58:18.506Z", 838 | "climate": "temperate", 839 | "surface_water": "unknown", 840 | "name": "Champala", 841 | "diameter": "unknown", 842 | "rotation_period": "27", 843 | "created": "2014-12-20T10:52:51.524Z", 844 | "terrain": "oceans, rainforests, plateaus", 845 | "gravity": "1", 846 | "orbital_period": "318", 847 | "population": "3500000000" 848 | }, 849 | "model": "resources.planet", 850 | "pk": 50 851 | }, 852 | { 853 | "fields": { 854 | "edited": "2014-12-20T20:58:18.508Z", 855 | "climate": "unknown", 856 | "surface_water": "unknown", 857 | "name": "Mirial", 858 | "diameter": "unknown", 859 | "rotation_period": "unknown", 860 | "created": "2014-12-20T16:44:46.318Z", 861 | "terrain": "deserts", 862 | "gravity": "unknown", 863 | "orbital_period": "unknown", 864 | "population": "unknown" 865 | }, 866 | "model": "resources.planet", 867 | "pk": 51 868 | }, 869 | { 870 | "fields": { 871 | "edited": "2014-12-20T20:58:18.510Z", 872 | "climate": "unknown", 873 | "surface_water": "unknown", 874 | "name": "Serenno", 875 | "diameter": "unknown", 876 | "rotation_period": "unknown", 877 | "created": "2014-12-20T16:52:13.357Z", 878 | "terrain": "rainforests, rivers, mountains", 879 | "gravity": "unknown", 880 | "orbital_period": "unknown", 881 | "population": "unknown" 882 | }, 883 | "model": "resources.planet", 884 | "pk": 52 885 | }, 886 | { 887 | "fields": { 888 | "edited": "2014-12-20T20:58:18.512Z", 889 | "climate": "unknown", 890 | "surface_water": "unknown", 891 | "name": "Concord Dawn", 892 | "diameter": "unknown", 893 | "rotation_period": "unknown", 894 | "created": "2014-12-20T16:54:39.909Z", 895 | "terrain": "jungles, forests, deserts", 896 | "gravity": "unknown", 897 | "orbital_period": "unknown", 898 | "population": "unknown" 899 | }, 900 | "model": "resources.planet", 901 | "pk": 53 902 | }, 903 | { 904 | "fields": { 905 | "edited": "2014-12-20T20:58:18.514Z", 906 | "climate": "unknown", 907 | "surface_water": "unknown", 908 | "name": "Zolan", 909 | "diameter": "unknown", 910 | "rotation_period": "unknown", 911 | "created": "2014-12-20T16:56:37.250Z", 912 | "terrain": "unknown", 913 | "gravity": "unknown", 914 | "orbital_period": "unknown", 915 | "population": "unknown" 916 | }, 917 | "model": "resources.planet", 918 | "pk": 54 919 | }, 920 | { 921 | "fields": { 922 | "edited": "2014-12-20T20:58:18.516Z", 923 | "climate": "frigid", 924 | "surface_water": "100", 925 | "name": "Ojom", 926 | "diameter": "unknown", 927 | "rotation_period": "unknown", 928 | "created": "2014-12-20T17:27:41.286Z", 929 | "terrain": "oceans, glaciers", 930 | "gravity": "unknown", 931 | "orbital_period": "unknown", 932 | "population": "500000000" 933 | }, 934 | "model": "resources.planet", 935 | "pk": 55 936 | }, 937 | { 938 | "fields": { 939 | "edited": "2014-12-20T20:58:18.517Z", 940 | "climate": "temperate", 941 | "surface_water": "unknown", 942 | "name": "Skako", 943 | "diameter": "unknown", 944 | "rotation_period": "27", 945 | "created": "2014-12-20T17:50:47.864Z", 946 | "terrain": "urban, vines", 947 | "gravity": "1", 948 | "orbital_period": "384", 949 | "population": "500000000000" 950 | }, 951 | "model": "resources.planet", 952 | "pk": 56 953 | }, 954 | { 955 | "fields": { 956 | "edited": "2014-12-20T20:58:18.519Z", 957 | "climate": "temperate", 958 | "surface_water": "25", 959 | "name": "Muunilinst", 960 | "diameter": "13800", 961 | "rotation_period": "28", 962 | "created": "2014-12-20T17:57:47.420Z", 963 | "terrain": "plains, forests, hills, mountains", 964 | "gravity": "1", 965 | "orbital_period": "412", 966 | "population": "5000000000" 967 | }, 968 | "model": "resources.planet", 969 | "pk": 57 970 | }, 971 | { 972 | "fields": { 973 | "edited": "2014-12-20T20:58:18.521Z", 974 | "climate": "temperate", 975 | "surface_water": "unknown", 976 | "name": "Shili", 977 | "diameter": "unknown", 978 | "rotation_period": "unknown", 979 | "created": "2014-12-20T18:43:14.049Z", 980 | "terrain": "cities, savannahs, seas, plains", 981 | "gravity": "1", 982 | "orbital_period": "unknown", 983 | "population": "unknown" 984 | }, 985 | "model": "resources.planet", 986 | "pk": 58 987 | }, 988 | { 989 | "fields": { 990 | "edited": "2014-12-20T20:58:18.523Z", 991 | "climate": "arid, temperate, tropical", 992 | "surface_water": "unknown", 993 | "name": "Kalee", 994 | "diameter": "13850", 995 | "rotation_period": "23", 996 | "created": "2014-12-20T19:43:51.278Z", 997 | "terrain": "rainforests, cliffs, canyons, seas", 998 | "gravity": "1", 999 | "orbital_period": "378", 1000 | "population": "4000000000" 1001 | }, 1002 | "model": "resources.planet", 1003 | "pk": 59 1004 | }, 1005 | { 1006 | "fields": { 1007 | "edited": "2014-12-20T20:58:18.525Z", 1008 | "climate": "unknown", 1009 | "surface_water": "unknown", 1010 | "name": "Umbara", 1011 | "diameter": "unknown", 1012 | "rotation_period": "unknown", 1013 | "created": "2014-12-20T20:18:36.256Z", 1014 | "terrain": "unknown", 1015 | "gravity": "unknown", 1016 | "orbital_period": "unknown", 1017 | "population": "unknown" 1018 | }, 1019 | "model": "resources.planet", 1020 | "pk": 60 1021 | } 1022 | ] 1023 | -------------------------------------------------------------------------------- /resources/fixtures/species.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "fields": { 4 | "edited": "2014-12-20T21:36:42.136Z", 5 | "classification": "mammal", 6 | "name": "Human", 7 | "designation": "sentient", 8 | "created": "2014-12-10T13:52:11.567Z", 9 | "eye_colors": "brown, blue, green, hazel, grey, amber", 10 | "people": [ 11 | 1, 4, 5, 6, 7, 9, 10, 11, 12, 12 | 14, 18, 19, 21, 22, 25, 26, 28, 13 | 29, 32, 34, 35, 39, 42, 43, 51, 14 | 60, 61, 62, 66, 67, 68, 69, 74, 15 | 81, 82 16 | ], 17 | "skin_colors": "caucasian, black, asian, hispanic", 18 | "language": "Galactic Basic", 19 | "hair_colors": "blonde, brown, black, red", 20 | "homeworld": 9, 21 | "average_lifespan": "120", 22 | "average_height": "180" 23 | }, 24 | "model": "resources.species", 25 | "pk": 1 26 | }, 27 | { 28 | "fields": { 29 | "edited": "2014-12-20T21:36:42.139Z", 30 | "classification": "artificial", 31 | "name": "Droid", 32 | "designation": "sentient", 33 | "created": "2014-12-10T15:16:16.259Z", 34 | "eye_colors": "n/a", 35 | "people": [ 36 | 2, 37 | 3, 38 | 8, 39 | 23 40 | ], 41 | "skin_colors": "n/a", 42 | "language": "n/a", 43 | "hair_colors": "n/a", 44 | "homeworld": null, 45 | "average_lifespan": "indefinite", 46 | "average_height": "n/a" 47 | }, 48 | "model": "resources.species", 49 | "pk": 2 50 | }, 51 | { 52 | "fields": { 53 | "edited": "2014-12-20T21:36:42.142Z", 54 | "classification": "mammal", 55 | "name": "Wookie", 56 | "designation": "sentient", 57 | "created": "2014-12-10T16:44:31.486Z", 58 | "eye_colors": "blue, green, yellow, brown, golden, red", 59 | "people": [ 60 | 13, 61 | 80 62 | ], 63 | "skin_colors": "gray", 64 | "language": "Shyriiwook", 65 | "hair_colors": "black, brown", 66 | "homeworld": 14, 67 | "average_lifespan": "400", 68 | "average_height": "210" 69 | }, 70 | "model": "resources.species", 71 | "pk": 3 72 | }, 73 | { 74 | "fields": { 75 | "edited": "2014-12-20T21:36:42.144Z", 76 | "classification": "sentient", 77 | "name": "Rodian", 78 | "designation": "reptilian", 79 | "created": "2014-12-10T17:05:26.471Z", 80 | "eye_colors": "black", 81 | "people": [ 82 | 15 83 | ], 84 | "skin_colors": "green, blue", 85 | "language": "Galatic Basic", 86 | "hair_colors": "n/a", 87 | "homeworld": 23, 88 | "average_lifespan": "unknown", 89 | "average_height": "170" 90 | }, 91 | "model": "resources.species", 92 | "pk": 4 93 | }, 94 | { 95 | "fields": { 96 | "edited": "2014-12-20T21:36:42.146Z", 97 | "classification": "gastropod", 98 | "name": "Hutt", 99 | "designation": "sentient", 100 | "created": "2014-12-10T17:12:50.410Z", 101 | "eye_colors": "yellow, red", 102 | "people": [ 103 | 16 104 | ], 105 | "skin_colors": "green, brown, tan", 106 | "language": "Huttese", 107 | "hair_colors": "n/a", 108 | "homeworld": 24, 109 | "average_lifespan": "1000", 110 | "average_height": "300" 111 | }, 112 | "model": "resources.species", 113 | "pk": 5 114 | }, 115 | { 116 | "fields": { 117 | "edited": "2014-12-20T21:36:42.148Z", 118 | "classification": "mammal", 119 | "name": "Yoda's species", 120 | "designation": "sentient", 121 | "created": "2014-12-15T12:27:22.877Z", 122 | "eye_colors": "brown, green, yellow", 123 | "people": [ 124 | 20 125 | ], 126 | "skin_colors": "green, yellow", 127 | "language": "Galactic basic", 128 | "hair_colors": "brown, white", 129 | "homeworld": 28, 130 | "average_lifespan": "900", 131 | "average_height": "66" 132 | }, 133 | "model": "resources.species", 134 | "pk": 6 135 | }, 136 | { 137 | "fields": { 138 | "edited": "2014-12-20T21:36:42.151Z", 139 | "classification": "reptile", 140 | "name": "Trandoshan", 141 | "designation": "sentient", 142 | "created": "2014-12-15T13:07:47.704Z", 143 | "eye_colors": "yellow, orange", 144 | "people": [ 145 | 24 146 | ], 147 | "skin_colors": "brown, green", 148 | "language": "Dosh", 149 | "hair_colors": "none", 150 | "homeworld": 29, 151 | "average_lifespan": "unknown", 152 | "average_height": "200" 153 | }, 154 | "model": "resources.species", 155 | "pk": 7 156 | }, 157 | { 158 | "fields": { 159 | "edited": "2014-12-20T21:36:42.153Z", 160 | "classification": "amphibian", 161 | "name": "Mon Calamari", 162 | "designation": "sentient", 163 | "created": "2014-12-18T11:09:52.263Z", 164 | "eye_colors": "yellow", 165 | "people": [ 166 | 27 167 | ], 168 | "skin_colors": "red, blue, brown, magenta", 169 | "language": "Mon Calamarian", 170 | "hair_colors": "none", 171 | "homeworld": 31, 172 | "average_lifespan": "unknown", 173 | "average_height": "160" 174 | }, 175 | "model": "resources.species", 176 | "pk": 8 177 | }, 178 | { 179 | "fields": { 180 | "edited": "2014-12-20T21:36:42.155Z", 181 | "classification": "mammal", 182 | "name": "Ewok", 183 | "designation": "sentient", 184 | "created": "2014-12-18T11:22:00.285Z", 185 | "eye_colors": "orange, brown", 186 | "people": [ 187 | 30 188 | ], 189 | "skin_colors": "brown", 190 | "language": "Ewokese", 191 | "hair_colors": "white, brown, black", 192 | "homeworld": 7, 193 | "average_lifespan": "unknown", 194 | "average_height": "100" 195 | }, 196 | "model": "resources.species", 197 | "pk": 9 198 | }, 199 | { 200 | "fields": { 201 | "edited": "2014-12-20T21:36:42.157Z", 202 | "classification": "mammal", 203 | "name": "Sullustan", 204 | "designation": "sentient", 205 | "created": "2014-12-18T11:26:20.103Z", 206 | "eye_colors": "black", 207 | "people": [ 208 | 31 209 | ], 210 | "skin_colors": "pale", 211 | "language": "Sullutese", 212 | "hair_colors": "none", 213 | "homeworld": 33, 214 | "average_lifespan": "unknown", 215 | "average_height": "180" 216 | }, 217 | "model": "resources.species", 218 | "pk": 10 219 | }, 220 | { 221 | "fields": { 222 | "edited": "2014-12-20T21:36:42.160Z", 223 | "classification": "unknown", 224 | "name": "Neimodian", 225 | "designation": "sentient", 226 | "created": "2014-12-19T17:07:31.319Z", 227 | "eye_colors": "red, pink", 228 | "people": [ 229 | 33 230 | ], 231 | "skin_colors": "grey, green", 232 | "language": "Neimoidia", 233 | "hair_colors": "none", 234 | "homeworld": 18, 235 | "average_lifespan": "unknown", 236 | "average_height": "180" 237 | }, 238 | "model": "resources.species", 239 | "pk": 11 240 | }, 241 | { 242 | "fields": { 243 | "edited": "2014-12-20T21:36:42.163Z", 244 | "classification": "amphibian", 245 | "name": "Gungan", 246 | "designation": "sentient", 247 | "created": "2014-12-19T17:30:37.341Z", 248 | "eye_colors": "orange", 249 | "people": [ 250 | 36, 251 | 37, 252 | 38 253 | ], 254 | "skin_colors": "brown, green", 255 | "language": "Gungan basic", 256 | "hair_colors": "none", 257 | "homeworld": 8, 258 | "average_lifespan": "unknown", 259 | "average_height": "190" 260 | }, 261 | "model": "resources.species", 262 | "pk": 12 263 | }, 264 | { 265 | "fields": { 266 | "edited": "2014-12-20T21:36:42.165Z", 267 | "classification": "mammal", 268 | "name": "Toydarian", 269 | "designation": "sentient", 270 | "created": "2014-12-19T17:48:56.893Z", 271 | "eye_colors": "yellow", 272 | "people": [ 273 | 40 274 | ], 275 | "skin_colors": "blue, green, grey", 276 | "language": "Toydarian", 277 | "hair_colors": "none", 278 | "homeworld": 34, 279 | "average_lifespan": "91", 280 | "average_height": "120" 281 | }, 282 | "model": "resources.species", 283 | "pk": 13 284 | }, 285 | { 286 | "fields": { 287 | "edited": "2014-12-20T21:36:42.167Z", 288 | "classification": "mammal", 289 | "name": "Dug", 290 | "designation": "sentient", 291 | "created": "2014-12-19T17:53:11.214Z", 292 | "eye_colors": "yellow, blue", 293 | "people": [ 294 | 41 295 | ], 296 | "skin_colors": "brown, purple, grey, red", 297 | "language": "Dugese", 298 | "hair_colors": "none", 299 | "homeworld": 35, 300 | "average_lifespan": "unknown", 301 | "average_height": "100" 302 | }, 303 | "model": "resources.species", 304 | "pk": 14 305 | }, 306 | { 307 | "fields": { 308 | "edited": "2014-12-20T21:36:42.169Z", 309 | "classification": "mammals", 310 | "name": "Twi'lek", 311 | "designation": "sentient", 312 | "created": "2014-12-20T09:48:02.406Z", 313 | "eye_colors": "blue, brown, orange, pink", 314 | "people": [ 315 | 45, 316 | 46 317 | ], 318 | "skin_colors": "orange, yellow, blue, green, pink, purple, tan", 319 | "language": "Twi'leki", 320 | "hair_colors": "none", 321 | "homeworld": 37, 322 | "average_lifespan": "unknown", 323 | "average_height": "200" 324 | }, 325 | "model": "resources.species", 326 | "pk": 15 327 | }, 328 | { 329 | "fields": { 330 | "edited": "2014-12-20T21:36:42.171Z", 331 | "classification": "reptile", 332 | "name": "Aleena", 333 | "designation": "sentient", 334 | "created": "2014-12-20T09:53:16.481Z", 335 | "eye_colors": "unknown", 336 | "people": [ 337 | 47 338 | ], 339 | "skin_colors": "blue, gray", 340 | "language": "Aleena", 341 | "hair_colors": "none", 342 | "homeworld": 38, 343 | "average_lifespan": "79", 344 | "average_height": "80" 345 | }, 346 | "model": "resources.species", 347 | "pk": 16 348 | }, 349 | { 350 | "fields": { 351 | "edited": "2014-12-20T21:36:42.173Z", 352 | "classification": "unknown", 353 | "name": "Vulptereen", 354 | "designation": "sentient", 355 | "created": "2014-12-20T09:57:33.128Z", 356 | "eye_colors": "yellow", 357 | "people": [ 358 | 48 359 | ], 360 | "skin_colors": "grey", 361 | "language": "vulpterish", 362 | "hair_colors": "none", 363 | "homeworld": 39, 364 | "average_lifespan": "unknown", 365 | "average_height": "100" 366 | }, 367 | "model": "resources.species", 368 | "pk": 17 369 | }, 370 | { 371 | "fields": { 372 | "edited": "2014-12-20T21:36:42.175Z", 373 | "classification": "unknown", 374 | "name": "Xexto", 375 | "designation": "sentient", 376 | "created": "2014-12-20T10:02:13.915Z", 377 | "eye_colors": "black", 378 | "people": [ 379 | 49 380 | ], 381 | "skin_colors": "grey, yellow, purple", 382 | "language": "Xextese", 383 | "hair_colors": "none", 384 | "homeworld": 40, 385 | "average_lifespan": "unknown", 386 | "average_height": "125" 387 | }, 388 | "model": "resources.species", 389 | "pk": 18 390 | }, 391 | { 392 | "fields": { 393 | "edited": "2014-12-20T21:36:42.177Z", 394 | "classification": "unknown", 395 | "name": "Toong", 396 | "designation": "sentient", 397 | "created": "2014-12-20T10:08:36.795Z", 398 | "eye_colors": "orange", 399 | "people": [ 400 | 50 401 | ], 402 | "skin_colors": "grey, green, yellow", 403 | "language": "Tundan", 404 | "hair_colors": "none", 405 | "homeworld": 41, 406 | "average_lifespan": "unknown", 407 | "average_height": "200" 408 | }, 409 | "model": "resources.species", 410 | "pk": 19 411 | }, 412 | { 413 | "fields": { 414 | "edited": "2014-12-20T21:36:42.179Z", 415 | "classification": "mammal", 416 | "name": "Cerean", 417 | "designation": "sentient", 418 | "created": "2014-12-20T10:15:33.765Z", 419 | "eye_colors": "hazel", 420 | "people": [ 421 | 52 422 | ], 423 | "skin_colors": "pale pink", 424 | "language": "Cerean", 425 | "hair_colors": "red, blond, black, white", 426 | "homeworld": 43, 427 | "average_lifespan": "unknown", 428 | "average_height": "200" 429 | }, 430 | "model": "resources.species", 431 | "pk": 20 432 | }, 433 | { 434 | "fields": { 435 | "edited": "2014-12-20T21:36:42.181Z", 436 | "classification": "amphibian", 437 | "name": "Nautolan", 438 | "designation": "sentient", 439 | "created": "2014-12-20T10:18:58.610Z", 440 | "eye_colors": "black", 441 | "people": [ 442 | 53 443 | ], 444 | "skin_colors": "green, blue, brown, red", 445 | "language": "Nautila", 446 | "hair_colors": "none", 447 | "homeworld": 44, 448 | "average_lifespan": "70", 449 | "average_height": "180" 450 | }, 451 | "model": "resources.species", 452 | "pk": 21 453 | }, 454 | { 455 | "fields": { 456 | "edited": "2014-12-20T21:36:42.183Z", 457 | "classification": "mammal", 458 | "name": "Zabrak", 459 | "designation": "sentient", 460 | "created": "2014-12-20T10:26:59.894Z", 461 | "eye_colors": "brown, orange", 462 | "people": [ 463 | 44, 464 | 54 465 | ], 466 | "skin_colors": "pale, brown, red, orange, yellow", 467 | "language": "Zabraki", 468 | "hair_colors": "black", 469 | "homeworld": 45, 470 | "average_lifespan": "unknown", 471 | "average_height": "180" 472 | }, 473 | "model": "resources.species", 474 | "pk": 22 475 | }, 476 | { 477 | "fields": { 478 | "edited": "2014-12-20T21:36:42.186Z", 479 | "classification": "mammal", 480 | "name": "Tholothian", 481 | "designation": "sentient", 482 | "created": "2014-12-20T10:29:13.798Z", 483 | "eye_colors": "blue, indigo", 484 | "people": [ 485 | 55 486 | ], 487 | "skin_colors": "dark", 488 | "language": "unknown", 489 | "hair_colors": "unknown", 490 | "homeworld": 46, 491 | "average_lifespan": "unknown", 492 | "average_height": "unknown" 493 | }, 494 | "model": "resources.species", 495 | "pk": 23 496 | }, 497 | { 498 | "fields": { 499 | "edited": "2014-12-20T21:36:42.188Z", 500 | "classification": "unknown", 501 | "name": "Iktotchi", 502 | "designation": "sentient", 503 | "created": "2014-12-20T10:32:13.046Z", 504 | "eye_colors": "orange", 505 | "people": [ 506 | 56 507 | ], 508 | "skin_colors": "pink", 509 | "language": "Iktotchese", 510 | "hair_colors": "none", 511 | "homeworld": 47, 512 | "average_lifespan": "unknown", 513 | "average_height": "180" 514 | }, 515 | "model": "resources.species", 516 | "pk": 24 517 | }, 518 | { 519 | "fields": { 520 | "edited": "2014-12-20T21:36:42.189Z", 521 | "classification": "mammal", 522 | "name": "Quermian", 523 | "designation": "sentient", 524 | "created": "2014-12-20T10:34:50.827Z", 525 | "eye_colors": "yellow", 526 | "people": [ 527 | 57 528 | ], 529 | "skin_colors": "white", 530 | "language": "Quermian", 531 | "hair_colors": "none", 532 | "homeworld": 48, 533 | "average_lifespan": "86", 534 | "average_height": "240" 535 | }, 536 | "model": "resources.species", 537 | "pk": 25 538 | }, 539 | { 540 | "fields": { 541 | "edited": "2014-12-20T21:36:42.191Z", 542 | "classification": "unknown", 543 | "name": "Kel Dor", 544 | "designation": "sentient", 545 | "created": "2014-12-20T10:49:21.692Z", 546 | "eye_colors": "black, silver", 547 | "people": [ 548 | 58 549 | ], 550 | "skin_colors": "peach, orange, red", 551 | "language": "Kel Dor", 552 | "hair_colors": "none", 553 | "homeworld": 49, 554 | "average_lifespan": "70", 555 | "average_height": "180" 556 | }, 557 | "model": "resources.species", 558 | "pk": 26 559 | }, 560 | { 561 | "fields": { 562 | "edited": "2014-12-20T21:36:42.193Z", 563 | "classification": "amphibian", 564 | "name": "Chagrian", 565 | "designation": "sentient", 566 | "created": "2014-12-20T10:53:28.795Z", 567 | "eye_colors": "blue", 568 | "people": [ 569 | 59 570 | ], 571 | "skin_colors": "blue", 572 | "language": "Chagria", 573 | "hair_colors": "none", 574 | "homeworld": 50, 575 | "average_lifespan": "unknown", 576 | "average_height": "190" 577 | }, 578 | "model": "resources.species", 579 | "pk": 27 580 | }, 581 | { 582 | "fields": { 583 | "edited": "2014-12-20T21:36:42.195Z", 584 | "classification": "insectoid", 585 | "name": "Geonosian", 586 | "designation": "sentient", 587 | "created": "2014-12-20T16:40:45.618Z", 588 | "eye_colors": "green, hazel", 589 | "people": [ 590 | 63 591 | ], 592 | "skin_colors": "green, brown", 593 | "language": "Geonosian", 594 | "hair_colors": "none", 595 | "homeworld": 11, 596 | "average_lifespan": "unknown", 597 | "average_height": "178" 598 | }, 599 | "model": "resources.species", 600 | "pk": 28 601 | }, 602 | { 603 | "fields": { 604 | "edited": "2014-12-20T21:36:42.197Z", 605 | "classification": "mammal", 606 | "name": "Mirialan", 607 | "designation": "sentient", 608 | "created": "2014-12-20T16:46:48.290Z", 609 | "eye_colors": "blue, green, red, yellow, brown, orange", 610 | "people": [ 611 | 64, 612 | 65 613 | ], 614 | "skin_colors": "yellow, green", 615 | "language": "Mirialan", 616 | "hair_colors": "black, brown", 617 | "homeworld": 51, 618 | "average_lifespan": "unknown", 619 | "average_height": "180" 620 | }, 621 | "model": "resources.species", 622 | "pk": 29 623 | }, 624 | { 625 | "fields": { 626 | "edited": "2014-12-20T21:36:42.199Z", 627 | "classification": "reptilian", 628 | "name": "Clawdite", 629 | "designation": "sentient", 630 | "created": "2014-12-20T16:57:46.171Z", 631 | "eye_colors": "yellow", 632 | "people": [ 633 | 70 634 | ], 635 | "skin_colors": "green, yellow", 636 | "language": "Clawdite", 637 | "hair_colors": "none", 638 | "homeworld": 54, 639 | "average_lifespan": "70", 640 | "average_height": "180" 641 | }, 642 | "model": "resources.species", 643 | "pk": 30 644 | }, 645 | { 646 | "fields": { 647 | "edited": "2014-12-20T21:36:42.200Z", 648 | "classification": "amphibian", 649 | "name": "Besalisk", 650 | "designation": "sentient", 651 | "created": "2014-12-20T17:28:28.821Z", 652 | "eye_colors": "yellow", 653 | "people": [ 654 | 71 655 | ], 656 | "skin_colors": "brown", 657 | "language": "besalisk", 658 | "hair_colors": "none", 659 | "homeworld": 55, 660 | "average_lifespan": "75", 661 | "average_height": "178" 662 | }, 663 | "model": "resources.species", 664 | "pk": 31 665 | }, 666 | { 667 | "fields": { 668 | "edited": "2014-12-20T21:36:42.202Z", 669 | "classification": "amphibian", 670 | "name": "Kaminoan", 671 | "designation": "sentient", 672 | "created": "2014-12-20T17:31:24.838Z", 673 | "eye_colors": "black", 674 | "people": [ 675 | 72, 676 | 73 677 | ], 678 | "skin_colors": "grey, blue", 679 | "language": "Kaminoan", 680 | "hair_colors": "none", 681 | "homeworld": 10, 682 | "average_lifespan": "80", 683 | "average_height": "220" 684 | }, 685 | "model": "resources.species", 686 | "pk": 32 687 | }, 688 | { 689 | "fields": { 690 | "edited": "2014-12-20T21:36:42.204Z", 691 | "classification": "mammal", 692 | "name": "Skakoan", 693 | "designation": "sentient", 694 | "created": "2014-12-20T17:53:54.515Z", 695 | "eye_colors": "unknown", 696 | "people": [ 697 | 76 698 | ], 699 | "skin_colors": "grey, green", 700 | "language": "Skakoan", 701 | "hair_colors": "none", 702 | "homeworld": 56, 703 | "average_lifespan": "unknown", 704 | "average_height": "unknown" 705 | }, 706 | "model": "resources.species", 707 | "pk": 33 708 | }, 709 | { 710 | "fields": { 711 | "edited": "2014-12-20T21:36:42.207Z", 712 | "classification": "mammal", 713 | "name": "Muun", 714 | "designation": "sentient", 715 | "created": "2014-12-20T17:58:19.088Z", 716 | "eye_colors": "black", 717 | "people": [ 718 | 77 719 | ], 720 | "skin_colors": "grey, white", 721 | "language": "Muun", 722 | "hair_colors": "none", 723 | "homeworld": 57, 724 | "average_lifespan": "100", 725 | "average_height": "190" 726 | }, 727 | "model": "resources.species", 728 | "pk": 34 729 | }, 730 | { 731 | "fields": { 732 | "edited": "2014-12-20T21:36:42.209Z", 733 | "classification": "mammal", 734 | "name": "Togruta", 735 | "designation": "sentient", 736 | "created": "2014-12-20T18:44:03.246Z", 737 | "eye_colors": "red, orange, yellow, green, blue, black", 738 | "people": [ 739 | 78 740 | ], 741 | "skin_colors": "red, white, orange, yellow, green, blue", 742 | "language": "Togruti", 743 | "hair_colors": "none", 744 | "homeworld": 58, 745 | "average_lifespan": "94", 746 | "average_height": "180" 747 | }, 748 | "model": "resources.species", 749 | "pk": 35 750 | }, 751 | { 752 | "fields": { 753 | "edited": "2014-12-20T21:36:42.210Z", 754 | "classification": "reptile", 755 | "name": "Kaleesh", 756 | "designation": "sentient", 757 | "created": "2014-12-20T19:45:42.537Z", 758 | "eye_colors": "yellow", 759 | "people": [ 760 | 79 761 | ], 762 | "skin_colors": "brown, orange, tan", 763 | "language": "Kaleesh", 764 | "hair_colors": "none", 765 | "homeworld": 59, 766 | "average_lifespan": "80", 767 | "average_height": "170" 768 | }, 769 | "model": "resources.species", 770 | "pk": 36 771 | }, 772 | { 773 | "fields": { 774 | "edited": "2014-12-20T21:36:42.212Z", 775 | "classification": "mammal", 776 | "name": "Pau'an", 777 | "designation": "sentient", 778 | "created": "2014-12-20T20:35:06.777Z", 779 | "eye_colors": "black", 780 | "people": [ 781 | 83 782 | ], 783 | "skin_colors": "grey", 784 | "language": "Utapese", 785 | "hair_colors": "none", 786 | "homeworld": 12, 787 | "average_lifespan": "700", 788 | "average_height": "190" 789 | }, 790 | "model": "resources.species", 791 | "pk": 37 792 | } 793 | ] 794 | -------------------------------------------------------------------------------- /resources/fixtures/starships.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "fields": { 4 | "pilots": [], 5 | "MGLT": "60", 6 | "starship_class": "corvette", 7 | "hyperdrive_rating": "2.0" 8 | }, 9 | "model": "resources.starship", 10 | "pk": 2 11 | }, 12 | { 13 | "fields": { 14 | "pilots": [], 15 | "MGLT": "60", 16 | "starship_class": "Star Destroyer", 17 | "hyperdrive_rating": "2.0" 18 | }, 19 | "model": "resources.starship", 20 | "pk": 3 21 | }, 22 | { 23 | "fields": { 24 | "pilots": [], 25 | "MGLT": "70", 26 | "starship_class": "landing craft", 27 | "hyperdrive_rating": "1.0" 28 | }, 29 | "model": "resources.starship", 30 | "pk": 5 31 | }, 32 | { 33 | "fields": { 34 | "pilots": [], 35 | "MGLT": "10", 36 | "starship_class": "Deep Space Mobile Battlestation", 37 | "hyperdrive_rating": "4.0" 38 | }, 39 | "model": "resources.starship", 40 | "pk": 9 41 | }, 42 | { 43 | "fields": { 44 | "pilots": [ 45 | 13, 46 | 14, 47 | 25, 48 | 31 49 | ], 50 | "MGLT": "75", 51 | "starship_class": "Light freighter", 52 | "hyperdrive_rating": "0.5" 53 | }, 54 | "model": "resources.starship", 55 | "pk": 10 56 | }, 57 | { 58 | "fields": { 59 | "pilots": [], 60 | "MGLT": "80", 61 | "starship_class": "assault starfighter", 62 | "hyperdrive_rating": "1.0" 63 | }, 64 | "model": "resources.starship", 65 | "pk": 11 66 | }, 67 | { 68 | "fields": { 69 | "pilots": [ 70 | 1, 71 | 9, 72 | 18, 73 | 19 74 | ], 75 | "MGLT": "100", 76 | "starship_class": "Starfighter", 77 | "hyperdrive_rating": "1.0" 78 | }, 79 | "model": "resources.starship", 80 | "pk": 12 81 | }, 82 | { 83 | "fields": { 84 | "pilots": [ 85 | 4 86 | ], 87 | "MGLT": "105", 88 | "starship_class": "Starfighter", 89 | "hyperdrive_rating": "1.0" 90 | }, 91 | "model": "resources.starship", 92 | "pk": 13 93 | }, 94 | { 95 | "fields": { 96 | "pilots": [], 97 | "MGLT": "40", 98 | "starship_class": "Star dreadnought", 99 | "hyperdrive_rating": "2.0" 100 | }, 101 | "model": "resources.starship", 102 | "pk": 15 103 | }, 104 | { 105 | "fields": { 106 | "pilots": [], 107 | "MGLT": "20", 108 | "starship_class": "Medium transport", 109 | "hyperdrive_rating": "4.0" 110 | }, 111 | "model": "resources.starship", 112 | "pk": 17 113 | }, 114 | { 115 | "fields": { 116 | "pilots": [ 117 | 22 118 | ], 119 | "MGLT": "70", 120 | "starship_class": "Patrol craft", 121 | "hyperdrive_rating": "3.0" 122 | }, 123 | "model": "resources.starship", 124 | "pk": 21 125 | }, 126 | { 127 | "fields": { 128 | "pilots": [ 129 | 1, 130 | 13, 131 | 14 132 | ], 133 | "MGLT": "50", 134 | "starship_class": "Armed government transport", 135 | "hyperdrive_rating": "1.0" 136 | }, 137 | "model": "resources.starship", 138 | "pk": 22 139 | }, 140 | { 141 | "fields": { 142 | "pilots": [], 143 | "MGLT": "40", 144 | "starship_class": "Escort ship", 145 | "hyperdrive_rating": "2.0" 146 | }, 147 | "model": "resources.starship", 148 | "pk": 23 149 | }, 150 | { 151 | "fields": { 152 | "pilots": [], 153 | "MGLT": "60", 154 | "starship_class": "Star Cruiser", 155 | "hyperdrive_rating": "1.0" 156 | }, 157 | "model": "resources.starship", 158 | "pk": 27 159 | }, 160 | { 161 | "fields": { 162 | "pilots": [ 163 | 29 164 | ], 165 | "MGLT": "120", 166 | "starship_class": "Starfighter", 167 | "hyperdrive_rating": "1.0" 168 | }, 169 | "model": "resources.starship", 170 | "pk": 28 171 | }, 172 | { 173 | "fields": { 174 | "pilots": [], 175 | "MGLT": "91", 176 | "starship_class": "Assault Starfighter", 177 | "hyperdrive_rating": "2.0" 178 | }, 179 | "model": "resources.starship", 180 | "pk": 29 181 | }, 182 | { 183 | "fields": { 184 | "pilots": [], 185 | "MGLT": "unknown", 186 | "starship_class": "Space cruiser", 187 | "hyperdrive_rating": "2.0" 188 | }, 189 | "model": "resources.starship", 190 | "pk": 31 191 | }, 192 | { 193 | "fields": { 194 | "pilots": [], 195 | "MGLT": "unknown", 196 | "starship_class": "Droid control ship", 197 | "hyperdrive_rating": "2.0" 198 | }, 199 | "model": "resources.starship", 200 | "pk": 32 201 | }, 202 | { 203 | "fields": { 204 | "pilots": [ 205 | 11, 206 | 35, 207 | 60 208 | ], 209 | "MGLT": "unknown", 210 | "starship_class": "Starfighter", 211 | "hyperdrive_rating": "1.0" 212 | }, 213 | "model": "resources.starship", 214 | "pk": 39 215 | }, 216 | { 217 | "fields": { 218 | "pilots": [ 219 | 39 220 | ], 221 | "MGLT": "unknown", 222 | "starship_class": "yacht", 223 | "hyperdrive_rating": "1.8" 224 | }, 225 | "model": "resources.starship", 226 | "pk": 40 227 | }, 228 | { 229 | "fields": { 230 | "pilots": [ 231 | 44 232 | ], 233 | "MGLT": "unknown", 234 | "starship_class": "Space Transport", 235 | "hyperdrive_rating": "1.5" 236 | }, 237 | "model": "resources.starship", 238 | "pk": 41 239 | }, 240 | { 241 | "fields": { 242 | "pilots": [], 243 | "MGLT": "unknown", 244 | "starship_class": "Diplomatic barge", 245 | "hyperdrive_rating": "0.7" 246 | }, 247 | "model": "resources.starship", 248 | "pk": 43 249 | }, 250 | { 251 | "fields": { 252 | "pilots": [], 253 | "MGLT": "unknown", 254 | "starship_class": "freighter", 255 | "hyperdrive_rating": "unknown" 256 | }, 257 | "model": "resources.starship", 258 | "pk": 47 259 | }, 260 | { 261 | "fields": { 262 | "pilots": [ 263 | 10, 264 | 58 265 | ], 266 | "MGLT": "unknown", 267 | "starship_class": "Starfighter", 268 | "hyperdrive_rating": "1.0" 269 | }, 270 | "model": "resources.starship", 271 | "pk": 48 272 | }, 273 | { 274 | "fields": { 275 | "pilots": [ 276 | 35 277 | ], 278 | "MGLT": "unknown", 279 | "starship_class": "yacht", 280 | "hyperdrive_rating": "0.9" 281 | }, 282 | "model": "resources.starship", 283 | "pk": 49 284 | }, 285 | { 286 | "fields": { 287 | "pilots": [], 288 | "MGLT": "unknown", 289 | "starship_class": "assault ship", 290 | "hyperdrive_rating": "0.6" 291 | }, 292 | "model": "resources.starship", 293 | "pk": 52 294 | }, 295 | { 296 | "fields": { 297 | "pilots": [], 298 | "MGLT": "unknown", 299 | "starship_class": "yacht", 300 | "hyperdrive_rating": "1.5" 301 | }, 302 | "model": "resources.starship", 303 | "pk": 58 304 | }, 305 | { 306 | "fields": { 307 | "pilots": [ 308 | 10, 309 | 11 310 | ], 311 | "MGLT": "unknown", 312 | "starship_class": "capital ship", 313 | "hyperdrive_rating": "1.5" 314 | }, 315 | "model": "resources.starship", 316 | "pk": 59 317 | }, 318 | { 319 | "fields": { 320 | "pilots": [], 321 | "MGLT": "unknown", 322 | "starship_class": "transport", 323 | "hyperdrive_rating": "1.0" 324 | }, 325 | "model": "resources.starship", 326 | "pk": 61 327 | }, 328 | { 329 | "fields": { 330 | "pilots": [], 331 | "MGLT": "unknown", 332 | "starship_class": "star destroyer", 333 | "hyperdrive_rating": "1.0" 334 | }, 335 | "model": "resources.starship", 336 | "pk": 63 337 | }, 338 | { 339 | "fields": { 340 | "pilots": [ 341 | 10, 342 | 35 343 | ], 344 | "MGLT": "unknown", 345 | "starship_class": "yacht", 346 | "hyperdrive_rating": "0.5" 347 | }, 348 | "model": "resources.starship", 349 | "pk": 64 350 | }, 351 | { 352 | "fields": { 353 | "pilots": [ 354 | 10, 355 | 11 356 | ], 357 | "MGLT": "unknown", 358 | "starship_class": "starfighter", 359 | "hyperdrive_rating": "1.0" 360 | }, 361 | "model": "resources.starship", 362 | "pk": 65 363 | }, 364 | { 365 | "fields": { 366 | "pilots": [], 367 | "MGLT": "100", 368 | "starship_class": "starfighter", 369 | "hyperdrive_rating": "1.0" 370 | }, 371 | "model": "resources.starship", 372 | "pk": 66 373 | }, 374 | { 375 | "fields": { 376 | "pilots": [], 377 | "MGLT": "unknown", 378 | "starship_class": "cruiser", 379 | "hyperdrive_rating": "1.0" 380 | }, 381 | "model": "resources.starship", 382 | "pk": 68 383 | }, 384 | { 385 | "fields": { 386 | "pilots": [ 387 | 10, 388 | 79 389 | ], 390 | "MGLT": "unknown", 391 | "starship_class": "starfighter", 392 | "hyperdrive_rating": "6" 393 | }, 394 | "model": "resources.starship", 395 | "pk": 74 396 | }, 397 | { 398 | "fields": { 399 | "pilots": [], 400 | "MGLT": "unknown", 401 | "starship_class": "starfighter", 402 | "hyperdrive_rating": "1.0" 403 | }, 404 | "model": "resources.starship", 405 | "pk": 75 406 | } 407 | ] 408 | -------------------------------------------------------------------------------- /resources/fixtures/vehicles.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "fields": { 4 | "vehicle_class": "wheeled", 5 | "pilots": [] 6 | }, 7 | "model": "resources.vehicle", 8 | "pk": 4 9 | }, 10 | { 11 | "fields": { 12 | "vehicle_class": "repulsorcraft", 13 | "pilots": [] 14 | }, 15 | "model": "resources.vehicle", 16 | "pk": 6 17 | }, 18 | { 19 | "fields": { 20 | "vehicle_class": "repulsorcraft", 21 | "pilots": [] 22 | }, 23 | "model": "resources.vehicle", 24 | "pk": 7 25 | }, 26 | { 27 | "fields": { 28 | "vehicle_class": "starfighter", 29 | "pilots": [] 30 | }, 31 | "model": "resources.vehicle", 32 | "pk": 8 33 | }, 34 | { 35 | "fields": { 36 | "vehicle_class": "airspeeder", 37 | "pilots": [ 38 | 1, 39 | 18 40 | ] 41 | }, 42 | "model": "resources.vehicle", 43 | "pk": 14 44 | }, 45 | { 46 | "fields": { 47 | "vehicle_class": "space/planetary bomber", 48 | "pilots": [] 49 | }, 50 | "model": "resources.vehicle", 51 | "pk": 16 52 | }, 53 | { 54 | "fields": { 55 | "vehicle_class": "assault walker", 56 | "pilots": [] 57 | }, 58 | "model": "resources.vehicle", 59 | "pk": 18 60 | }, 61 | { 62 | "fields": { 63 | "vehicle_class": "walker", 64 | "pilots": [ 65 | 13 66 | ] 67 | }, 68 | "model": "resources.vehicle", 69 | "pk": 19 70 | }, 71 | { 72 | "fields": { 73 | "vehicle_class": "repulsorcraft", 74 | "pilots": [] 75 | }, 76 | "model": "resources.vehicle", 77 | "pk": 20 78 | }, 79 | { 80 | "fields": { 81 | "vehicle_class": "sail barge", 82 | "pilots": [] 83 | }, 84 | "model": "resources.vehicle", 85 | "pk": 24 86 | }, 87 | { 88 | "fields": { 89 | "vehicle_class": "repulsorcraft cargo skiff", 90 | "pilots": [] 91 | }, 92 | "model": "resources.vehicle", 93 | "pk": 25 94 | }, 95 | { 96 | "fields": { 97 | "vehicle_class": "starfighter", 98 | "pilots": [] 99 | }, 100 | "model": "resources.vehicle", 101 | "pk": 26 102 | }, 103 | { 104 | "fields": { 105 | "vehicle_class": "speeder", 106 | "pilots": [ 107 | 1, 108 | 5 109 | ] 110 | }, 111 | "model": "resources.vehicle", 112 | "pk": 30 113 | }, 114 | { 115 | "fields": { 116 | "vehicle_class": "starfighter", 117 | "pilots": [] 118 | }, 119 | "model": "resources.vehicle", 120 | "pk": 33 121 | }, 122 | { 123 | "fields": { 124 | "vehicle_class": "repulsorcraft", 125 | "pilots": [] 126 | }, 127 | "model": "resources.vehicle", 128 | "pk": 34 129 | }, 130 | { 131 | "fields": { 132 | "vehicle_class": "repulsorcraft", 133 | "pilots": [] 134 | }, 135 | "model": "resources.vehicle", 136 | "pk": 35 137 | }, 138 | { 139 | "fields": { 140 | "vehicle_class": "repulsorcraft", 141 | "pilots": [] 142 | }, 143 | "model": "resources.vehicle", 144 | "pk": 36 145 | }, 146 | { 147 | "fields": { 148 | "vehicle_class": "landing craft", 149 | "pilots": [] 150 | }, 151 | "model": "resources.vehicle", 152 | "pk": 37 153 | }, 154 | { 155 | "fields": { 156 | "vehicle_class": "submarine", 157 | "pilots": [ 158 | 10, 159 | 32 160 | ] 161 | }, 162 | "model": "resources.vehicle", 163 | "pk": 38 164 | }, 165 | { 166 | "fields": { 167 | "vehicle_class": "speeder", 168 | "pilots": [ 169 | 44 170 | ] 171 | }, 172 | "model": "resources.vehicle", 173 | "pk": 42 174 | }, 175 | { 176 | "fields": { 177 | "vehicle_class": "repulsorcraft", 178 | "pilots": [ 179 | 11 180 | ] 181 | }, 182 | "model": "resources.vehicle", 183 | "pk": 44 184 | }, 185 | { 186 | "fields": { 187 | "vehicle_class": "airspeeder", 188 | "pilots": [ 189 | 70 190 | ] 191 | }, 192 | "model": "resources.vehicle", 193 | "pk": 45 194 | }, 195 | { 196 | "fields": { 197 | "vehicle_class": "airspeeder", 198 | "pilots": [ 199 | 11 200 | ] 201 | }, 202 | "model": "resources.vehicle", 203 | "pk": 46 204 | }, 205 | { 206 | "fields": { 207 | "vehicle_class": "gunship", 208 | "pilots": [] 209 | }, 210 | "model": "resources.vehicle", 211 | "pk": 50 212 | }, 213 | { 214 | "fields": { 215 | "vehicle_class": "gunship", 216 | "pilots": [] 217 | }, 218 | "model": "resources.vehicle", 219 | "pk": 51 220 | }, 221 | { 222 | "fields": { 223 | "vehicle_class": "walker", 224 | "pilots": [] 225 | }, 226 | "model": "resources.vehicle", 227 | "pk": 53 228 | }, 229 | { 230 | "fields": { 231 | "vehicle_class": "walker", 232 | "pilots": [] 233 | }, 234 | "model": "resources.vehicle", 235 | "pk": 54 236 | }, 237 | { 238 | "fields": { 239 | "vehicle_class": "speeder", 240 | "pilots": [ 241 | 67 242 | ] 243 | }, 244 | "model": "resources.vehicle", 245 | "pk": 55 246 | }, 247 | { 248 | "fields": { 249 | "vehicle_class": "transport", 250 | "pilots": [] 251 | }, 252 | "model": "resources.vehicle", 253 | "pk": 56 254 | }, 255 | { 256 | "fields": { 257 | "vehicle_class": "starfighter", 258 | "pilots": [] 259 | }, 260 | "model": "resources.vehicle", 261 | "pk": 57 262 | }, 263 | { 264 | "fields": { 265 | "vehicle_class": "wheeled walker", 266 | "pilots": [ 267 | 79 268 | ] 269 | }, 270 | "model": "resources.vehicle", 271 | "pk": 60 272 | }, 273 | { 274 | "fields": { 275 | "vehicle_class": "fire suppression ship", 276 | "pilots": [] 277 | }, 278 | "model": "resources.vehicle", 279 | "pk": 62 280 | }, 281 | { 282 | "fields": { 283 | "vehicle_class": "droid starfighter", 284 | "pilots": [] 285 | }, 286 | "model": "resources.vehicle", 287 | "pk": 67 288 | }, 289 | { 290 | "fields": { 291 | "vehicle_class": "airspeeder", 292 | "pilots": [] 293 | }, 294 | "model": "resources.vehicle", 295 | "pk": 69 296 | }, 297 | { 298 | "fields": { 299 | "vehicle_class": "air speeder", 300 | "pilots": [] 301 | }, 302 | "model": "resources.vehicle", 303 | "pk": 70 304 | }, 305 | { 306 | "fields": { 307 | "vehicle_class": "wheeled walker", 308 | "pilots": [] 309 | }, 310 | "model": "resources.vehicle", 311 | "pk": 71 312 | }, 313 | { 314 | "fields": { 315 | "vehicle_class": "droid tank", 316 | "pilots": [] 317 | }, 318 | "model": "resources.vehicle", 319 | "pk": 72 320 | }, 321 | { 322 | "fields": { 323 | "vehicle_class": "airspeeder", 324 | "pilots": [] 325 | }, 326 | "model": "resources.vehicle", 327 | "pk": 73 328 | }, 329 | { 330 | "fields": { 331 | "vehicle_class": "walker", 332 | "pilots": [] 333 | }, 334 | "model": "resources.vehicle", 335 | "pk": 76 336 | } 337 | ] 338 | -------------------------------------------------------------------------------- /resources/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ] 11 | 12 | operations = [ 13 | migrations.CreateModel( 14 | name='Film', 15 | fields=[ 16 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 17 | ('created', models.DateTimeField(auto_now_add=True)), 18 | ('edited', models.DateTimeField(auto_now=True)), 19 | ('title', models.CharField(max_length=100)), 20 | ('episode_id', models.IntegerField(max_length=10)), 21 | ('opening_crawl', models.TextField(max_length=1000)), 22 | ('director', models.CharField(max_length=100)), 23 | ('producer', models.CharField(max_length=100)), 24 | ], 25 | options={ 26 | 'abstract': False, 27 | }, 28 | bases=(models.Model,), 29 | ), 30 | migrations.CreateModel( 31 | name='People', 32 | fields=[ 33 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 34 | ('created', models.DateTimeField(auto_now_add=True)), 35 | ('edited', models.DateTimeField(auto_now=True)), 36 | ('name', models.CharField(max_length=100)), 37 | ('height', models.CharField(max_length=10, blank=True)), 38 | ('mass', models.CharField(max_length=10, blank=True)), 39 | ('hair_color', models.CharField(max_length=20, blank=True)), 40 | ('skin_color', models.CharField(max_length=20, blank=True)), 41 | ('eye_color', models.CharField(max_length=20, blank=True)), 42 | ('birth_year', models.CharField(max_length=10, blank=True)), 43 | ('gender', models.CharField(max_length=40, blank=True)), 44 | ], 45 | options={ 46 | 'abstract': False, 47 | }, 48 | bases=(models.Model,), 49 | ), 50 | migrations.CreateModel( 51 | name='Planet', 52 | fields=[ 53 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 54 | ('created', models.DateTimeField(auto_now_add=True)), 55 | ('edited', models.DateTimeField(auto_now=True)), 56 | ('name', models.CharField(max_length=100)), 57 | ('rotation_period', models.CharField(max_length=40)), 58 | ('orbital_period', models.CharField(max_length=40)), 59 | ('diameter', models.CharField(max_length=40)), 60 | ('climate', models.CharField(max_length=40)), 61 | ('gravity', models.CharField(max_length=40)), 62 | ('terrain', models.CharField(max_length=40)), 63 | ('surface_water', models.CharField(max_length=40)), 64 | ('population', models.CharField(max_length=40)), 65 | ], 66 | options={ 67 | 'abstract': False, 68 | }, 69 | bases=(models.Model,), 70 | ), 71 | migrations.CreateModel( 72 | name='Species', 73 | fields=[ 74 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 75 | ('created', models.DateTimeField(auto_now_add=True)), 76 | ('edited', models.DateTimeField(auto_now=True)), 77 | ('name', models.CharField(max_length=40)), 78 | ('classification', models.CharField(max_length=40)), 79 | ('designation', models.CharField(max_length=40)), 80 | ('average_height', models.CharField(max_length=40)), 81 | ('skin_colors', models.CharField(max_length=200)), 82 | ('hair_colors', models.CharField(max_length=200)), 83 | ('eye_colors', models.CharField(max_length=200)), 84 | ('average_lifespan', models.CharField(max_length=40)), 85 | ('language', models.CharField(max_length=40)), 86 | ('homeworld', models.ForeignKey(to='resources.Planet', blank=True)), 87 | ('people', models.ManyToManyField(related_name='species', to='resources.People')), 88 | ], 89 | options={ 90 | 'abstract': False, 91 | }, 92 | bases=(models.Model,), 93 | ), 94 | migrations.CreateModel( 95 | name='Transport', 96 | fields=[ 97 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 98 | ('created', models.DateTimeField(auto_now_add=True)), 99 | ('edited', models.DateTimeField(auto_now=True)), 100 | ('name', models.CharField(max_length=40)), 101 | ('model', models.CharField(max_length=40)), 102 | ('manufacturer', models.CharField(max_length=80)), 103 | ('cost_in_credits', models.CharField(max_length=40)), 104 | ('length', models.CharField(max_length=40)), 105 | ('max_atmosphering_speed', models.CharField(max_length=40)), 106 | ('crew', models.CharField(max_length=40)), 107 | ('passengers', models.CharField(max_length=40)), 108 | ('cargo_capacity', models.CharField(max_length=40)), 109 | ('consumables', models.CharField(max_length=40)), 110 | ], 111 | options={ 112 | 'abstract': False, 113 | }, 114 | bases=(models.Model,), 115 | ), 116 | migrations.CreateModel( 117 | name='Starship', 118 | fields=[ 119 | ('transport_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='resources.Transport')), 120 | ('hyperdrive_rating', models.CharField(max_length=40)), 121 | ('MGLT', models.CharField(max_length=40)), 122 | ('starship_class', models.CharField(max_length=40)), 123 | ], 124 | options={ 125 | 'abstract': False, 126 | }, 127 | bases=('resources.transport',), 128 | ), 129 | migrations.CreateModel( 130 | name='Vehicle', 131 | fields=[ 132 | ('transport_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='resources.Transport')), 133 | ('vehicle_class', models.CharField(max_length=40)), 134 | ], 135 | options={ 136 | 'abstract': False, 137 | }, 138 | bases=('resources.transport',), 139 | ), 140 | migrations.AddField( 141 | model_name='transport', 142 | name='pilots', 143 | field=models.ManyToManyField(related_name='transport', to='resources.People'), 144 | preserve_default=True, 145 | ), 146 | migrations.AddField( 147 | model_name='people', 148 | name='homeworld', 149 | field=models.ForeignKey(related_name='residents', to='resources.Planet'), 150 | preserve_default=True, 151 | ), 152 | migrations.AddField( 153 | model_name='film', 154 | name='characters', 155 | field=models.ManyToManyField(related_name='films', to='resources.People'), 156 | preserve_default=True, 157 | ), 158 | migrations.AddField( 159 | model_name='film', 160 | name='planets', 161 | field=models.ManyToManyField(related_name='films', to='resources.Planet'), 162 | preserve_default=True, 163 | ), 164 | migrations.AddField( 165 | model_name='film', 166 | name='species', 167 | field=models.ManyToManyField(related_name='films', to='resources.Species'), 168 | preserve_default=True, 169 | ), 170 | migrations.AddField( 171 | model_name='film', 172 | name='starships', 173 | field=models.ManyToManyField(related_name='films', to='resources.Starship'), 174 | preserve_default=True, 175 | ), 176 | migrations.AddField( 177 | model_name='film', 178 | name='vehicles', 179 | field=models.ManyToManyField(related_name='films', to='resources.Vehicle'), 180 | preserve_default=True, 181 | ), 182 | ] 183 | -------------------------------------------------------------------------------- /resources/migrations/0001_squashed_0005_remove_transport_pilots.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | replaces = [(b'resources', '0001_initial'), (b'resources', '0002_auto_20141210_1424'), (b'resources', '0003_auto_20141210_1516'), (b'resources', '0004_auto_20141213_1443'), (b'resources', '0005_remove_transport_pilots')] 10 | 11 | dependencies = [ 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='Film', 17 | fields=[ 18 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 19 | ('created', models.DateTimeField(auto_now_add=True)), 20 | ('edited', models.DateTimeField(auto_now=True)), 21 | ('title', models.CharField(max_length=100)), 22 | ('episode_id', models.IntegerField(max_length=10)), 23 | ('opening_crawl', models.TextField(max_length=1000)), 24 | ('director', models.CharField(max_length=100)), 25 | ('producer', models.CharField(max_length=100)), 26 | ], 27 | options={ 28 | 'abstract': False, 29 | }, 30 | bases=(models.Model,), 31 | ), 32 | migrations.CreateModel( 33 | name='People', 34 | fields=[ 35 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 36 | ('created', models.DateTimeField(auto_now_add=True)), 37 | ('edited', models.DateTimeField(auto_now=True)), 38 | ('name', models.CharField(max_length=100)), 39 | ('height', models.CharField(max_length=10, blank=True)), 40 | ('mass', models.CharField(max_length=10, blank=True)), 41 | ('hair_color', models.CharField(max_length=20, blank=True)), 42 | ('skin_color', models.CharField(max_length=20, blank=True)), 43 | ('eye_color', models.CharField(max_length=20, blank=True)), 44 | ('birth_year', models.CharField(max_length=10, blank=True)), 45 | ('gender', models.CharField(max_length=40, blank=True)), 46 | ], 47 | options={ 48 | 'abstract': False, 49 | }, 50 | bases=(models.Model,), 51 | ), 52 | migrations.CreateModel( 53 | name='Planet', 54 | fields=[ 55 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 56 | ('created', models.DateTimeField(auto_now_add=True)), 57 | ('edited', models.DateTimeField(auto_now=True)), 58 | ('name', models.CharField(max_length=100)), 59 | ('rotation_period', models.CharField(max_length=40)), 60 | ('orbital_period', models.CharField(max_length=40)), 61 | ('diameter', models.CharField(max_length=40)), 62 | ('climate', models.CharField(max_length=40)), 63 | ('gravity', models.CharField(max_length=40)), 64 | ('terrain', models.CharField(max_length=40)), 65 | ('surface_water', models.CharField(max_length=40)), 66 | ('population', models.CharField(max_length=40)), 67 | ], 68 | options={ 69 | 'abstract': False, 70 | }, 71 | bases=(models.Model,), 72 | ), 73 | migrations.CreateModel( 74 | name='Species', 75 | fields=[ 76 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 77 | ('created', models.DateTimeField(auto_now_add=True)), 78 | ('edited', models.DateTimeField(auto_now=True)), 79 | ('name', models.CharField(max_length=40)), 80 | ('classification', models.CharField(max_length=40)), 81 | ('designation', models.CharField(max_length=40)), 82 | ('average_height', models.CharField(max_length=40)), 83 | ('skin_colors', models.CharField(max_length=200)), 84 | ('hair_colors', models.CharField(max_length=200)), 85 | ('eye_colors', models.CharField(max_length=200)), 86 | ('average_lifespan', models.CharField(max_length=40)), 87 | ('language', models.CharField(max_length=40)), 88 | ('homeworld', models.ForeignKey(blank=True, to='resources.Planet', null=True)), 89 | ('people', models.ManyToManyField(related_name='species', to=b'resources.People')), 90 | ], 91 | options={ 92 | 'abstract': False, 93 | }, 94 | bases=(models.Model,), 95 | ), 96 | migrations.CreateModel( 97 | name='Transport', 98 | fields=[ 99 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 100 | ('created', models.DateTimeField(auto_now_add=True)), 101 | ('edited', models.DateTimeField(auto_now=True)), 102 | ('name', models.CharField(max_length=40)), 103 | ('model', models.CharField(max_length=40)), 104 | ('manufacturer', models.CharField(max_length=80)), 105 | ('cost_in_credits', models.CharField(max_length=40)), 106 | ('length', models.CharField(max_length=40)), 107 | ('max_atmosphering_speed', models.CharField(max_length=40)), 108 | ('crew', models.CharField(max_length=40)), 109 | ('passengers', models.CharField(max_length=40)), 110 | ('cargo_capacity', models.CharField(max_length=40)), 111 | ('consumables', models.CharField(max_length=40)), 112 | ], 113 | options={ 114 | 'abstract': False, 115 | }, 116 | bases=(models.Model,), 117 | ), 118 | migrations.CreateModel( 119 | name='Starship', 120 | fields=[ 121 | ('transport_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='resources.Transport')), 122 | ('hyperdrive_rating', models.CharField(max_length=40)), 123 | ('MGLT', models.CharField(max_length=40)), 124 | ('starship_class', models.CharField(max_length=40)), 125 | ], 126 | options={ 127 | 'abstract': False, 128 | }, 129 | bases=('resources.transport',), 130 | ), 131 | migrations.CreateModel( 132 | name='Vehicle', 133 | fields=[ 134 | ('transport_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='resources.Transport')), 135 | ('vehicle_class', models.CharField(max_length=40)), 136 | ], 137 | options={ 138 | 'abstract': False, 139 | }, 140 | bases=('resources.transport',), 141 | ), 142 | migrations.AddField( 143 | model_name='people', 144 | name='homeworld', 145 | field=models.ForeignKey(related_name='residents', to='resources.Planet'), 146 | preserve_default=True, 147 | ), 148 | migrations.AddField( 149 | model_name='film', 150 | name='characters', 151 | field=models.ManyToManyField(related_name='films', to=b'resources.People', blank=True), 152 | preserve_default=True, 153 | ), 154 | migrations.AddField( 155 | model_name='film', 156 | name='planets', 157 | field=models.ManyToManyField(related_name='films', to=b'resources.Planet', blank=True), 158 | preserve_default=True, 159 | ), 160 | migrations.AddField( 161 | model_name='film', 162 | name='species', 163 | field=models.ManyToManyField(related_name='films', to=b'resources.Species', blank=True), 164 | preserve_default=True, 165 | ), 166 | migrations.AddField( 167 | model_name='film', 168 | name='starships', 169 | field=models.ManyToManyField(related_name='films', to=b'resources.Starship', blank=True), 170 | preserve_default=True, 171 | ), 172 | migrations.AddField( 173 | model_name='film', 174 | name='vehicles', 175 | field=models.ManyToManyField(related_name='films', to=b'resources.Vehicle', blank=True), 176 | preserve_default=True, 177 | ), 178 | migrations.AddField( 179 | model_name='starship', 180 | name='new_pilots', 181 | field=models.ManyToManyField(related_name='starships', to=b'resources.People', blank=True), 182 | preserve_default=True, 183 | ), 184 | migrations.AddField( 185 | model_name='vehicle', 186 | name='new_pilots', 187 | field=models.ManyToManyField(related_name='vehicles', to=b'resources.People', blank=True), 188 | preserve_default=True, 189 | ), 190 | migrations.AlterField( 191 | model_name='film', 192 | name='episode_id', 193 | field=models.IntegerField(), 194 | ), 195 | ] 196 | -------------------------------------------------------------------------------- /resources/migrations/0002_auto_20141213_1454.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('resources', '0001_squashed_0005_remove_transport_pilots'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RenameField( 15 | model_name='starship', 16 | old_name='new_pilots', 17 | new_name='pilots', 18 | ), 19 | migrations.RenameField( 20 | model_name='vehicle', 21 | old_name='new_pilots', 22 | new_name='pilots', 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /resources/migrations/0003_film_release_date.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import models, migrations 5 | import django.utils.datetime_safe 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('resources', '0002_auto_20141213_1454'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='film', 17 | name='release_date', 18 | field=models.DateField(default=django.utils.datetime_safe.date.today), 19 | preserve_default=False, 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /resources/migrations/0004_editablemodel.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('resources', '0003_film_release_date'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='EditableModel', 16 | fields=[ 17 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 18 | ('editable', models.NullBooleanField()), 19 | ], 20 | options={ 21 | }, 22 | bases=(models.Model,), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /resources/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Juriy/swapi/5413ffe76ccd449fbcd9b2379b18a6c2a14ff1a5/resources/migrations/__init__.py -------------------------------------------------------------------------------- /resources/models.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.db import models 4 | 5 | 6 | class DateTimeModel(models.Model): 7 | """ A base model with created and edited datetime fields """ 8 | 9 | class Meta: 10 | abstract = True 11 | 12 | created = models.DateTimeField(auto_now_add=True) 13 | 14 | edited = models.DateTimeField(auto_now=True) 15 | 16 | 17 | class EditableModel(models.Model): 18 | """ 19 | A model with a boolean that determins the read/write state of the model 20 | """ 21 | 22 | editable = models.NullBooleanField() 23 | 24 | 25 | class Planet(DateTimeModel): 26 | """ A planet i.e. Tatooine """ 27 | 28 | def __unicode__(self): 29 | return self.name 30 | 31 | name = models.CharField(max_length=100) 32 | 33 | rotation_period = models.CharField(max_length=40) 34 | 35 | orbital_period = models.CharField(max_length=40) 36 | 37 | diameter = models.CharField(max_length=40) 38 | 39 | climate = models.CharField(max_length=40) 40 | 41 | gravity = models.CharField(max_length=40) 42 | 43 | terrain = models.CharField(max_length=40) 44 | 45 | surface_water = models.CharField(max_length=40) 46 | 47 | population = models.CharField(max_length=40) 48 | 49 | 50 | class People(DateTimeModel): 51 | """ A person i.e. - Luke Skywalker """ 52 | 53 | def __unicode__(self): 54 | return self.name 55 | 56 | name = models.CharField(max_length=100) 57 | 58 | height = models.CharField(max_length=10, blank=True) 59 | 60 | mass = models.CharField(max_length=10, blank=True) 61 | 62 | hair_color = models.CharField(max_length=20, blank=True) 63 | 64 | skin_color = models.CharField(max_length=20, blank=True) 65 | 66 | eye_color = models.CharField(max_length=20, blank=True) 67 | 68 | birth_year = models.CharField(max_length=10, blank=True) 69 | 70 | gender = models.CharField(max_length=40, blank=True) 71 | 72 | homeworld = models.ForeignKey(Planet, related_name="residents") 73 | 74 | 75 | class Transport(DateTimeModel): 76 | 77 | def __unicode__(self): 78 | return self.name 79 | 80 | name = models.CharField(max_length=40) 81 | 82 | model = models.CharField(max_length=40) 83 | 84 | manufacturer = models.CharField(max_length=80) 85 | 86 | cost_in_credits = models.CharField(max_length=40) 87 | 88 | length = models.CharField(max_length=40) 89 | 90 | max_atmosphering_speed = models.CharField(max_length=40) 91 | 92 | crew = models.CharField(max_length=40) 93 | 94 | passengers = models.CharField(max_length=40) 95 | 96 | cargo_capacity = models.CharField(max_length=40) 97 | 98 | consumables = models.CharField(max_length=40) 99 | 100 | 101 | class Starship(Transport): 102 | """ A starship is a transport with a hypderdrive """ 103 | 104 | hyperdrive_rating = models.CharField(max_length=40) 105 | 106 | MGLT = models.CharField(max_length=40) 107 | 108 | starship_class = models.CharField(max_length=40) 109 | 110 | pilots = models.ManyToManyField( 111 | People, 112 | related_name="starships", 113 | blank=True 114 | ) 115 | 116 | 117 | class Vehicle(Transport): 118 | """ A vehicle is anything without hyperdrive capability """ 119 | 120 | vehicle_class = models.CharField(max_length=40) 121 | 122 | pilots = models.ManyToManyField( 123 | People, 124 | related_name="vehicles", 125 | blank=True 126 | ) 127 | 128 | 129 | class Species(DateTimeModel): 130 | "A species is a type of alien or person" 131 | 132 | def __unicode__(self): 133 | return self.name 134 | 135 | name = models.CharField(max_length=40) 136 | 137 | classification = models.CharField(max_length=40) 138 | 139 | designation = models.CharField(max_length=40) 140 | 141 | average_height = models.CharField(max_length=40) 142 | 143 | skin_colors = models.CharField(max_length=200) 144 | 145 | hair_colors = models.CharField(max_length=200) 146 | 147 | eye_colors = models.CharField(max_length=200) 148 | 149 | average_lifespan = models.CharField(max_length=40) 150 | 151 | homeworld = models.ForeignKey(Planet, blank=True, null=True) 152 | 153 | language = models.CharField(max_length=40) 154 | 155 | people = models.ManyToManyField(People, related_name="species") 156 | 157 | 158 | class Film(DateTimeModel): 159 | """ A film i.e. The Empire Strikes Back (which is also the best film) """ 160 | 161 | def __unicode__(self): 162 | return self.title 163 | 164 | title = models.CharField(max_length=100) 165 | 166 | episode_id = models.IntegerField() 167 | 168 | opening_crawl = models.TextField(max_length=1000) 169 | 170 | director = models.CharField(max_length=100) 171 | 172 | producer = models.CharField(max_length=100) 173 | 174 | release_date = models.DateField() 175 | 176 | characters = models.ManyToManyField( 177 | People, 178 | related_name="films", 179 | blank=True 180 | ) 181 | 182 | planets = models.ManyToManyField( 183 | Planet, 184 | related_name="films", 185 | blank=True 186 | ) 187 | 188 | starships = models.ManyToManyField( 189 | Starship, 190 | related_name="films", 191 | blank=True 192 | ) 193 | 194 | vehicles = models.ManyToManyField( 195 | Vehicle, 196 | related_name="films", 197 | blank=True 198 | ) 199 | 200 | species = models.ManyToManyField( 201 | Species, 202 | related_name="films", 203 | blank=True 204 | ) 205 | 206 | -------------------------------------------------------------------------------- /resources/renderers.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | from rest_framework import renderers 3 | 4 | 5 | class WookieeRenderer(renderers.JSONRenderer): 6 | media_type = "application/json" 7 | charset = 'utf-8' 8 | format = "wookiee" 9 | lookup = { 10 | "a": "ra", 11 | "b": "rh", 12 | "c": "oa", 13 | "d": "wa", 14 | "e": "wo", 15 | "f": "ww", 16 | "g": "rr", 17 | "h": "ac", 18 | "i": "ah", 19 | "j": "sh", 20 | "k": "or", 21 | "l": "an", 22 | "m": "sc", 23 | "n": "wh", 24 | "o": "oo", 25 | "p": "ak", 26 | "q": "rq", 27 | "r": "rc", 28 | "s": "c", 29 | "t": "ao", 30 | "u": "hu", 31 | "v": "ho", 32 | "w": "oh", 33 | "x": "k", 34 | "y": "ro", 35 | "z": "uf", 36 | } 37 | 38 | def render(self, data, media_type=None, renderer_context=None): 39 | encoded_data = super(WookieeRenderer, self).render( 40 | data, media_type, renderer_context 41 | ) 42 | return bytes(self.translate_to_wookie(encoded_data)) 43 | 44 | def translate_to_wookie(self, data): 45 | translated_data = "" 46 | for char in data: 47 | if char in self.lookup: 48 | translated_data += self.lookup[char] 49 | else: 50 | translated_data += char 51 | return translated_data 52 | -------------------------------------------------------------------------------- /resources/schemas.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.http import HttpResponse 4 | 5 | import json 6 | 7 | 8 | class JSONResponse(): 9 | 10 | def __init__(self, resource): 11 | with open('resources/schemas/{0}.json'.format(resource)) as f: 12 | data = json.loads(f.read()) 13 | self.data = data 14 | 15 | @property 16 | def response(self): 17 | return HttpResponse( 18 | json.dumps(self.data), 19 | content_type="application/json" 20 | ) 21 | 22 | 23 | def people(request): 24 | return JSONResponse('people').response 25 | 26 | 27 | def planets(request): 28 | return JSONResponse('planets').response 29 | 30 | 31 | def films(request): 32 | return JSONResponse('films').response 33 | 34 | 35 | def species(request): 36 | return JSONResponse('species').response 37 | 38 | 39 | def vehicles(request): 40 | return JSONResponse('vehicles').response 41 | 42 | 43 | def starships(request): 44 | return JSONResponse('starships').response 45 | -------------------------------------------------------------------------------- /resources/schemas/films.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema", 3 | "title": "Film", 4 | "description": "A Star Wars film", 5 | "type": "object", 6 | "properties": { 7 | "title": { 8 | "type": "string", 9 | "description": "The title of this film." 10 | }, 11 | "episode_id": { 12 | "type": "integer", 13 | "description": "The episode number of this film." 14 | }, 15 | "opening_crawl": { 16 | "type": "string", 17 | "description": "The opening crawl text at the beginning of this film." 18 | }, 19 | "director": { 20 | "type": "string", 21 | "description": "The director of this film." 22 | }, 23 | "producer": { 24 | "type": "string", 25 | "description": "The producer(s) of this film." 26 | }, 27 | "release_date": { 28 | "type": "string", 29 | "format": "date", 30 | "description": "The release date at original creator country." 31 | }, 32 | "characters": { 33 | "type": "array", 34 | "description": "The people resources featured within this film." 35 | }, 36 | "planets": { 37 | "type": "array", 38 | "description": "The planet resources featured within this film." 39 | }, 40 | "starships": { 41 | "type": "array", 42 | "description": "The starship resources featured within this film." 43 | }, 44 | "vehicles": { 45 | "type": "array", 46 | "description": "The vehicle resources featured within this film." 47 | }, 48 | "species": { 49 | "type": "array", 50 | "description": "The species resources featured within this film." 51 | }, 52 | "url": { 53 | "type": "string", 54 | "format": "uri", 55 | "description": "The url of this resource" 56 | }, 57 | "created": { 58 | "type": "string", 59 | "format": "date-time", 60 | "description": "The ISO 8601 date format of the time that this resource was created." 61 | }, 62 | "edited": { 63 | "type": "string", 64 | "format": "date-time", 65 | "description": "the ISO 8601 date format of the time that this resource was edited." 66 | } 67 | }, 68 | "required": [ 69 | "title", 70 | "episode_id", 71 | "opening_crawl", 72 | "director", 73 | "producer", 74 | "release_date", 75 | "characters", 76 | "planets", 77 | "starships", 78 | "vehicles", 79 | "species", 80 | "url", 81 | "created", 82 | "edited" 83 | ] 84 | } 85 | -------------------------------------------------------------------------------- /resources/schemas/people.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema", 3 | "title": "People", 4 | "description": "A person within the Star Wars universe", 5 | "type": "object", 6 | "properties": { 7 | "name": { 8 | "type": "string", 9 | "description": "The name of this person." 10 | }, 11 | "height": { 12 | "type": "string", 13 | "description": "The height of this person in meters." 14 | }, 15 | "mass": { 16 | "type": "string", 17 | "description": "The mass of this person in kilograms." 18 | }, 19 | "hair_color": { 20 | "type": "string", 21 | "description": "The hair color of this person." 22 | }, 23 | "skin_color": { 24 | "type": "string", 25 | "description": "The skin color of this person." 26 | }, 27 | "eye_color": { 28 | "type": "string", 29 | "description": "The eye color of this person." 30 | }, 31 | "birth_year": { 32 | "type": "string", 33 | "description": "The birth year of this person. BBY (Before the Battle of Yavin) or ABY (After the Battle of Yavin)." 34 | }, 35 | "gender": { 36 | "type": "string", 37 | "description": "The gender of this person (if known)." 38 | }, 39 | "homeworld": { 40 | "type": "string", 41 | "description": "The url of the planet resource that this person was born on." 42 | }, 43 | "films": { 44 | "type": "array", 45 | "description": "An array of urls of film resources that this person has been in." 46 | }, 47 | "species": { 48 | "type": "array", 49 | "description": "The url of the species resource that this person is." 50 | }, 51 | "vehicles": { 52 | "type": "array", 53 | "description": "An array of vehicle resources that this person has piloted" 54 | }, 55 | "starships": { 56 | "type": "array", 57 | "description": "An array of starship resources that this person has piloted" 58 | }, 59 | "url": { 60 | "type": "string", 61 | "format": "uri", 62 | "description": "The url of this resource" 63 | }, 64 | "created": { 65 | "type": "string", 66 | "format": "date-time", 67 | "description": "The ISO 8601 date format of the time that this resource was created." 68 | }, 69 | "edited": { 70 | "type": "string", 71 | "format": "date-time", 72 | "description": "the ISO 8601 date format of the time that this resource was edited." 73 | } 74 | }, 75 | "required": [ 76 | "name", 77 | "height", 78 | "mass", 79 | "hair_color", 80 | "skin_color", 81 | "eye_color", 82 | "birth_year", 83 | "gender", 84 | "homeworld", 85 | "films", 86 | "species", 87 | "vehicles", 88 | "starships", 89 | "url", 90 | "created", 91 | "edited" 92 | ] 93 | } 94 | -------------------------------------------------------------------------------- /resources/schemas/planets.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema", 3 | "title": "Planet", 4 | "description": "A planet.", 5 | "type": "object", 6 | "properties": { 7 | "name": { 8 | "type": "string", 9 | "description": "The name of this planet." 10 | }, 11 | "diameter": { 12 | "type": "string", 13 | "description": "The diameter of this planet in kilometers." 14 | }, 15 | "rotation_period": { 16 | "type": "string", 17 | "description": "The number of standard hours it takes for this planet to complete a single rotation on its axis." 18 | }, 19 | "orbital_period": { 20 | "type": "string", 21 | "description": "The number of standard days it takes for this planet to complete a single orbit of its local star." 22 | }, 23 | "gravity": { 24 | "type": "string", 25 | "description": "A number denoting the gravity of this planet. Where 1 is normal." 26 | }, 27 | "population": { 28 | "type": "string", 29 | "description": "The average populationof sentient beings inhabiting this planet." 30 | }, 31 | "climate": { 32 | "type": "string", 33 | "description": "The climate of this planet. Comma-seperated if diverse." 34 | }, 35 | "terrain": { 36 | "type": "string", 37 | "description": "the terrain of this planet. Comma-seperated if diverse." 38 | }, 39 | "surface_water": { 40 | "type": "string", 41 | "description": "The percentage of the planet surface that is naturally occuring water or bodies of water." 42 | }, 43 | "films": { 44 | "type": "array", 45 | "description": "An array of Film URL Resources that this planet has appeared in." 46 | }, 47 | "residents": { 48 | "type": "array", 49 | "description": "An array of People URL Resources that live on this planet." 50 | }, 51 | "url": { 52 | "type": "string", 53 | "format": "uri", 54 | "description": "The hypermedia URL of this resource." 55 | }, 56 | "created": { 57 | "type": "string", 58 | "format": "date-time", 59 | "description": "The ISO 8601 date format of the time that this resource was created." 60 | }, 61 | "edited": { 62 | "type": "string", 63 | "format": "date-time", 64 | "description": "the ISO 8601 date format of the time that this resource was edited." 65 | } 66 | }, 67 | "required": [ 68 | "name", 69 | "rotation_period", 70 | "orbital_period", 71 | "diameter", 72 | "climate", 73 | "gravity", 74 | "terrain", 75 | "surface_water", 76 | "population", 77 | "residents", 78 | "films", 79 | "created", 80 | "edited", 81 | "url" 82 | ] 83 | } 84 | -------------------------------------------------------------------------------- /resources/schemas/species.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema", 3 | "title": "People", 4 | "description": "A species within the Star Wars universe", 5 | "type": "object", 6 | "properties": { 7 | "name": { 8 | "type": "string", 9 | "description": "The name of this species." 10 | }, 11 | "classification": { 12 | "type": "string", 13 | "description": "The classification of this species." 14 | }, 15 | "designation": { 16 | "type": "string", 17 | "description": "The designation of this species." 18 | }, 19 | "average_height": { 20 | "type": "string", 21 | "description": "The average height of this person in centimeters." 22 | }, 23 | "average_lifespan": { 24 | "type": "string", 25 | "description": "The average lifespan of this species in years." 26 | }, 27 | "hair_colors": { 28 | "type": "string", 29 | "description": "A comma-seperated string of common hair colors for this species, none if this species does not typically have hair." 30 | }, 31 | "skin_colors": { 32 | "type": "string", 33 | "description": "A comma-seperated string of common skin colors for this species, none if this species does not typically have skin." 34 | }, 35 | "eye_colors": { 36 | "type": "string", 37 | "description": "A comma-seperated string of common eye colors for this species, none if this species does not typically have eyes." 38 | }, 39 | "homeworld": { 40 | "type": "string", 41 | "description": "The URL of a planet resource, a planet that this species originates from." 42 | }, 43 | "language": { 44 | "type": "string", 45 | "description": "The language commonly spoken by this species." 46 | }, 47 | "people": { 48 | "type": "array", 49 | "description": "An array of People URL Resources that are a part of this species." 50 | }, 51 | "films": { 52 | "type": "array", 53 | "description": " An array of Film URL Resources that this species has appeared in." 54 | }, 55 | "url": { 56 | "type": "string", 57 | "format": "uri", 58 | "description": "The hypermedia URL of this resource." 59 | }, 60 | "created": { 61 | "type": "string", 62 | "format": "date-time", 63 | "description": "The ISO 8601 date format of the time that this resource was created." 64 | }, 65 | "edited": { 66 | "type": "string", 67 | "format": "date-time", 68 | "description": "The ISO 8601 date format of the time that this resource was edited." 69 | } 70 | }, 71 | "required": [ 72 | "name", 73 | "classification", 74 | "designation", 75 | "average_height", 76 | "average_lifespan", 77 | "hair_colors", 78 | "skin_colors", 79 | "eye_colors", 80 | "homeworld", 81 | "language", 82 | "people", 83 | "films", 84 | "url", 85 | "created", 86 | "edited" 87 | ] 88 | } 89 | -------------------------------------------------------------------------------- /resources/schemas/starships.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema", 3 | "title": "Starship", 4 | "description": "A Starship", 5 | "type": "object", 6 | "properties": { 7 | "name": { 8 | "type": "string", 9 | "description": "The name of this starship. The common name, such as Death Star." 10 | }, 11 | "model": { 12 | "type": "string", 13 | "description": "The model or official name of this starship. Such as T-65 X-wing or DS-1 Orbital Battle Station." 14 | }, 15 | "starship_class": { 16 | "type": "string", 17 | "description": "The class of this starship, such as Starfighter or Deep Space Mobile Battlestation." 18 | }, 19 | "manufacturer": { 20 | "type": "string", 21 | "description": "The manufacturer of this starship. Comma seperated if more than one." 22 | }, 23 | "cost_in_credits": { 24 | "type": "string", 25 | "description": "The cost of this starship new, in galactic credits." 26 | }, 27 | "length": { 28 | "type": "string", 29 | "description": "The length of this starship in meters." 30 | }, 31 | "crew":{ 32 | "type": "string", 33 | "description": "The number of personnel needed to run or pilot this starship." 34 | }, 35 | "passengers": { 36 | "type": "string", 37 | "description": "The number of non-essential people this starship can transport." 38 | }, 39 | "max_atmosphering_speed": { 40 | "type": "string", 41 | "description": "The maximum speed of this starship in atmosphere. n/a if this starship is incapable of atmosphering flight." 42 | }, 43 | "hyperdrive_rating" : { 44 | "type": "string", 45 | "description": "The class of this starships hyperdrive." 46 | }, 47 | "MGLT": { 48 | "type": "string", 49 | "description": "The Maximum number of Megalights this starship can travel in a standard hour. A Megalight is a standard unit of distance and has never been defined before within the Star Wars universe. This figure is only really useful for measuring the difference in speed of starships. We can assume it is similar to AU, the distance between our Sun (Sol) and Earth." 50 | }, 51 | "cargo_capacity": { 52 | "type": "string", 53 | "description": "The maximum number of kilograms that this starship can transport." 54 | }, 55 | "consumables": { 56 | "type": "string", 57 | "description": "The maximum length of time that this starship can provide consumables for its entire crew without having to resupply." 58 | }, 59 | "films": { 60 | "type": "array", 61 | "description": "An array of Film URL Resources that this starship has appeared in." 62 | }, 63 | "pilots": { 64 | "type": "array", 65 | "description": "An array of People URL Resources that this starship has been piloted by." 66 | }, 67 | "url": { 68 | "type": "string", 69 | "format": "uri", 70 | "description": "The hypermedia URL of this resource." 71 | }, 72 | "created": { 73 | "type": "string", 74 | "format": "date-time", 75 | "description": "The ISO 8601 date format of the time that this resource was created." 76 | }, 77 | "edited": { 78 | "type": "string", 79 | "format": "date-time", 80 | "description": "the ISO 8601 date format of the time that this resource was edited." 81 | } 82 | }, 83 | "required": [ 84 | "name", 85 | "model", 86 | "manufacturer", 87 | "cost_in_credits", 88 | "length", 89 | "max_atmosphering_speed", 90 | "crew", 91 | "passengers", 92 | "cargo_capacity", 93 | "consumables", 94 | "hyperdrive_rating", 95 | "MGLT", 96 | "starship_class", 97 | "pilots", 98 | "films", 99 | "created", 100 | "edited", 101 | "url" 102 | ] 103 | } 104 | -------------------------------------------------------------------------------- /resources/schemas/vehicles.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema", 3 | "title": "Starship", 4 | "description": "A vehicle.", 5 | "type": "object", 6 | "properties": { 7 | "name": { 8 | "type": "string", 9 | "description": "The name of this vehicle. The common name, such as Sand Crawler." 10 | }, 11 | "model": { 12 | "type": "string", 13 | "description": "The model or official name of this vehicle. Such as All Terrain Attack Transport." 14 | }, 15 | "vehicle_class": { 16 | "type": "string", 17 | "description": "The class of this vehicle, such as Wheeled." 18 | }, 19 | "manufacturer": { 20 | "type": "string", 21 | "description": "The manufacturer of this vehicle. Comma seperated if more than one." 22 | }, 23 | "cost_in_credits": { 24 | "type": "string", 25 | "description": "The cost of this vehicle new, in galactic credits." 26 | }, 27 | "length": { 28 | "type": "string", 29 | "description": "The length of this vehicle in meters." 30 | }, 31 | "crew":{ 32 | "type": "string", 33 | "description": "The number of personnel needed to run or pilot this vehicle." 34 | }, 35 | "passengers": { 36 | "type": "string", 37 | "description": "The number of non-essential people this vehicle can transport." 38 | }, 39 | "max_atmosphering_speed": { 40 | "type": "string", 41 | "description": "The maximum speed of this vehicle in atmosphere." 42 | }, 43 | "cargo_capacity": { 44 | "type": "string", 45 | "description": "The maximum number of kilograms that this vehicle can transport." 46 | }, 47 | "consumables": { 48 | "type": "string", 49 | "description": "The maximum length of time that this vehicle can provide consumables for its entire crew without having to resupply." 50 | }, 51 | "films": { 52 | "type": "array", 53 | "description": "An array of Film URL Resources that this vehicle has appeared in." 54 | }, 55 | "pilots": { 56 | "type": "array", 57 | "description": "An array of People URL Resources that this vehicle has been piloted by." 58 | }, 59 | "url": { 60 | "type": "string", 61 | "format": "uri", 62 | "description": "The hypermedia URL of this resource." 63 | }, 64 | "created": { 65 | "type": "string", 66 | "format": "date-time", 67 | "description": "The ISO 8601 date format of the time that this resource was created." 68 | }, 69 | "edited": { 70 | "type": "string", 71 | "format": "date-time", 72 | "description": "the ISO 8601 date format of the time that this resource was edited." 73 | } 74 | }, 75 | "required": [ 76 | "name", 77 | "model", 78 | "manufacturer", 79 | "cost_in_credits", 80 | "length", 81 | "max_atmosphering_speed", 82 | "crew", 83 | "passengers", 84 | "cargo_capacity", 85 | "consumables", 86 | "vehicle_class", 87 | "pilots", 88 | "films", 89 | "created", 90 | "edited", 91 | "url" 92 | ] 93 | } 94 | -------------------------------------------------------------------------------- /resources/serializers.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from rest_framework import serializers 4 | 5 | from .models import ( 6 | People, 7 | Planet, 8 | Film, 9 | Species, 10 | Vehicle, 11 | Starship, 12 | ) 13 | 14 | 15 | class PeopleSerializer(serializers.HyperlinkedModelSerializer): 16 | 17 | homeworld = serializers.HyperlinkedRelatedField( 18 | read_only=True, 19 | view_name="planet-detail" 20 | ) 21 | 22 | class Meta: 23 | model = People 24 | fields = ( 25 | "name", 26 | "height", 27 | "mass", 28 | "hair_color", 29 | "skin_color", 30 | "eye_color", 31 | "birth_year", 32 | "gender", 33 | "homeworld", 34 | "films", 35 | "species", 36 | "vehicles", 37 | "starships", 38 | "created", 39 | "edited", 40 | "url", 41 | ) 42 | 43 | 44 | class PlanetSerializer(serializers.HyperlinkedModelSerializer): 45 | 46 | class Meta: 47 | model = Planet 48 | fields = ( 49 | "name", 50 | "rotation_period", 51 | "orbital_period", 52 | "diameter", 53 | "climate", 54 | "gravity", 55 | "terrain", 56 | "surface_water", 57 | "population", 58 | "residents", 59 | "films", 60 | "created", 61 | "edited", 62 | "url" 63 | ) 64 | 65 | 66 | class FilmSerializer(serializers.HyperlinkedModelSerializer): 67 | 68 | class Meta: 69 | model = Film 70 | fields = ( 71 | "title", 72 | "episode_id", 73 | "opening_crawl", 74 | "director", 75 | "producer", 76 | "release_date", 77 | "characters", 78 | "planets", 79 | "starships", 80 | "vehicles", 81 | "species", 82 | "created", 83 | "edited", 84 | "url" 85 | ) 86 | 87 | 88 | class SpeciesSerializer(serializers.HyperlinkedModelSerializer): 89 | 90 | homeworld = serializers.HyperlinkedRelatedField( 91 | read_only=True, 92 | view_name='planet-detail' 93 | ) 94 | 95 | class Meta: 96 | model = Species 97 | fields = ( 98 | "name", 99 | "classification", 100 | "designation", 101 | "average_height", 102 | "skin_colors", 103 | "hair_colors", 104 | "eye_colors", 105 | "average_lifespan", 106 | "homeworld", 107 | "language", 108 | "people", 109 | "films", 110 | "created", 111 | "edited", 112 | "url" 113 | ) 114 | 115 | 116 | class VehicleSerializer(serializers.HyperlinkedModelSerializer): 117 | 118 | pilots = serializers.HyperlinkedRelatedField( 119 | many=True, 120 | read_only=True, 121 | view_name='people-detail' 122 | ) 123 | 124 | class Meta: 125 | model = Vehicle 126 | fields = ( 127 | "name", 128 | "model", 129 | "manufacturer", 130 | "cost_in_credits", 131 | "length", 132 | "max_atmosphering_speed", 133 | "crew", 134 | "passengers", 135 | "cargo_capacity", 136 | "consumables", 137 | "vehicle_class", 138 | "pilots", 139 | "films", 140 | "created", 141 | "edited", 142 | "url" 143 | ) 144 | 145 | 146 | class StarshipSerializer(serializers.HyperlinkedModelSerializer): 147 | 148 | pilots = serializers.HyperlinkedRelatedField( 149 | many=True, 150 | read_only=True, 151 | view_name="people-detail" 152 | ) 153 | 154 | class Meta: 155 | model = Starship 156 | fields = ( 157 | "name", 158 | "model", 159 | "manufacturer", 160 | "cost_in_credits", 161 | "length", 162 | "max_atmosphering_speed", 163 | "crew", 164 | "passengers", 165 | "cargo_capacity", 166 | "consumables", 167 | "hyperdrive_rating", 168 | "MGLT", 169 | "starship_class", 170 | "pilots", 171 | "films", 172 | "created", 173 | "edited", 174 | "url" 175 | ) 176 | 177 | -------------------------------------------------------------------------------- /resources/tests.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.test import TestCase 4 | 5 | from .models import ( 6 | People, 7 | Planet, 8 | Film, 9 | Species, 10 | Vehicle, 11 | Starship 12 | ) 13 | 14 | from .renderers import WookieeRenderer 15 | 16 | import json 17 | 18 | class TestAllEndpoints(TestCase): 19 | """ Test ALL the endpoints """ 20 | fixtures = [ 21 | "planets.json", 22 | "people.json", 23 | "species.json", 24 | "starships.json", 25 | "vehicles.json", 26 | "transport.json", 27 | "films.json" 28 | ] 29 | 30 | def get_query(self, url): 31 | return self.client.get(url) 32 | 33 | def test_api_root(self): 34 | self.assertEqual( 35 | self.get_query("/api/").status_code, 200) 36 | 37 | def test_people_root(self): 38 | self.assertEqual( 39 | self.get_query("/api/people/").status_code, 200) 40 | 41 | def test_people_schema(self): 42 | self.assertEqual( 43 | self.get_query("/api/people/schema").status_code, 200) 44 | 45 | def test_people_search(self): 46 | response = self.get_query("/api/people/?search=r2") 47 | json_data = json.loads(response.content) 48 | person = People.objects.get(name='R2-D2') 49 | self.assertEqual(response.status_code, 200) 50 | 51 | list_response = self.get_query("/api/people/") 52 | list_data = json.loads(list_response.content) 53 | self.assertLess(json_data["count"],list_data["count"]) 54 | self.assertEqual(person.name, json_data["results"][0]["name"]) 55 | 56 | def test_planets_root(self): 57 | self.assertEqual( 58 | self.get_query("/api/planets/").status_code, 200) 59 | 60 | def test_planets_schema(self): 61 | self.assertEqual( 62 | self.get_query("/api/planets/schema").status_code, 200) 63 | 64 | def test_planets_search(self): 65 | response = self.get_query("/api/planets/?search=yavin") 66 | json_data = json.loads(response.content) 67 | planet = Planet.objects.get(name='Yavin IV') 68 | self.assertEqual(response.status_code, 200) 69 | 70 | list_response = self.get_query("/api/planets/") 71 | list_data = json.loads(list_response.content) 72 | self.assertLess(json_data["count"],list_data["count"]) 73 | self.assertEqual(planet.name, json_data["results"][0]["name"]) 74 | 75 | def test_films_root(self): 76 | self.assertEqual( 77 | self.get_query("/api/films/").status_code, 200) 78 | 79 | def test_films_schema(self): 80 | self.assertEqual( 81 | self.get_query("/api/films/schema").status_code, 200) 82 | 83 | def test_films_search(self): 84 | response = self.get_query("/api/films/?search=sith") 85 | json_data = json.loads(response.content) 86 | film = Film.objects.get(title='Revenge of the Sith') 87 | self.assertEqual(response.status_code, 200) 88 | 89 | list_response = self.get_query("/api/films/") 90 | list_data = json.loads(list_response.content) 91 | self.assertLess(json_data["count"],list_data["count"]) 92 | self.assertEqual(film.title, json_data["results"][0]["title"]) 93 | 94 | def test_starships_root(self): 95 | self.assertEqual( 96 | self.get_query("/api/starships/").status_code, 200) 97 | 98 | def test_starship_schema(self): 99 | self.assertEqual( 100 | self.get_query("/api/starships/schema").status_code, 200) 101 | 102 | def test_starship_search(self): 103 | response = self.get_query("/api/starships/?search=x1") 104 | json_data = json.loads(response.content) 105 | ship = Starship.objects.get(name='TIE Advanced x1') 106 | self.assertEqual(response.status_code, 200) 107 | 108 | list_response = self.get_query("/api/starships/") 109 | list_data = json.loads(list_response.content) 110 | self.assertLess(json_data["count"],list_data["count"]) 111 | self.assertEqual(ship.name, json_data["results"][0]["name"]) 112 | 113 | def test_vehicles_root(self): 114 | self.assertEqual( 115 | self.get_query("/api/vehicles/").status_code, 200) 116 | 117 | def test_vehicle_schema(self): 118 | self.assertEqual( 119 | self.get_query("/api/vehicles/schema").status_code, 200) 120 | 121 | def test_vehicle_search(self): 122 | response = self.get_query("/api/vehicles/?search=crawler") 123 | json_data = json.loads(response.content) 124 | vehicle = Vehicle.objects.get(name='Sand Crawler') 125 | self.assertEqual(response.status_code, 200) 126 | 127 | list_response = self.get_query("/api/vehicles/") 128 | list_data = json.loads(list_response.content) 129 | self.assertLess(json_data["count"],list_data["count"]) 130 | self.assertEqual(vehicle.name, json_data["results"][0]["name"]) 131 | 132 | def test_species_root(self): 133 | self.assertEqual( 134 | self.get_query("/api/species/").status_code, 200) 135 | 136 | def test_species_schema(self): 137 | self.assertEqual( 138 | self.get_query("/api/species/schema").status_code, 200) 139 | 140 | def test_species_search(self): 141 | response = self.get_query("/api/species/?search=calamari") 142 | json_data = json.loads(response.content) 143 | species = Species.objects.get(name='Mon Calamari') 144 | self.assertEqual(response.status_code, 200) 145 | 146 | list_response = self.get_query("/api/species/") 147 | list_data = json.loads(list_response.content) 148 | self.assertLess(json_data["count"],list_data["count"]) 149 | self.assertEqual(species.name, json_data["results"][0]["name"]) 150 | 151 | def test_people_detail(self): 152 | response = self.get_query("/api/people/1/") 153 | json_data = json.loads(response.content) 154 | person = People.objects.get(pk=1) 155 | self.assertEqual(response.status_code, 200) 156 | self.assertEqual(person.name, json_data["name"]) 157 | 158 | def test_planets_detail(self): 159 | response = self.get_query("/api/planets/1/") 160 | json_data = json.loads(response.content) 161 | planet = Planet.objects.get(pk=1) 162 | self.assertEqual(response.status_code, 200) 163 | self.assertEqual(planet.name, json_data["name"]) 164 | 165 | def test_films_detail(self): 166 | response = self.get_query("/api/films/1/") 167 | json_data = json.loads(response.content) 168 | film = Film.objects.get(pk=1) 169 | self.assertEqual(response.status_code, 200) 170 | self.assertEqual(film.title, json_data["title"]) 171 | 172 | def test_starships_detail(self): 173 | response = self.get_query("/api/starships/2/") 174 | json_data = json.loads(response.content) 175 | starship = Starship.objects.get(pk=2) 176 | self.assertEqual(response.status_code, 200) 177 | self.assertEqual(starship.name, json_data["name"]) 178 | 179 | def test_vehicles_detail(self): 180 | response = self.get_query("/api/vehicles/4/") 181 | json_data = json.loads(response.content) 182 | vehicle = Vehicle.objects.get(pk=4) 183 | self.assertEqual(response.status_code, 200) 184 | self.assertEqual(vehicle.name, json_data["name"]) 185 | 186 | def test_species_detail(self): 187 | response = self.get_query("/api/species/1/") 188 | json_data = json.loads(response.content) 189 | specie = Species.objects.get(pk=1) 190 | self.assertEqual(response.status_code, 200) 191 | self.assertEqual(specie.name, json_data["name"]) 192 | 193 | def test_etag(self): 194 | valid_etag = self.get_query("/api/")["ETag"] 195 | self.client.defaults['HTTP_IF_NONE_MATCH'] = valid_etag 196 | self.assertEqual( 197 | self.get_query("/api/").status_code, 304) 198 | 199 | def test_wookie_renderer(self): 200 | wookiee_renderer = WookieeRenderer() 201 | translated_data = wookiee_renderer.translate_to_wookie("swapi") 202 | self.assertEqual(translated_data, "cohraakah") 203 | translated_data = wookiee_renderer.translate_to_wookie("") 204 | self.assertEqual(translated_data, "") 205 | 206 | def test_wookie_format(self): 207 | wr = WookieeRenderer() 208 | response = self.get_query("/api/species/1/?format=wookiee") 209 | json_data = json.loads(response.content) 210 | specie = Species.objects.get(pk=1) 211 | self.assertEqual(response.status_code, 200) 212 | self.assertEqual( 213 | wr.translate_to_wookie(specie.name), 214 | json_data[wr.translate_to_wookie("name")] 215 | ) 216 | -------------------------------------------------------------------------------- /resources/utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from .models import ( 4 | People, 5 | Planet, 6 | Film, 7 | Species, 8 | Vehicle, 9 | Starship, 10 | ) 11 | 12 | def get_resource_stats(): 13 | return { 14 | 'people': People.objects.count(), 15 | 'planets': Planet.objects.count(), 16 | 'films': Film.objects.count(), 17 | 'species': Species.objects.count(), 18 | 'vehicles': Vehicle.objects.count(), 19 | 'starships': Starship.objects.count() 20 | } 21 | -------------------------------------------------------------------------------- /resources/views.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from rest_framework import viewsets 4 | 5 | from .models import ( 6 | People, 7 | Planet, 8 | Film, 9 | Species, 10 | Vehicle, 11 | Starship 12 | ) 13 | 14 | from .serializers import ( 15 | PeopleSerializer, 16 | PlanetSerializer, 17 | FilmSerializer, 18 | SpeciesSerializer, 19 | VehicleSerializer, 20 | StarshipSerializer 21 | ) 22 | 23 | 24 | class PeopleViewSet(viewsets.ReadOnlyModelViewSet): 25 | 26 | queryset = People.objects.all() 27 | serializer_class = PeopleSerializer 28 | search_fields = ('name',) 29 | 30 | def retrieve(self, request, *args, **kwargs): 31 | return super(PeopleViewSet, self).retrieve(request, *args, **kwargs) 32 | 33 | def list(self, request, *args, **kwargs): 34 | return super(PeopleViewSet, self).list(request, *args, **kwargs) 35 | 36 | 37 | class PlanetViewSet(viewsets.ReadOnlyModelViewSet): 38 | 39 | queryset = Planet.objects.all() 40 | serializer_class = PlanetSerializer 41 | search_fields = ('name',) 42 | 43 | def retrieve(self, request, *args, **kwargs): 44 | return super(PlanetViewSet, self).retrieve(request, *args, **kwargs) 45 | 46 | def list(self, request, *args, **kwargs): 47 | return super(PlanetViewSet, self).list(request, *args, **kwargs) 48 | 49 | 50 | class FilmViewSet(viewsets.ReadOnlyModelViewSet): 51 | 52 | queryset = Film.objects.all() 53 | serializer_class = FilmSerializer 54 | search_fields = ('title',) 55 | 56 | def retrieve(self, request, *args, **kwargs): 57 | return super(FilmViewSet, self).retrieve(request, *args, **kwargs) 58 | 59 | def list(self, request, *args, **kwargs): 60 | return super(FilmViewSet, self).list(request, *args, **kwargs) 61 | 62 | 63 | class SpeciesViewSet(viewsets.ReadOnlyModelViewSet): 64 | 65 | queryset = Species.objects.all() 66 | serializer_class = SpeciesSerializer 67 | search_fields = ('name',) 68 | 69 | def retrieve(self, request, *args, **kwargs): 70 | return super(SpeciesViewSet, self).retrieve(request, *args, **kwargs) 71 | 72 | def list(self, request, *args, **kwargs): 73 | return super(SpeciesViewSet, self).list(request, *args, **kwargs) 74 | 75 | 76 | class VehicleViewSet(viewsets.ReadOnlyModelViewSet): 77 | 78 | queryset = Vehicle.objects.all() 79 | serializer_class = VehicleSerializer 80 | search_fields = ('name','model',) 81 | 82 | def retrieve(self, request, *args, **kwargs): 83 | return super(VehicleViewSet, self).retrieve(request, *args, **kwargs) 84 | 85 | def list(self, request, *args, **kwargs): 86 | return super(VehicleViewSet, self).list(request, *args, **kwargs) 87 | 88 | 89 | class StarshipViewSet(viewsets.ReadOnlyModelViewSet): 90 | 91 | queryset = Starship.objects.all() 92 | serializer_class = StarshipSerializer 93 | search_fields = ('name','model',) 94 | 95 | def retrieve(self, request, *args, **kwargs): 96 | return super(StarshipViewSet, self).retrieve(request, *args, **kwargs) 97 | 98 | def list(self, request, *args, **kwargs): 99 | return super(StarshipViewSet, self).list(request, *args, **kwargs) 100 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | python manage.py migrate 3 | make load_data 4 | python manage.py runserver 0.0.0.0:8000 5 | -------------------------------------------------------------------------------- /runtime.txt: -------------------------------------------------------------------------------- 1 | python-2.7.8 -------------------------------------------------------------------------------- /swapi/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Juriy/swapi/5413ffe76ccd449fbcd9b2379b18a6c2a14ff1a5/swapi/__init__.py -------------------------------------------------------------------------------- /swapi/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | import dj_database_url 3 | 4 | BASE_DIR = os.path.dirname(os.path.dirname(__file__)) 5 | 6 | SECRET_KEY = os.environ.get( 7 | 'SECRET_KEY', 8 | 'i+acxn5(akgsn!sr4^qgf(^m&*@+g1@u^t@=8s@axc41ml*f=s' 9 | ) 10 | 11 | DEBUG = bool(os.environ.get('DEBUG', True)) 12 | # Because test settings will trigger KEEN.io hits 13 | KEEN_DEBUG = bool(os.environ.get('DEBUG', True)) 14 | 15 | TEMPLATE_DEBUG = DEBUG 16 | 17 | ALLOWED_HOSTS = [] 18 | 19 | CUSTOM_APPS = ( 20 | 'resources', 21 | 'rest_framework', 22 | 'markdown_deux', 23 | 'corsheaders', 24 | 'clear_cache', 25 | ) 26 | 27 | INSTALLED_APPS = ( 28 | 'django.contrib.admin', 29 | 'django.contrib.auth', 30 | 'django.contrib.contenttypes', 31 | 'django.contrib.sessions', 32 | 'django.contrib.humanize', 33 | 'django.contrib.staticfiles', 34 | ) + CUSTOM_APPS 35 | 36 | MIDDLEWARE_CLASSES = ( 37 | 'django.contrib.sessions.middleware.SessionMiddleware', 38 | 'corsheaders.middleware.CorsMiddleware', 39 | 'django.middleware.common.CommonMiddleware', 40 | 'django.middleware.csrf.CsrfViewMiddleware', 41 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 42 | 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 43 | 'django.contrib.messages.middleware.MessageMiddleware', 44 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 45 | ) 46 | 47 | ROOT_URLCONF = 'swapi.urls' 48 | 49 | WSGI_APPLICATION = 'swapi.wsgi.application' 50 | 51 | DATABASES = { 52 | 'default': { 53 | 'ENGINE': 'django.db.backends.sqlite3', 54 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 55 | } 56 | } 57 | 58 | LANGUAGE_CODE = 'en-us' 59 | TIME_ZONE = 'UTC' 60 | USE_ETAGS = True 61 | USE_I18N = True 62 | USE_L10N = True 63 | USE_TZ = True 64 | 65 | if not DEBUG: 66 | DATABASES['default'] = dj_database_url.config() 67 | 68 | DATABASES['default']['ENGINE'] = 'django_postgrespool' 69 | 70 | SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') 71 | 72 | ALLOWED_HOSTS = ['*'] 73 | 74 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 75 | STATIC_ROOT = 'staticfiles' 76 | STATIC_URL = '/static/' 77 | 78 | STATICFILES_DIRS = ( 79 | os.path.join(BASE_DIR, 'static'), 80 | ) 81 | 82 | TEMPLATE_DIRS = ( 83 | os.path.join(BASE_DIR, 'templates'), 84 | ) 85 | 86 | CACHES = { 87 | 'default': { 88 | 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', 89 | 'TIMEOUT': 60 90 | } 91 | } 92 | 93 | STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage' 94 | 95 | 96 | # Markdown 97 | 98 | MARKDOWN_DEUX_STYLES = { 99 | "default": { 100 | "extras": { 101 | "code-friendly": None, 102 | }, 103 | "safe_mode": False, 104 | }, 105 | } 106 | 107 | # REST Framework 108 | 109 | REST_FRAMEWORK = { 110 | "DEFAULT_RENDERER_CLASSES": ( 111 | 'rest_framework.renderers.JSONRenderer', 112 | 'rest_framework.renderers.BrowsableAPIRenderer', 113 | 'resources.renderers.WookieeRenderer' 114 | ), 115 | 'PAGINATE_BY': 10, 116 | 'DEFAULT_THROTTLE_CLASSES': ( 117 | 'rest_framework.throttling.AnonRateThrottle', 118 | ), 119 | 'DEFAULT_THROTTLE_RATES': { 120 | 'anon': '10000/day', 121 | }, 122 | 'DEFAULT_FILTER_BACKENDS': ( 123 | 'rest_framework.filters.SearchFilter', 124 | ) 125 | } 126 | 127 | # Keen.io 128 | 129 | KEEN_PROJECT_ID = os.environ.get('KEEN_PROJECT_ID', '') 130 | KEEN_WRITE_KEY = os.environ.get('KEEN_WRITE_KEY', '') 131 | KEEN_READ_KEY = os.environ.get('KEEN_READ_KEY', '') 132 | KEEN_CELERY = False 133 | 134 | # Stripe 135 | 136 | STRIPE_TEST_SECRET_KEY = os.environ.get('STRIPE_TEST_SECRET_KEY', '') 137 | STRIPE_SECRET_KEY = os.environ.get('STRIPE_SECRET_KEY', '') 138 | STRIPE_PUBLISHABLE_KEY = os.environ.get('STRIPE_PUBLISHABLE_KEY', '') 139 | STRIPE_TEST_PUBLISHABLE_KEY = os.environ.get('STRIPE_TEST_PUBLISHABLE_KEY', '') 140 | 141 | if DEBUG: 142 | STRIPE_KEYS = { 143 | "secret" :STRIPE_TEST_SECRET_KEY, 144 | "publishable": STRIPE_TEST_PUBLISHABLE_KEY 145 | } 146 | else: 147 | STRIPE_KEYS = { 148 | "secret" :STRIPE_SECRET_KEY, 149 | "publishable": STRIPE_PUBLISHABLE_KEY 150 | } 151 | 152 | # Cors 153 | 154 | CORS_ORIGIN_ALLOW_ALL = True 155 | CORS_URLS_REGEX = r'^/api/.*$' 156 | CORS_ALLOW_METHODS = ( 157 | 'GET', 158 | ) 159 | 160 | # Memcache 161 | 162 | from memcacheify import memcacheify 163 | 164 | CACHES = memcacheify() 165 | 166 | 167 | APPEND_SLASH = True 168 | -------------------------------------------------------------------------------- /swapi/static/css/custom.css: -------------------------------------------------------------------------------- 1 | 2 | .center { 3 | text-align: center; 4 | } 5 | 6 | .yellow { 7 | color: #FFE300; 8 | } 9 | 10 | .pad_top { 11 | padding-top: 34px; 12 | } 13 | 14 | .pad_bot { 15 | padding-bottom: 34px; 16 | } 17 | 18 | .subscribe_btn { 19 | margin-left: -100px; 20 | } 21 | -------------------------------------------------------------------------------- /swapi/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Juriy/swapi/5413ffe76ccd449fbcd9b2379b18a6c2a14ff1a5/swapi/static/favicon.ico -------------------------------------------------------------------------------- /swapi/static/humans.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Juriy/swapi/5413ffe76ccd449fbcd9b2379b18a6c2a14ff1a5/swapi/static/humans.txt -------------------------------------------------------------------------------- /swapi/templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% block mainbody %} 3 |
This is not the page you are looking for.
8 |Oh no! Something has gone awefully wrong.
8 |People: {{people}}
7 |Planets: {{planets}}
8 |Films: {{films}}
9 |Species : {{species}}
10 |Vehicles: {{vehicles}}
11 |Starships: {{starships}}
12 |All the Star Wars data you've ever wanted:
9 |Planets, Spaceships, Vehicles, People, Films and Species
10 |From all SEVEN Star Wars films
11 |Result:
32 |34 | { 35 | "name": "Luke Skywalker", 36 | "height": "172", 37 | "mass": "77", 38 | "hair_color": "blond", 39 | "skin_color": "fair", 40 | "eye_color": "blue", 41 | "birth_year": "19BBY", 42 | "gender": "male", 43 | "homeworld": "https://swapi.dev/api/planets/1/", 44 | "films": [ 45 | "https://swapi.dev/api/films/2/", 46 | "https://swapi.dev/api/films/6/", 47 | "https://swapi.dev/api/films/3/", 48 | "https://swapi.dev/api/films/1/", 49 | "https://swapi.dev/api/films/7/" 50 | ], 51 | "species": [ 52 | "https://swapi.dev/api/species/1/" 53 | ], 54 | "vehicles": [ 55 | "https://swapi.dev/api/vehicles/14/", 56 | "https://swapi.dev/api/vehicles/30/" 57 | ], 58 | "starships": [ 59 | "https://swapi.dev/api/starships/12/", 60 | "https://swapi.dev/api/starships/22/" 61 | ], 62 | "created": "2014-12-09T13:50:51.644000Z", 63 | "edited": "2014-12-20T21:17:56.891000Z", 64 | "url": "https://swapi.dev/api/people/1/" 65 | } 66 |67 |
The Star Wars API, or "swapi" (Swah-pee) is the world's first quantified and programmatically-accessible data source for all the data from the Star Wars canon universe!
78 |We've taken all the rich contextual stuff from the universe and formatted into something easier to consume with software. Then we went and stuck an API on the front so you can access it all!
79 |All the data is accessible through our HTTP web API. Consult our documentation if you'd like to get started.
83 |Helper libraries for popular programming languages are also provided so you can consume swapi in your favourite programming language, in a style that suits you.
84 |swapi.co is not supported and maintained anymore. But since so many projects and tutorials used it as their educational 88 | playground, this is an "unofficial" branch.
89 |This project is open source and you can contribute on GitHub.
90 |