summaryrefslogtreecommitdiff
path: root/app/accounts
diff options
context:
space:
mode:
Diffstat (limited to 'app/accounts')
-rw-r--r--app/accounts/__init__.py1
-rw-r--r--app/accounts/admin.py13
-rw-r--r--app/accounts/apps.py8
-rw-r--r--app/accounts/forms.py28
-rw-r--r--app/accounts/models.py33
-rw-r--r--app/accounts/signals.py12
-rw-r--r--app/accounts/tests/__init__.py0
-rw-r--r--app/accounts/tests/test_models.py13
-rw-r--r--app/accounts/tests/test_views.py23
-rw-r--r--app/accounts/urls.py18
-rw-r--r--app/accounts/views.py32
11 files changed, 181 insertions, 0 deletions
diff --git a/app/accounts/__init__.py b/app/accounts/__init__.py
new file mode 100644
index 0000000..9332741
--- /dev/null
+++ b/app/accounts/__init__.py
@@ -0,0 +1 @@
+default_app_config = 'accounts.apps.AccountAppConfig'
diff --git a/app/accounts/admin.py b/app/accounts/admin.py
new file mode 100644
index 0000000..25f873b
--- /dev/null
+++ b/app/accounts/admin.py
@@ -0,0 +1,13 @@
+from django.contrib import admin
+
+from .models import User, UserProfile
+
+
+@admin.register(User)
+class UserAdmin(admin.ModelAdmin):
+ pass
+
+
+@admin.register(UserProfile)
+class UserProfileAdmin(admin.ModelAdmin):
+ pass
diff --git a/app/accounts/apps.py b/app/accounts/apps.py
new file mode 100644
index 0000000..9a7d5ba
--- /dev/null
+++ b/app/accounts/apps.py
@@ -0,0 +1,8 @@
+from django.apps import AppConfig
+
+
+class AccountAppConfig(AppConfig):
+ name = 'accounts'
+
+ def ready(self):
+ import accounts.signals
diff --git a/app/accounts/forms.py b/app/accounts/forms.py
new file mode 100644
index 0000000..2da08cb
--- /dev/null
+++ b/app/accounts/forms.py
@@ -0,0 +1,28 @@
+from django import forms
+from django.utils.translation import ugettext_lazy as _
+from django_registration.forms import RegistrationForm
+
+from .models import User, UserProfile
+
+
+class UserForm(RegistrationForm):
+ class Meta(RegistrationForm.Meta):
+ model = User
+
+
+class ProfileForm(forms.ModelForm):
+ class Meta:
+ model = UserProfile
+ fields = ['bio', 'photo', 'website']
+ labels = {
+ "photo": _("Profile photo"),
+ "bio": _("Bio. A little about you. links are fine, line breaks are not. Keep it short and sweet, 350 characters max"),
+ "website": _("If you have a personal website, plug it in here."),
+ }
+ widgets = {
+ 'bio': forms.Textarea(attrs={'cols': 104, 'rows': 10, 'class': 'textarea-rounded'}),
+ }
+
+ def __init__(self, *args, **kwargs):
+ self.user = kwargs.pop("user", None)
+ super(ProfileForm, self).__init__(*args, **kwargs)
diff --git a/app/accounts/models.py b/app/accounts/models.py
new file mode 100644
index 0000000..feb20bf
--- /dev/null
+++ b/app/accounts/models.py
@@ -0,0 +1,33 @@
+from django.db import models
+from django.urls import reverse
+from django.contrib.auth.models import AbstractUser
+from django.utils.functional import cached_property
+
+from notes.models import Notebook
+
+
+class User(AbstractUser):
+ pass
+
+ class Meta:
+ ordering = ['-date_joined']
+
+
+class UserProfile(models.Model):
+ user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
+ photo = models.ImageField(upload_to='profile', null=True, blank=True)
+ website = models.CharField(max_length=300, blank=True, default='')
+ location = models.CharField(max_length=300, blank=True, default='')
+ bio = models.CharField(max_length=350, blank=True, default='')
+ #default_note_folder = models.ForeignKey('notes.Notebook', null=True, on_delete=models.SET_NULL)
+ #default_note_public = models.BooleanField(default=False)
+
+ def __str__(self):
+ return self.user.username
+
+ def get_absolute_url(self):
+ return reverse("accounts:settings")
+
+ @cached_property
+ def get_notebook_list(self):
+ return Notebook.objects.filter(owner=self.user).select_related().annotate(note_count=models.Count('note'))[:8]
diff --git a/app/accounts/signals.py b/app/accounts/signals.py
new file mode 100644
index 0000000..837a7ed
--- /dev/null
+++ b/app/accounts/signals.py
@@ -0,0 +1,12 @@
+from django.db.models.signals import post_save
+from django.dispatch import receiver
+
+from .models import User, UserProfile
+
+
+@receiver(post_save, sender=User)
+def create_profile(sender, update_fields, created, instance, **kwargs):
+ """ creates a blank profile when a new user signs up """
+ if created:
+ user_profile = UserProfile.objects.create(user=instance)
+ user_profile.save()
diff --git a/app/accounts/tests/__init__.py b/app/accounts/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/accounts/tests/__init__.py
diff --git a/app/accounts/tests/test_models.py b/app/accounts/tests/test_models.py
new file mode 100644
index 0000000..f9b33f6
--- /dev/null
+++ b/app/accounts/tests/test_models.py
@@ -0,0 +1,13 @@
+from django.test import TestCase
+from mixer.backend.django import mixer
+
+from accounts.models import User, UserProfile
+
+
+class UserProfileModelTest(TestCase):
+
+ def test_string_representation(self):
+ user = mixer.blend(User, username='test')
+ user.save()
+ profile = UserProfile.objects.get(user=user)
+ self.assertEqual(str(profile), str(user.username))
diff --git a/app/accounts/tests/test_views.py b/app/accounts/tests/test_views.py
new file mode 100644
index 0000000..39dcb31
--- /dev/null
+++ b/app/accounts/tests/test_views.py
@@ -0,0 +1,23 @@
+from django.test import Client
+from django.test import RequestFactory, TestCase
+from mixer.backend.django import mixer
+
+from accounts.models import User
+from accounts.views import ProfileView
+
+
+class ProfileViewTest(TestCase):
+ def setUp(self):
+ # Every test needs access to the request factory.
+ self.factory = RequestFactory()
+ self.user = mixer.blend(User, username='tpynchon', password="gravity")
+
+ def test_profile_view(self):
+ request = self.factory.get('/settings/')
+ request.user = self.user
+ response = ProfileView.as_view()(request)
+ self.assertEqual(response.status_code, 200)
+ response.render()
+ html = response.content.decode('utf8')
+ self.assertTrue(html.startswith('<!DOCTYPE html>'))
+ self.assertIn('<h1>Account Settings</h1>', html)
diff --git a/app/accounts/urls.py b/app/accounts/urls.py
new file mode 100644
index 0000000..5cad311
--- /dev/null
+++ b/app/accounts/urls.py
@@ -0,0 +1,18 @@
+from django.urls import path
+
+from . import views
+
+app_name = "accounts"
+
+urlpatterns = [
+ path(
+ r'change-profile/',
+ views.ProfileView.as_view(),
+ name="change-profile"
+ ),
+ path(
+ r'',
+ views.SettingsListView.as_view(),
+ name="settings"
+ ),
+]
diff --git a/app/accounts/views.py b/app/accounts/views.py
new file mode 100644
index 0000000..75bb933
--- /dev/null
+++ b/app/accounts/views.py
@@ -0,0 +1,32 @@
+from django.views.generic import UpdateView, DetailView
+from django.utils.decorators import method_decorator
+from django.contrib.auth.decorators import login_required
+
+from .models import UserProfile
+from .forms import ProfileForm
+
+
+@method_decorator(login_required, name='dispatch')
+class UpdateViewWithUser(UpdateView):
+
+ def get_form_kwargs(self, **kwargs):
+ kwargs = super().get_form_kwargs(**kwargs)
+ kwargs.update({'user': self.request.user})
+ return kwargs
+
+
+class ProfileView(UpdateViewWithUser):
+ model = UserProfile
+ form_class = ProfileForm
+ template_name = "accounts/change-settings.html"
+
+ def get_object(self):
+ return self.request.user.profile
+
+
+class SettingsListView(DetailView):
+ model = UserProfile
+ template_name = "accounts/profile.html"
+
+ def get_object(self):
+ return self.request.user.profile