From d47ec4635ecfb5b199ef9e1374438fb3059ae5fa Mon Sep 17 00:00:00 2001 From: Michael Hall Date: Fri, 2 Feb 2018 22:34:08 -0500 Subject: [PATCH] Add accounts app and ability to give badges to users --- accounts/__init__.py | 0 accounts/admin.py | 18 +++++ accounts/apps.py | 5 ++ accounts/migrations/0001_initial.py | 55 ++++++++++++++ accounts/migrations/__init__.py | 0 accounts/models.py | 70 ++++++++++++++++++ accounts/tests.py | 3 + accounts/views.py | 3 + get_together/settings.py | 1 + get_together/static/img/badges/gold_tier.png | Bin 0 -> 2097 bytes .../static/img/badges/silver_tier.png | Bin 0 -> 1058 bytes .../get_together/events/show_event.html | 19 ++++- .../get_together/teams/show_team.html | 19 ++++- 13 files changed, 189 insertions(+), 4 deletions(-) create mode 100644 accounts/__init__.py create mode 100644 accounts/admin.py create mode 100644 accounts/apps.py create mode 100644 accounts/migrations/0001_initial.py create mode 100644 accounts/migrations/__init__.py create mode 100644 accounts/models.py create mode 100644 accounts/tests.py create mode 100644 accounts/views.py create mode 100644 get_together/static/img/badges/gold_tier.png create mode 100644 get_together/static/img/badges/silver_tier.png diff --git a/accounts/__init__.py b/accounts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/accounts/admin.py b/accounts/admin.py new file mode 100644 index 0000000..51e6cef --- /dev/null +++ b/accounts/admin.py @@ -0,0 +1,18 @@ +from django.contrib import admin + +from .models import Account, Badge, BadgeGrant + +# Register your models here. +class AccountAdmin(admin.ModelAdmin): + list_display = ('user', 'acctname') +admin.site.register(Account, AccountAdmin) + +class BadgeAdmin(admin.ModelAdmin): + list_display = ('name', 'img_url') +admin.site.register(Badge, BadgeAdmin) + +class GrantAdmin(admin.ModelAdmin): + list_display = ('badge', 'account', 'expires', 'granted_by') +admin.site.register(BadgeGrant, GrantAdmin) + + diff --git a/accounts/apps.py b/accounts/apps.py new file mode 100644 index 0000000..9b3fc5a --- /dev/null +++ b/accounts/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class AccountsConfig(AppConfig): + name = 'accounts' diff --git a/accounts/migrations/0001_initial.py b/accounts/migrations/0001_initial.py new file mode 100644 index 0000000..113aebb --- /dev/null +++ b/accounts/migrations/0001_initial.py @@ -0,0 +1,55 @@ +# Generated by Django 2.0 on 2018-02-02 22:05 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Account', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('acctname', models.CharField(blank=True, max_length=150, verbose_name='Account Name')), + ], + options={ + 'ordering': ('user__username',), + }, + ), + migrations.CreateModel( + name='Badge', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=64, verbose_name='Badge Name')), + ('img_url', models.URLField(verbose_name='Badge Image')), + ], + ), + migrations.CreateModel( + name='BadgeGrant', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('expires', models.DateTimeField()), + ('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='accounts.Account')), + ('badge', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='accounts.Badge')), + ('granted_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.AddField( + model_name='account', + name='badges', + field=models.ManyToManyField(through='accounts.BadgeGrant', to='accounts.Badge'), + ), + migrations.AddField( + model_name='account', + name='user', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/accounts/migrations/__init__.py b/accounts/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/accounts/models.py b/accounts/models.py new file mode 100644 index 0000000..08cd51d --- /dev/null +++ b/accounts/models.py @@ -0,0 +1,70 @@ +from django.db import models +from django.contrib.sites.models import Site +from django.contrib.auth.models import User, Group, AnonymousUser +from django.utils.translation import ugettext_lazy as _ + +import pytz +import datetime +import hashlib + +class Account(models.Model): + " Store account information about a user " + + user = models.OneToOneField(User, on_delete=models.CASCADE) + acctname = models.CharField(_("Account Name"), max_length=150, blank=True) + + badges = models.ManyToManyField('Badge', through='BadgeGrant') + + class Meta: + ordering = ('user__username',) + + def __str__(self): + try: + if self.acctname: + return self.acctname + return "%s" % self.user.username + except: + return "Unknown Account" + + +def _getUserAccount(self): + if not self.is_authenticated: + return Account() + + profile, created = Account.objects.get_or_create(user=self) + + if created: + if self.first_name: + if self.last_name: + profile.acctname = '%s %s' % (self.first_name, self.last_name) + else: + profile.acctname = self.first_name + + profile.save() + + return profile + +def _getAnonAccount(self): + return Account(acctname=_('Anonymous User')) + +User.account = property(_getUserAccount) +AnonymousUser.account = property(_getAnonAccount) + +class Badge(models.Model): + name = models.CharField(_('Badge Name'), max_length=64, blank=False, null=False) + img_url = models.URLField(_('Badge Image'), blank=False, null=False) + + def __str__(self): + return self.name + +class BadgeGrant(models.Model): + badge = models.ForeignKey(Badge, on_delete=models.CASCADE) + account = models.ForeignKey(Account, on_delete=models.CASCADE) + + expires = models.DateTimeField() + granted_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) + + def __str__(self): + return '%s for %s' % (self.badge.name, self.account.acctname) + + diff --git a/accounts/tests.py b/accounts/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/accounts/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/accounts/views.py b/accounts/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/accounts/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/get_together/settings.py b/get_together/settings.py index 54a1a72..fea1042 100644 --- a/get_together/settings.py +++ b/get_together/settings.py @@ -46,6 +46,7 @@ INSTALLED_APPS = [ 'get_together', 'events', + 'accounts', ] LOGIN_URL = 'login' diff --git a/get_together/static/img/badges/gold_tier.png b/get_together/static/img/badges/gold_tier.png new file mode 100644 index 0000000000000000000000000000000000000000..2da7c5d2184ebd938e44f5249093e7aff8f1296f GIT binary patch literal 2097 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 literal 0 HcmV?d00001 diff --git a/get_together/templates/get_together/events/show_event.html b/get_together/templates/get_together/events/show_event.html index ddbe1b6..9291a8c 100644 --- a/get_together/templates/get_together/events/show_event.html +++ b/get_together/templates/get_together/events/show_event.html @@ -1,6 +1,20 @@ {% extends "get_together/base.html" %} {% load markup %} +{% block styles %} + +{% endblock %} + {% block content %}
@@ -38,8 +52,9 @@
{% for attendee in attendee_list %}
-
- +
+ + {% for badge in attendee.user.user.account.badges.all %}{% endfor %}
{{attendee.user}} {{ attendee.status_name }}
{% if attendee.role > 0 %}{{ attendee.role_name }}{% endif %} diff --git a/get_together/templates/get_together/teams/show_team.html b/get_together/templates/get_together/teams/show_team.html index 01a9efe..e3a2567 100644 --- a/get_together/templates/get_together/teams/show_team.html +++ b/get_together/templates/get_together/teams/show_team.html @@ -1,6 +1,20 @@ {% extends "get_together/base.html" %} {% load markup %} +{% block styles %} + +{% endblock %} + {% block content %}
@@ -43,8 +57,9 @@

Members


{% for member in member_list %}
-
- +
+ + {% for badge in member.user.user.account.badges.all %}{% endfor %}
{{member.user}}
{% if member.role > 0 %}{{ member.role_name }}{% endif %}