aboutsummaryrefslogtreecommitdiff
path: root/apps/notes
diff options
context:
space:
mode:
authorluxagraf <sng@luxagraf.net>2018-11-14 13:17:42 -0600
committerluxagraf <sng@luxagraf.net>2018-11-14 13:17:42 -0600
commita0b95dc2dfb84c682bb8f677e5d471f84e5028fe (patch)
tree6dd1919856f736c5b644270d59b57e4bb20336c5 /apps/notes
wrote out basic notes skeleton
Diffstat (limited to 'apps/notes')
-rw-r--r--apps/notes/__init__.py0
-rw-r--r--apps/notes/forms.py17
-rw-r--r--apps/notes/migrations/0001_initial.py38
-rw-r--r--apps/notes/migrations/0002_auto_20181111_1825.py31
-rw-r--r--apps/notes/migrations/0003_note_folder.py19
-rw-r--r--apps/notes/migrations/__init__.py0
-rw-r--r--apps/notes/models.py38
-rw-r--r--apps/notes/serializers.py18
-rw-r--r--apps/notes/tests/__init__.py1
-rw-r--r--apps/notes/tests/test_models.py30
-rw-r--r--apps/notes/tests/test_views.py57
-rw-r--r--apps/notes/urls.py18
-rw-r--r--apps/notes/views.py41
13 files changed, 308 insertions, 0 deletions
diff --git a/apps/notes/__init__.py b/apps/notes/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/apps/notes/__init__.py
diff --git a/apps/notes/forms.py b/apps/notes/forms.py
new file mode 100644
index 0000000..6a27ec9
--- /dev/null
+++ b/apps/notes/forms.py
@@ -0,0 +1,17 @@
+from django import forms
+from django.utils.translation import ugettext_lazy as _
+
+from .models import Note
+
+
+class NoteForm(forms.ModelForm):
+ class Meta:
+ model = Note
+ fields = ['title', 'body_markdown', 'url', 'tags']
+ labels = {
+ "body_markdown": _("Note"),
+ }
+
+ def __init__(self, *args, **kwargs):
+ self.user = kwargs.pop("user", None)
+ super(NoteForm, self).__init__(*args, **kwargs)
diff --git a/apps/notes/migrations/0001_initial.py b/apps/notes/migrations/0001_initial.py
new file mode 100644
index 0000000..3f04eb7
--- /dev/null
+++ b/apps/notes/migrations/0001_initial.py
@@ -0,0 +1,38 @@
+# Generated by Django 2.1.2 on 2018-11-11 18:01
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+import taggit.managers
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('taggit', '0002_auto_20150616_2121'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Folder',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=250)),
+ ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Note',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('title', models.CharField(max_length=250)),
+ ('body_markdown', models.TextField(null=True)),
+ ('url', models.CharField(max_length=250)),
+ ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ('tags', taggit.managers.TaggableManager(blank=True, help_text='Tags', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags')),
+ ],
+ ),
+ ]
diff --git a/apps/notes/migrations/0002_auto_20181111_1825.py b/apps/notes/migrations/0002_auto_20181111_1825.py
new file mode 100644
index 0000000..a7bc1c7
--- /dev/null
+++ b/apps/notes/migrations/0002_auto_20181111_1825.py
@@ -0,0 +1,31 @@
+# Generated by Django 2.1.2 on 2018-11-11 18:25
+
+import datetime
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('notes', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='note',
+ name='date_created',
+ field=models.DateTimeField(blank=True, default=datetime.datetime(2018, 11, 11, 18, 25, 29, 645561), editable=False),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='note',
+ name='date_updated',
+ field=models.DateTimeField(blank=True, default=datetime.datetime(2018, 11, 11, 18, 25, 42, 867666), editable=False),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='note',
+ name='slug',
+ field=models.SlugField(blank=True, unique=True),
+ ),
+ ]
diff --git a/apps/notes/migrations/0003_note_folder.py b/apps/notes/migrations/0003_note_folder.py
new file mode 100644
index 0000000..d548429
--- /dev/null
+++ b/apps/notes/migrations/0003_note_folder.py
@@ -0,0 +1,19 @@
+# Generated by Django 2.1.2 on 2018-11-14 15:41
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('notes', '0002_auto_20181111_1825'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='note',
+ name='folder',
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='notes.Folder'),
+ ),
+ ]
diff --git a/apps/notes/migrations/__init__.py b/apps/notes/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/apps/notes/migrations/__init__.py
diff --git a/apps/notes/models.py b/apps/notes/models.py
new file mode 100644
index 0000000..aeb3bb3
--- /dev/null
+++ b/apps/notes/models.py
@@ -0,0 +1,38 @@
+from django.db import models
+from django.utils import timezone
+from django.template.defaultfilters import slugify
+
+from taggit.managers import TaggableManager
+
+from django.conf import settings
+
+
+class Folder(models.Model):
+ created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
+ name = models.CharField(max_length=250)
+
+ def __str__(self):
+ return self.name
+
+
+class Note(models.Model):
+ created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
+ date_created = models.DateTimeField(blank=True, editable=False)
+ date_updated = models.DateTimeField(blank=True, editable=False)
+ title = models.CharField(max_length=250)
+ body_markdown = models.TextField(null=True)
+ url = models.CharField(max_length=250)
+ slug = models.SlugField(unique=True, blank=True)
+ folder = models.ForeignKey(Folder, null=True, on_delete=models.SET_NULL)
+ tags = TaggableManager(blank=True, help_text='Tags')
+
+ def __str__(self):
+ return self.title
+
+ def save(self, **kwargs):
+ # On save, update timestamps (users updated through admin.py)
+ if not self.id:
+ self.date_created = timezone.now()
+ self.slug = slugify(self.title)[:50]
+ self.date_updated = timezone.now()
+ super(Note, self).save()
diff --git a/apps/notes/serializers.py b/apps/notes/serializers.py
new file mode 100644
index 0000000..d6c7392
--- /dev/null
+++ b/apps/notes/serializers.py
@@ -0,0 +1,18 @@
+from rest_framework import serializers
+from taggit_serializer.serializers import TagListSerializerField, TaggitSerializer
+
+from .models import Note, Folder
+
+
+class NoteSerializer(TaggitSerializer, serializers.HyperlinkedModelSerializer):
+ tags = TagListSerializerField()
+
+ class Meta:
+ model = Note
+ fields = ('title', 'body_markdown', 'url', 'folder', 'tags', 'date_created')
+
+
+class FolderSerializer(serializers.HyperlinkedModelSerializer):
+ class Meta:
+ model = Folder
+ fields = ('name')
diff --git a/apps/notes/tests/__init__.py b/apps/notes/tests/__init__.py
new file mode 100644
index 0000000..1d7ccb7
--- /dev/null
+++ b/apps/notes/tests/__init__.py
@@ -0,0 +1 @@
+from notes.tests import test_models, test_views
diff --git a/apps/notes/tests/test_models.py b/apps/notes/tests/test_models.py
new file mode 100644
index 0000000..e6cdb6a
--- /dev/null
+++ b/apps/notes/tests/test_models.py
@@ -0,0 +1,30 @@
+from django.test import TestCase
+from mixer.backend.django import mixer
+
+from notes.models import Note, Folder
+from accounts.models import User
+
+
+class FolderModelTest(TestCase):
+
+ def test_string_representation(self):
+ user = mixer.blend(User, username='tpynchon')
+ folder = Folder(created_by=user, name="My Folder")
+ self.assertEqual(str(folder), "My Folder")
+
+
+class NoteModelTest(TestCase):
+
+ def test_string_representation(self):
+ user = mixer.blend(User, username='test')
+ note = Note(
+ created_by=user,
+ title="test note",
+ body_markdown="the body of the note",
+ url="https://luxagraf.net/",
+ tags="mine,cool site"
+ )
+ self.assertEqual(str(note), "test note")
+ self.assertEqual(str(note.body_markdown), "the body of the note")
+ self.assertEqual(str(note.url), "https://luxagraf.net/")
+ self.assertEqual(str(note.tags), "mine,cool site")
diff --git a/apps/notes/tests/test_views.py b/apps/notes/tests/test_views.py
new file mode 100644
index 0000000..3f21b0b
--- /dev/null
+++ b/apps/notes/tests/test_views.py
@@ -0,0 +1,57 @@
+import json
+from django.test import Client
+from django.test import RequestFactory, TestCase
+
+from rest_framework.test import force_authenticate
+from rest_framework.test import APIRequestFactory
+from mixer.backend.django import mixer
+
+from accounts.models import User
+from notes.models import Note
+from notes.views import NoteListView, NoteViewSet
+
+
+class StoriesViewTest(TestCase):
+ def setUp(self):
+ # Every test needs access to the request factory.
+ self.factory = RequestFactory()
+ # test API with rest framework request factory.
+ self.apifactory = APIRequestFactory()
+ self.user = mixer.blend(User, username='tpynchon', password="gravity")
+ self.note = Note.objects.create(
+ created_by=self.user,
+ title="test note",
+ body_markdown="the body of the note",
+ url="https://luxagraf.net/",
+ )
+ self.note.tags.add("mine,cool site")
+ self.note.save()
+
+ def test_list_view(self):
+ request = self.factory.get('/%s/notes/' % (self.user.username))
+ request.user = self.user
+ response = NoteListView.as_view()(request)
+ self.assertEqual(response.status_code, 200)
+ response.render()
+
+ def test_api_list(self):
+ # Make an authenticated request to the view...
+ request = self.factory.get('/api/notes/')
+ force_authenticate(request, user=self.user)
+ response = NoteViewSet.as_view({'get': 'list'})(request)
+ self.assertEqual(response.status_code, 200)
+ response.render()
+ api_data = json.loads(response.content.decode('utf8'))[0]
+ self.assertEqual(api_data['title'], 'test note')
+ self.assertEqual(api_data['tags'], ['mine,cool site'])
+
+ def test_api_(self):
+ # Make an authenticated request to the view...
+ request = self.factory.get('/api/notes/')
+ force_authenticate(request, user=self.user)
+ response = NoteViewSet.as_view({'get': 'list'})(request)
+ self.assertEqual(response.status_code, 200)
+ response.render()
+ api_data = json.loads(response.content.decode('utf8'))[0]
+ self.assertEqual(api_data['title'], 'test note')
+ self.assertEqual(api_data['tags'], ['mine,cool site'])
diff --git a/apps/notes/urls.py b/apps/notes/urls.py
new file mode 100644
index 0000000..76bdeb1
--- /dev/null
+++ b/apps/notes/urls.py
@@ -0,0 +1,18 @@
+from django.urls import path
+
+from . import views
+
+app_name = "notes"
+
+urlpatterns = [
+ path(
+ r'create/',
+ views.NoteCreateView.as_view(),
+ name="note-create"
+ ),
+ path(
+ r'',
+ views.NoteListView.as_view(),
+ name="note"
+ ),
+]
diff --git a/apps/notes/views.py b/apps/notes/views.py
new file mode 100644
index 0000000..ddb72ed
--- /dev/null
+++ b/apps/notes/views.py
@@ -0,0 +1,41 @@
+from django.views.generic import CreateView, ListView, UpdateView, DeleteView
+from django.views.generic.detail import DetailView
+from django.utils.decorators import method_decorator
+from django.contrib.auth.decorators import login_required
+
+from rest_framework import viewsets
+from .serializers import NoteSerializer, FolderSerializer
+from .models import Note
+from .forms import NoteForm
+
+
+@method_decorator(login_required, name='dispatch')
+class LoggedInCreateViewWithUser(CreateView):
+
+ def get_form_kwargs(self, **kwargs):
+ kwargs = super().get_form_kwargs(**kwargs)
+ kwargs.update({'user': self.request.user})
+ return kwargs
+
+
+class NoteListView(ListView):
+ model = Note
+
+ def get_queryset(self):
+ return Note.objects.filter(created_by=self.request.user)
+
+
+class NoteCreateView(LoggedInCreateViewWithUser):
+ model = Note
+ form_class = NoteForm
+ template_name = "notes/create.html"
+
+
+class NoteViewSet(viewsets.ModelViewSet):
+ """
+ API endpoint that allows users to be viewed or edited.
+ """
+ serializer_class = NoteSerializer
+
+ def get_queryset(self):
+ return Note.objects.filter(created_by=self.request.user).order_by('-date_created')