initial commit
This commit is contained in:
0
teamsnap/__init__.py
Normal file
0
teamsnap/__init__.py
Normal file
9
teamsnap/admin.py
Normal file
9
teamsnap/admin.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from django.contrib import admin
|
||||
from .models import User, Team, Location, Event, Member
|
||||
|
||||
# Register your models here.
|
||||
admin.site.register(User)
|
||||
admin.site.register(Team)
|
||||
admin.site.register(Event)
|
||||
admin.site.register(Location)
|
||||
admin.site.register(Member)
|
||||
6
teamsnap/apps.py
Normal file
6
teamsnap/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class TeamsnapConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'teamsnap'
|
||||
82
teamsnap/migrations/0001_initial.py
Normal file
82
teamsnap/migrations/0001_initial.py
Normal file
@@ -0,0 +1,82 @@
|
||||
# Generated by Django 3.2.6 on 2021-11-20 23:53
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('teams', '0001_initial'),
|
||||
('players', '0003_player_team'),
|
||||
('venues', '0001_initial'),
|
||||
('events', '0004_delete_availability'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='User',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('teamsnap_id', models.CharField(max_length=10)),
|
||||
('access_token', models.CharField(max_length=50)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Team',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('teamsnap_id', models.CharField(max_length=10)),
|
||||
('name', models.CharField(max_length=50, null=True)),
|
||||
('team', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='teams.team')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Member',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('teamsnap_id', models.CharField(max_length=10)),
|
||||
('name', models.CharField(max_length=50, null=True)),
|
||||
('player', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='players.player')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Location',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('teamsnap_id', models.CharField(max_length=10)),
|
||||
('name', models.CharField(max_length=50, null=True)),
|
||||
('venue', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='venues.venue')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Event',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('teamsnap_id', models.CharField(max_length=10)),
|
||||
('name', models.CharField(max_length=50, null=True)),
|
||||
('label', models.CharField(max_length=50, null=True)),
|
||||
('start_date', models.DateTimeField(null=True)),
|
||||
('event', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='events.event')),
|
||||
('location', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='teamsnap.location')),
|
||||
('opponent', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='teamsnap.team')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
43
teamsnap/migrations/0002_auto_20211121_0035.py
Normal file
43
teamsnap/migrations/0002_auto_20211121_0035.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# Generated by Django 3.2.6 on 2021-11-21 00:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('teamsnap', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='formatted_title',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='teamsnap_id',
|
||||
field=models.CharField(max_length=10, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='location',
|
||||
name='teamsnap_id',
|
||||
field=models.CharField(max_length=10, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='member',
|
||||
name='teamsnap_id',
|
||||
field=models.CharField(max_length=10, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='team',
|
||||
name='teamsnap_id',
|
||||
field=models.CharField(max_length=10, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='teamsnap_id',
|
||||
field=models.CharField(max_length=10, unique=True),
|
||||
),
|
||||
]
|
||||
0
teamsnap/migrations/__init__.py
Normal file
0
teamsnap/migrations/__init__.py
Normal file
33
teamsnap/models.py
Normal file
33
teamsnap/models.py
Normal file
@@ -0,0 +1,33 @@
|
||||
from django.db import models
|
||||
import teams.models
|
||||
import venues.models
|
||||
import players.models
|
||||
import events.models
|
||||
|
||||
class TeamsnapBaseModel(models.Model):
|
||||
teamsnap_id = models.CharField(max_length=10, unique=True)
|
||||
name = models.CharField(max_length=50, null=True)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
class User(TeamsnapBaseModel):
|
||||
access_token = models.CharField(max_length = 50)
|
||||
name = None
|
||||
|
||||
class Team(TeamsnapBaseModel):
|
||||
team = models.ForeignKey(teams.models.Team, null=True, on_delete=models.CASCADE)
|
||||
|
||||
class Location(TeamsnapBaseModel):
|
||||
venue = models.ForeignKey(venues.models.Venue, null=True, on_delete=models.CASCADE)
|
||||
|
||||
class Member(TeamsnapBaseModel):
|
||||
player = models.ForeignKey(players.models.Player, null=True, on_delete=models.CASCADE)
|
||||
|
||||
class Event(TeamsnapBaseModel):
|
||||
event = models.ForeignKey(events.models.Event, null=True, on_delete=models.CASCADE)
|
||||
label = models.CharField(max_length = 50, null=True)
|
||||
start_date = models.DateTimeField(null=True)
|
||||
opponent = models.ForeignKey(Team, null=True, on_delete=models.CASCADE)
|
||||
location = models.ForeignKey(Location, null=True, on_delete=models.CASCADE)
|
||||
formatted_title = models.CharField(max_length = 50, null=True)
|
||||
3
teamsnap/teamsnap/__init__.py
Normal file
3
teamsnap/teamsnap/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .api import TeamSnap
|
||||
|
||||
__all__ = ['TeamSnap']
|
||||
109
teamsnap/teamsnap/api.py
Normal file
109
teamsnap/teamsnap/api.py
Normal file
@@ -0,0 +1,109 @@
|
||||
__all__ = ['TeamSnap', 'Team', 'Event', 'Availability', 'Member', 'Location', 'Me']
|
||||
from apiclient import APIClient, HeaderAuthentication, JsonResponseHandler
|
||||
|
||||
|
||||
class ApiObject():
|
||||
rel = None
|
||||
|
||||
def __init__(self, client, rel=rel, data={}):
|
||||
self.client = client
|
||||
self.data = data
|
||||
self.rel = rel
|
||||
|
||||
@classmethod
|
||||
def search(cls, client, **kwargs):
|
||||
results = client.query(cls.rel, "search", **kwargs)
|
||||
return [cls(client,rel=cls.rel, data=r) for r in results]
|
||||
|
||||
@classmethod
|
||||
def get(cls, client, id):
|
||||
r = client.get(f"{client.link(cls.rel)}/{id}")
|
||||
return cls(client, cls.rel, client.parse_response(r)[0])
|
||||
|
||||
class Me (ApiObject):
|
||||
rel = "me"
|
||||
|
||||
def __init__(self, client):
|
||||
super().__init__(client=client, rel=self.rel, data=client.get(client.link(self.rel)))
|
||||
|
||||
class Event (ApiObject):
|
||||
rel = "events"
|
||||
|
||||
class Team (ApiObject):
|
||||
rel = "teams"
|
||||
pass
|
||||
|
||||
class Availability (ApiObject):
|
||||
rel = "availabilities"
|
||||
pass
|
||||
|
||||
class Member (ApiObject):
|
||||
rel = "members"
|
||||
|
||||
class Location (ApiObject):
|
||||
rel = "locations"
|
||||
|
||||
class Opponent (ApiObject):
|
||||
rel = "opponents"
|
||||
|
||||
class TeamSnap(APIClient):
|
||||
base_url = 'https://api.teamsnap.com/v3'
|
||||
|
||||
def __init__(self, token, *args, **kwargs):
|
||||
super().__init__(*args,
|
||||
authentication_method=HeaderAuthentication(token=token),
|
||||
response_handler=JsonResponseHandler,
|
||||
**kwargs)
|
||||
self._root_collection = self.get(self.base_url)['collection']
|
||||
self._links = self._by_rel(self.base_url, 'links')
|
||||
self._queries = self._by_rel(self.base_url, 'queries')
|
||||
self._commands = self._by_rel(self.base_url, 'commands')
|
||||
pass
|
||||
|
||||
def link(self, link_name):
|
||||
d = {l['rel']:l['href'] for l in self._root_collection["links"]}
|
||||
return d.get(link_name)
|
||||
|
||||
def _by_rel (self, url, k):
|
||||
try:
|
||||
{l['rel']: l for l in self._root_collection[k]}
|
||||
except Exception as e:
|
||||
return {}
|
||||
self.get(url)['collection'][k]
|
||||
return {l['rel']:l for l in self.get(url)['collection'][k]}
|
||||
|
||||
def query (self, rel, query, **kwargs):
|
||||
queries = self._by_rel(self._get_href(rel), 'queries')
|
||||
response = self.get(self._get_href(query, queries), params=kwargs)
|
||||
return self.parse_response(response)
|
||||
|
||||
def command (self, rel, command, **kwargs):
|
||||
commands = self._by_rel(self._get_href(rel), 'commands')
|
||||
response = self.get(self._get_href(command, commands), params=kwargs)
|
||||
return self.parse_response(response)
|
||||
|
||||
def _get_href (self, rel: str, links:dict = None, url = base_url) -> str:
|
||||
"""returns a hyperlink from a the links dictionary. Each item in the links dictionary is a
|
||||
dictionary with a rel and href key"""
|
||||
if links is None: links = self._by_rel(url, 'links')
|
||||
link = links[rel]['href']
|
||||
return link
|
||||
|
||||
def get_item (self, rel, id):
|
||||
r = self.get(f"{self.link(rel)}/{id}")
|
||||
return self.parse_response(r)[0]
|
||||
|
||||
@classmethod
|
||||
def parse_response(self, response):
|
||||
result = []
|
||||
items = [item['data'] for item in response['collection'].get('items',[])]
|
||||
for item in response['collection'].get('items',[]):
|
||||
details = {}
|
||||
for detail in item['data']:
|
||||
# TODO type casting and validation based on item['type']
|
||||
details[detail['name']] = detail['value']
|
||||
result.append(details)
|
||||
|
||||
return result
|
||||
# return [{detail['name']: detail['value'] for detail in item} for item in items]
|
||||
|
||||
23
teamsnap/templates/teamsnap/event_list.html
Normal file
23
teamsnap/templates/teamsnap/event_list.html
Normal file
@@ -0,0 +1,23 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %} {{ title }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{{ title }}</h1>
|
||||
<ol class="list-group">
|
||||
{% for item in object_list %}
|
||||
<li class="list-group-item">
|
||||
<span class="fs-5 fw-bold">{{ item.formatted_title }}</span>
|
||||
<span class="fs-6">{{ item.subtitle }}</span>
|
||||
{# {% if item.body %}#}
|
||||
{# <br><span class="fs-6">{{ item.body }}</span>#}
|
||||
<br>{{ item.start_date|date:"D, M j, g:i A" }},<br>{{item.location.name}}
|
||||
{# {% endif %}#}
|
||||
<br>
|
||||
{% for button in item.buttons %}
|
||||
<a class="btn btn-primary btn-sm" href="{{ button.href }}" role="button">{{ button.label }}</a>
|
||||
{% endfor %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
{% endblock %}
|
||||
3
teamsnap/tests.py
Normal file
3
teamsnap/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
9
teamsnap/urls.py
Normal file
9
teamsnap/urls.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from django.urls import path, include
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path('events', views.EventsListView.as_view(), name="teamsnap events list")
|
||||
]
|
||||
15
teamsnap/views.py
Normal file
15
teamsnap/views.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# from .teamsnap.api import TeamSnap, Team, Event, Availability
|
||||
from .models import User, Member, Team, Event, Location
|
||||
from django.views.generic.list import ListView
|
||||
|
||||
|
||||
class EventsListView(ListView):
|
||||
model = Event
|
||||
|
||||
class TeamListView(ListView):
|
||||
model = Team
|
||||
|
||||
class LocationListView(ListView):
|
||||
model = Location
|
||||
Reference in New Issue
Block a user