API Timeline ajoutée !
This commit is contained in:
parent
95d8b30c3c
commit
92ea2f6af7
@ -4,7 +4,7 @@ Current version (0.2) :
|
||||
- Renommage des consoles en « plateformes »
|
||||
- Activation des requêtes CORS pour permettre à une autre application d'accéder à l'API
|
||||
- MàJ vers Django 1.11.5
|
||||
- Activation d'une API (pour les consoles et les jeux) accessible par l'administrateur (avec documentation)
|
||||
- Activation d'une API accessible par l'administrateur (avec documentation)
|
||||
- Ajout d'une page d'accueil listant les jeux vidéos en cours, la liste complète et les 5 dernières activités sur ces derniers triées par date
|
||||
- Nouveau champ 'note' pour la progression dans le jeu
|
||||
- Omission de l'état "Nouveau" pour les jeux
|
||||
|
5
TODO
5
TODO
@ -1,6 +1,7 @@
|
||||
# À faire
|
||||
|
||||
* Ajouter des help_text à tous les champs + classes enfants. Les traduire.
|
||||
* Test API sur l'ordre de tri des date pour les Timeline
|
||||
* Bug? : dans la documentation de l'API, les champs "required" sont peu nombreux. Regarder s'il faut faire quelque chose de particulier pour la Timeline (sur date et status) et Game (sur status).
|
||||
* étudier la possibilité à l'utilisateur, via des variables d'environnement, de configurer un email, une autre BDD, etc.
|
||||
|
||||
## Dépôt / code
|
||||
@ -11,7 +12,6 @@
|
||||
|
||||
* Unplayed ne doit pas s'afficher si on a un état différent de Unfinished
|
||||
* Gérer les figurines (trouver le nom de l'objet qui permet de les regrouper, par exemple Skylanders, Disney Infinity, etc.)
|
||||
* API django rest framework
|
||||
* ajouter une date d'obtention du jeu vidéo (par défaut aujourd'hui) => est-ce vraiment utile si on a la Timeline ?
|
||||
|
||||
## Tests
|
||||
@ -30,7 +30,6 @@
|
||||
|
||||
## Documentation
|
||||
|
||||
* documentation API
|
||||
* documentation du projet : installation par Docker, utilisation des variables d'environnement pour changer différentes choses, etc.
|
||||
|
||||
# Idée
|
||||
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 0.1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-09-16 15:15+0000\n"
|
||||
"POT-Creation-Date: 2017-09-16 21:58+0000\n"
|
||||
"PO-Revision-Date: 2017-09-16 17:16+0200\n"
|
||||
"Last-Translator: Olivier DOSSMANN <git@dossmann.net>\n"
|
||||
"Language-Team: \n"
|
||||
|
@ -16,7 +16,12 @@ Including another URLconf
|
||||
from django.conf.urls import url, include
|
||||
from django.contrib import admin
|
||||
from collection import __version__ as app_version
|
||||
from games.views import GameList, GameViewSet, PlatformViewSet
|
||||
from games.views import (
|
||||
GameList,
|
||||
GameViewSet,
|
||||
GameTimelineViewSet,
|
||||
PlatformViewSet,
|
||||
)
|
||||
from rest_framework import routers
|
||||
from rest_framework.documentation import include_docs_urls
|
||||
|
||||
@ -28,6 +33,10 @@ admin.site.site_header = '%s %s' % (admin.site.site_title, app_version)
|
||||
router = routers.DefaultRouter()
|
||||
router.register(r'games', GameViewSet)
|
||||
router.register(r'platforms', PlatformViewSet)
|
||||
router.register(
|
||||
r'game_timelines',
|
||||
GameTimelineViewSet,
|
||||
base_name='game_timeline')
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', GameList.as_view(), name='homepage'),
|
||||
|
@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 0.1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-09-16 15:15+0000\n"
|
||||
"PO-Revision-Date: 2017-09-16 17:17+0200\n"
|
||||
"POT-Creation-Date: 2017-09-16 21:58+0000\n"
|
||||
"PO-Revision-Date: 2017-09-16 23:59+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: fr\n"
|
||||
@ -55,7 +55,7 @@ msgstr "plateformes"
|
||||
|
||||
#: collection/games/models.py:20
|
||||
msgid "Most used platform name."
|
||||
msgstr "Nom de plateforme le plus utilisé."
|
||||
msgstr "Nom de plateforme le plus communément utilisé."
|
||||
|
||||
#: collection/games/models.py:40
|
||||
msgid "Beaten"
|
||||
@ -117,14 +117,38 @@ msgstr "jeu"
|
||||
msgid "games"
|
||||
msgstr "jeux"
|
||||
|
||||
#: collection/games/models.py:84
|
||||
#: collection/games/models.py:77
|
||||
msgid "Game title"
|
||||
msgstr "Titre du jeu"
|
||||
|
||||
#: collection/games/models.py:78
|
||||
msgid "Game running platform"
|
||||
msgstr "Plateforme sur laquelle se lance le jeu"
|
||||
|
||||
#: collection/games/models.py:79
|
||||
msgid "Game progression"
|
||||
msgstr "Progression du jeu"
|
||||
|
||||
#: collection/games/models.py:90
|
||||
msgid "Timeline"
|
||||
msgstr "Chronologie"
|
||||
|
||||
#: collection/games/models.py:85
|
||||
#: collection/games/models.py:91
|
||||
msgid "Timelines"
|
||||
msgstr "Chronologies"
|
||||
|
||||
#: collection/games/models.py:95
|
||||
msgid "Status change date"
|
||||
msgstr "Date de changement de statut"
|
||||
|
||||
#: collection/games/models.py:96
|
||||
msgid "Which game?"
|
||||
msgstr "Quel jeu ?"
|
||||
|
||||
#: collection/games/models.py:98
|
||||
msgid "New status for this game at the given date"
|
||||
msgstr "Nouveau statut pour ce jeu à la date donnée"
|
||||
|
||||
#: collection/games/templates/games/index.html:5
|
||||
msgid "Games"
|
||||
msgstr "Jeux"
|
||||
|
@ -0,0 +1,61 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.5 on 2017-09-16 21:55
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('games', '0008_rename_console_to_platform'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='platform',
|
||||
options={'ordering': ('name',), 'verbose_name': 'plateforme', 'verbose_name_plural': 'plateformes'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='game',
|
||||
name='collection',
|
||||
field=models.ForeignKey(help_text='Game running platform', on_delete=django.db.models.deletion.CASCADE, related_name='games', to='games.Platform', verbose_name='plateforme'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='game',
|
||||
name='name',
|
||||
field=models.CharField(help_text='Game title', max_length=255, verbose_name='nom'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='game',
|
||||
name='note',
|
||||
field=models.CharField(blank=True, help_text='Courte note affichée à ceux qui vous suive.', max_length=150, null=True, verbose_name='Note de progression'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='game',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('created', 'Nouveau'), ('beaten', 'Terminé (quête principale)'), ('completed', 'Terminé complètement'), ('excluded', 'Exclu'), ('mastered', 'Usé / Épuisé'), ('unfinished', 'Inachevé')], default='unfinished', help_text='Game progression', max_length=30, verbose_name='état'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='platform',
|
||||
name='name',
|
||||
field=models.CharField(help_text='Nom de plateforme le plus utilisé.', max_length=255, verbose_name='nom'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='timeline',
|
||||
name='date',
|
||||
field=models.DateField(default=datetime.datetime.now, help_text='Status change date', verbose_name='date'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='timeline',
|
||||
name='item',
|
||||
field=models.ForeignKey(help_text='Which game?', on_delete=django.db.models.deletion.CASCADE, to='games.Game', verbose_name='jeu'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='timeline',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('created', 'Nouveau'), ('beaten', 'Terminé (quête principale)'), ('completed', 'Terminé complètement'), ('excluded', 'Exclu'), ('mastered', 'Usé / Épuisé'), ('unfinished', 'Inachevé')], default='created', help_text='New status for this game at the given date', max_length=30, verbose_name='état'),
|
||||
),
|
||||
]
|
@ -73,6 +73,12 @@ class Game(Item):
|
||||
verbose_name_plural = _('games')
|
||||
|
||||
|
||||
# Redefine help_text (for documentation, API, etc.)
|
||||
Game._meta.get_field('name').help_text = _('Game title')
|
||||
Game._meta.get_field('collection').help_text = _('Game running platform')
|
||||
Game._meta.get_field('status').help_text = _('Game progression')
|
||||
|
||||
|
||||
class Timeline(BaseTimeline):
|
||||
TARGET_MODEL = 'games.Game'
|
||||
TARGET_VERBOSE_NAME = 'game'
|
||||
@ -83,3 +89,10 @@ class Timeline(BaseTimeline):
|
||||
ordering = ('-date',)
|
||||
verbose_name = _('Timeline')
|
||||
verbose_name_plural = _('Timelines')
|
||||
|
||||
|
||||
# Redefine help_text (for documentation, API, etc.)
|
||||
Timeline._meta.get_field('date').help_text = _('Status change date')
|
||||
Timeline._meta.get_field('item').help_text = _('Which game?')
|
||||
Timeline._meta.get_field('status').help_text = _(
|
||||
'New status for this game at the given date')
|
||||
|
@ -1,4 +1,4 @@
|
||||
from games.models import Game, Platform
|
||||
from games.models import Game, Platform, Timeline
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
@ -16,6 +16,16 @@ class GameSerializer(serializers.HyperlinkedModelSerializer):
|
||||
)
|
||||
|
||||
|
||||
class GameTimelineSerializer(serializers.HyperlinkedModelSerializer):
|
||||
class Meta:
|
||||
model = Timeline
|
||||
fields = (
|
||||
'date',
|
||||
'item',
|
||||
'status',
|
||||
)
|
||||
|
||||
|
||||
class PlatformSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Platform
|
||||
|
@ -1,8 +1,9 @@
|
||||
from django.contrib.auth.models import User
|
||||
from django.urls import reverse
|
||||
from games.models import Game, Platform
|
||||
from games.models import Game, Platform, Timeline
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase, force_authenticate
|
||||
from datetime import date
|
||||
import json
|
||||
|
||||
|
||||
@ -112,3 +113,46 @@ class GameTest(APITestCase):
|
||||
response = self.client.post(url, data, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(Game.objects.count(), 0)
|
||||
|
||||
|
||||
class TimelineTest(APITestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
cls.superuser = User.objects.create_superuser(
|
||||
'admin',
|
||||
'admin@localhost',
|
||||
'admin')
|
||||
|
||||
def test_create_timeline(self):
|
||||
"""
|
||||
Check we can create a timeline object.
|
||||
"""
|
||||
console = Platform.objects.create(name='BestPlatform4Ever')
|
||||
game = Game.objects.create(
|
||||
name='Cherubin',
|
||||
collection=console,
|
||||
status='created')
|
||||
|
||||
# By default a timeline is generated with current datetime.
|
||||
# We need to change this date.
|
||||
timeline = Timeline.objects.first()
|
||||
timeline.date = date(2017, 9, 15)
|
||||
timeline.save()
|
||||
|
||||
url = reverse('game_timeline-list')
|
||||
data = {
|
||||
'item': reverse('game-detail', kwargs={'pk': game.id}),
|
||||
'date': date(2017, 9, 16),
|
||||
'status': 'beaten',
|
||||
}
|
||||
self.client.force_authenticate(user=self.superuser)
|
||||
response = self.client.post(url, data, format='json')
|
||||
self.assertEqual(
|
||||
response.status_code,
|
||||
status.HTTP_201_CREATED,
|
||||
response.content)
|
||||
self.assertEqual(Timeline.objects.count(), 2)
|
||||
|
||||
def test_sorted_game_timeline(self):
|
||||
# TODO: Check descending date order.
|
||||
pass
|
||||
|
@ -1,10 +1,14 @@
|
||||
from django.db.models import Q
|
||||
from django.views.generic import ListView
|
||||
from rest_framework import viewsets
|
||||
from .serializers import GameSerializer, PlatformSerializer
|
||||
|
||||
from .serializers import (
|
||||
GameSerializer,
|
||||
GameTimelineSerializer,
|
||||
PlatformSerializer
|
||||
)
|
||||
from .models import Game, Platform, Timeline
|
||||
|
||||
|
||||
class PlatformViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
API endpoints that allows platforms to be edited or viewed.
|
||||
@ -22,12 +26,32 @@ class PlatformViewSet(viewsets.ModelViewSet):
|
||||
serializer_class = PlatformSerializer
|
||||
|
||||
|
||||
class GameTimelineViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
API endpoints that allows to keep games life.
|
||||
BE CAREFUL. You shouldn't change these entries because they're generated
|
||||
by Game status change. It could be only useful to change the acquisition
|
||||
date. Not more.
|
||||
|
||||
retrieve:
|
||||
Return the given timeline entry.
|
||||
|
||||
list:
|
||||
Return a list of timeline entries sorted by date in descending order.
|
||||
|
||||
create:
|
||||
Create a new timeline instance.
|
||||
"""
|
||||
queryset = Timeline.objects.all().order_by('-date')
|
||||
serializer_class = GameTimelineSerializer
|
||||
|
||||
|
||||
class GameViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
API endpoints that allows games to be edited or viewed.
|
||||
|
||||
retrieve:
|
||||
Return the given game
|
||||
Return the given game.
|
||||
|
||||
list:
|
||||
Return a list of all existing games ordered by name.
|
||||
|
Loading…
Reference in New Issue
Block a user