Skip to content

Commit

Permalink
Add backend basic functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
mrEvgenX committed May 27, 2020
1 parent 9810822 commit 25aeea2
Show file tree
Hide file tree
Showing 14 changed files with 227 additions and 3 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Expand Up @@ -23,4 +23,5 @@ yarn-debug.log*
yarn-error.log*

**/venv
**/__pycache__
**/__pycache__
**/*.sqlite3
12 changes: 12 additions & 0 deletions django/config/settings.py
Expand Up @@ -31,6 +31,9 @@
# Application definition

INSTALLED_APPS = [
'core',
'rest_framework',
'corsheaders',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
Expand All @@ -43,6 +46,7 @@
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
Expand All @@ -69,6 +73,12 @@

WSGI_APPLICATION = 'config.wsgi.application'

REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
]
}

# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
Expand Down Expand Up @@ -118,3 +128,5 @@
# https://docs.djangoproject.com/en/3.0/howto/static-files/

STATIC_URL = '/static/'

CORS_ORIGIN_ALLOW_ALL = True
5 changes: 4 additions & 1 deletion django/config/urls.py
Expand Up @@ -14,8 +14,11 @@
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.urls import path, include
import core.urls


urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include(core.urls, namespace='api')),
]
Empty file added django/core/__init__.py
Empty file.
6 changes: 6 additions & 0 deletions django/core/admin.py
@@ -0,0 +1,6 @@
from django.contrib import admin
from .models import Folder, Item


admin.site.register(Folder)
admin.site.register(Item)
5 changes: 5 additions & 0 deletions django/core/apps.py
@@ -0,0 +1,5 @@
from django.apps import AppConfig


class CoreConfig(AppConfig):
name = 'core'
48 changes: 48 additions & 0 deletions django/core/migrations/0001_initial.py
@@ -0,0 +1,48 @@
# Generated by Django 3.0.6 on 2020-05-27 07:58

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='Folder',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('slug', models.CharField(max_length=140, unique=True)),
('name', models.CharField(max_length=140)),
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Item',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=140)),
('folder', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Folder')),
],
options={
'unique_together': {('folder', 'name')},
},
),
migrations.CreateModel(
name='Entry',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('timeBucket', models.DateField()),
('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Item')),
],
options={
'unique_together': {('timeBucket', 'item')},
},
),
]
Empty file.
34 changes: 34 additions & 0 deletions django/core/models.py
@@ -0,0 +1,34 @@
from django.db import models
from django.conf import settings


class Folder(models.Model):
owner = models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
slug = models.CharField(max_length=140, unique=True)
name = models.CharField(max_length=140)

def __str__(self):
return '{} ({})'.format(self.name, self.owner.username)

# TODO Включить потом, когда научимся десериализировать
# class Meta:
# unique_together = (('owner', 'slug'),)


class Item(models.Model):
folder = models.ForeignKey(to=Folder, on_delete=models.CASCADE)
name = models.CharField(max_length=140)

def __str__(self):
return '{} ({}) / {}'.format(self.folder.name, self.folder.owner.username, self.name)

class Meta:
unique_together = (('folder', 'name'),)


class Entry(models.Model):
timeBucket = models.DateField()
item = models.ForeignKey(to=Item, on_delete=models.CASCADE)

class Meta:
unique_together = (('timeBucket', 'item'),)
29 changes: 29 additions & 0 deletions django/core/serializers.py
@@ -0,0 +1,29 @@
from rest_framework import serializers
from .models import Folder, Item, Entry


class FolderSerializer(serializers.ModelSerializer):

class Meta:
model = Folder
fields = ['owner', 'slug', 'name']
extra_kwargs = {
'owner': {'write_only': True},
}


class ItemSerializer(serializers.ModelSerializer):
folder = serializers.SlugRelatedField(slug_field='slug', queryset=Folder.objects.all())

class Meta:
model = Item
fields = ['id', 'folder', 'name']
read_only_fields = ['id']


class EntrySerializer(serializers.ModelSerializer):
item = serializers.PrimaryKeyRelatedField(queryset=Item.objects.all())

class Meta:
model = Entry
fields = ['timeBucket', 'item']
41 changes: 41 additions & 0 deletions django/core/tests.py
@@ -0,0 +1,41 @@
from datetime import date
from django.test import TestCase
from django.contrib.auth.models import User
from .models import Folder, Item, Entry
from .serializers import FolderSerializer, ItemSerializer, EntrySerializer


class SerializerTests(TestCase):

def test_serializer_folder(self):
user = User.objects.create(username='user')
folder = Folder.objects.create(owner=user, slug='papka', name='Папка')
serializer = FolderSerializer(folder)
self.assertEqual(serializer.data, {'slug': 'papka', 'name': 'Папка'})

data = {'owner': user.pk, 'slug': 'gruppa', 'name': 'Группа'}
serializer = FolderSerializer(data=data)
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.validated_data, {'owner': user, 'slug': 'gruppa', 'name': 'Группа'})
folder = serializer.save()
print('!!!!!!', folder)

def test_serializer_item(self):
user = User.objects.create(username='user')
folder = Folder.objects.create(owner=user, slug='papka', name='Папка')
item = Item.objects.create(folder=folder, name='Элемент1')
serializer = ItemSerializer(item)
self.assertEqual(serializer.data, {'id': item.id, 'folder': 'papka', 'name': 'Элемент1'})

data = {'folder': 'papka', 'name': 'Элемент2'}
serializer = ItemSerializer(data=data)
self.assertTrue(serializer.is_valid(), serializer.errors)
self.assertEqual(serializer.validated_data, {'folder': folder, 'name': 'Элемент2'})

def test_serializer_entry(self):
user = User.objects.create(username='user')
folder = Folder.objects.create(owner=user, slug='papka', name='Папка')
item = Item.objects.create(folder=folder, name='Элемент')
entry = Entry.objects.create(timeBucket=date(2020, 1, 1), item=item)
serializer = EntrySerializer(entry)
self.assertEqual(serializer.data, {'timeBucket': '2020-01-01', 'item': item.id})
10 changes: 10 additions & 0 deletions django/core/urls.py
@@ -0,0 +1,10 @@
from django.urls import path
from .views import ListCreateFolders, ListCreateItems, ListCreateEntries
from rest_framework.urlpatterns import format_suffix_patterns

app_name = 'core'
urlpatterns = format_suffix_patterns([
path('folders', ListCreateFolders.as_view()),
path('items', ListCreateItems.as_view()),
path('entries', ListCreateEntries.as_view()),
])
33 changes: 33 additions & 0 deletions django/core/views.py
@@ -0,0 +1,33 @@
from rest_framework.response import Response
from rest_framework import generics
from rest_framework import status
from .models import Folder, Item, Entry
from .serializers import FolderSerializer, ItemSerializer, EntrySerializer

from unidecode import unidecode
from django.utils.text import slugify


class ListCreateFolders(generics.ListCreateAPIView):
queryset = Folder.objects.all()
serializer_class = FolderSerializer

def get_serializer(self, *args, **kwargs):
data = kwargs.get('data')
if data:
data.update({
'slug': slugify(unidecode(data['name'])),
'owner': self.request.user.pk
})
kwargs['data'] = data
return super().get_serializer(*args, **kwargs)


class ListCreateItems(generics.ListCreateAPIView):
queryset = Item.objects.all()
serializer_class = ItemSerializer


class ListCreateEntries(generics.ListCreateAPIView):
queryset = Entry.objects.all()
serializer_class = EntrySerializer
4 changes: 3 additions & 1 deletion requirements.txt
@@ -1,2 +1,4 @@
django==3.0.6
django-rest-framework==0.1.0
django-cors-headers==3.3.0
djangorestframework==3.11.0
unidecode==1.1.1

0 comments on commit 25aeea2

Please sign in to comment.