Skip to content

Commit bd2832a

Browse files
committed
'add_api_v1'
1 parent fd41211 commit bd2832a

20 files changed

+219
-25
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ COPY . /code
99

1010
RUN pip install pipenv
1111

12-
RUN pipenv install --system --deploy
12+
RUN pipenv install --system --deploy --dev

Pipfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ djangorestframework = "*"
99
psycopg2-binary = "*"
1010

1111
[dev-packages]
12+
mypy = "*"
13+
django-stubs = "*"
1214

1315
[requires]
1416
python_version = "3.9"

Pipfile.lock

Lines changed: 120 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
182 Bytes
Binary file not shown.
99 Bytes
Binary file not shown.

blogapi/settings.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"""
1212
import os
1313
from pathlib import Path
14-
14+
from typing import List
1515
# Build paths inside the project like this: BASE_DIR / 'subdir'.
1616
BASE_DIR = Path(__file__).resolve().parent.parent
1717

@@ -25,7 +25,7 @@
2525
# SECURITY WARNING: don't run with debug turned on in production!
2626
DEBUG = os.environ.get('DEBUG')
2727

28-
ALLOWED_HOSTS = []
28+
ALLOWED_HOSTS:List[str] = []
2929

3030

3131
# Application definition
@@ -45,7 +45,12 @@
4545
'posts.apps.PostsConfig',
4646

4747
]
48-
48+
# Django rest framework settings
49+
REST_FRAMEWORK = {
50+
'DEFAULT_PERMISSION_CLASSES':[
51+
'rest_framework.permissions.IsAuthenticated',
52+
]
53+
}
4954
MIDDLEWARE = [
5055
'django.middleware.security.SecurityMiddleware',
5156
'django.contrib.sessions.middleware.SessionMiddleware',

blogapi/urls.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
1515
"""
1616
from django.contrib import admin
17-
from django.urls import path
17+
from django.urls import path, include
1818

1919
urlpatterns = [
2020
path('admin/', admin.site.urls),
21+
path('api/v1/', include('posts.urls')),
22+
path('api-auth/', include('rest_framework.urls')),
2123
]
433 Bytes
Binary file not shown.

modules/modeltestcase.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
11
import unittest
2-
class ModelTestCase:
3-
def create_model(self, modelClass, data:dict) -> None:
2+
from typing import Optional
3+
class ModelTestCase(unittest.TestCase):
4+
def create_model_and_save_data(self, modelClass, data:dict) -> None:
45
self.model = modelClass.objects.create(**data)
56
self.data = data
67

78
def check_content_of_model(self, msg:str = None) -> None:
89
for key in self.data:
910
self.assertEqual(
10-
getattr(self.model,key),
11-
self.data[key],
12-
msg = msg if msg != None else f'{key.capitalize()}: {getattr(self.model,key)} != {self.data[key]}'
11+
getattr(self.model,key).__str__(),
12+
self.data[key].__str__(),
13+
msg = msg if msg else f"{key.capitalize()}: {getattr(self.model, key)} != {self.data[key]}!"
1314
)
1415

16+
def check_str_method(self,str_field:str, msg:str = None) -> None:
17+
if not str_field: return None
18+
self.assertEqual(
19+
self.model.__str__(),
20+
getattr(self.model, str_field),
21+
msg = msg if msg else f'Model __str__ return {self.model.__str__()} expected {getattr(self.model, str_field)}!'
22+
)
23+
24+
1525

1626

1727

593 Bytes
Binary file not shown.
602 Bytes
Binary file not shown.
253 Bytes
Binary file not shown.

posts/__pycache__/urls.cpython-39.pyc

323 Bytes
Binary file not shown.
806 Bytes
Binary file not shown.

posts/permissions.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from rest_framework import permissions
2+
3+
class IsAuthorOrReadOnly(permissions.BasePermission):
4+
def has_object_permission(self, request, view, obj):
5+
if request.method in permissions.SAFE_METHODS:
6+
return True
7+
8+
return obj.author == request.user

posts/serializers.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from rest_framework import serializers
2+
3+
from .models import Post
4+
5+
class PostSerializer(serializers.ModelSerializer):
6+
class Meta:
7+
fields = (
8+
'id',
9+
'author',
10+
'title',
11+
'body',
12+
'created_at',
13+
)
14+
model = Post

posts/tests.py

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,29 @@
11
from django.test import TestCase
22
from django.contrib.auth import get_user_model
33
from .models import Post
4-
from modules import ModelTestCase
4+
# from modules import ModelTestCase
55
# Create your tests here.
6-
data = {
7-
'title':'title',
8-
'body':'body',
9-
'author':get_user_model().objects.get(id = 1)
10-
}
11-
class PostTestCase(ModelTestCase, TestCase):
12-
def setUp(self):
13-
self.create_model(Post, data)
146

15-
def test_content(self):
16-
self.check_content_of_model()
7+
class PostTestCase(TestCase):
8+
@classmethod
9+
def setUpTestData(cls):
10+
testuser1 = get_user_model().objects.create_user(
11+
username = 'testuser1',
12+
password = 'abc123'
13+
)
14+
testuser1.save()
15+
test_post = Post.objects.create(
16+
author = testuser1,
17+
title = 'Blog title',
18+
body = 'Body content...'
19+
)
20+
test_post.save()
21+
22+
def test_blog_content(self):
23+
post = Post.objects.get(id = 1)
24+
author = str(post.author)
25+
title = str(post.title)
26+
body = str(post.body)
27+
self.assertEqual(author, 'testuser1')
28+
self.assertEqual(title, 'Blog title')
29+
self.assertEqual(body, 'Body content...')

posts/urls.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from django.urls import path
22

3+
from .views import PostList, PostDetail
34
urlpatterns = [
4-
# path('')
5+
path('<int:pk>/', PostDetail.as_view(), name = 'post_detail'),
6+
path('', PostList.as_view(), name = 'post_list'),
57
]

posts/views.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1-
from django.shortcuts import render
1+
from rest_framework import generics, permissions
22

33
# Create your views here.
4+
5+
from .models import Post
6+
7+
from .serializers import PostSerializer
8+
9+
from .permissions import IsAuthorOrReadOnly
10+
class PostList(generics.ListCreateAPIView):
11+
queryset = Post.objects.all()
12+
serializer_class = PostSerializer
13+
14+
class PostDetail(generics.RetrieveUpdateDestroyAPIView):
15+
permission_classes = (IsAuthorOrReadOnly,)
16+
queryset = Post.objects.all()
17+
serializer_class = PostSerializer

setup.cfg

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[mypy]
2+
plugins =
3+
mypy_django_plugin.main
4+
5+
[mypy.plugins.django-stubs]
6+
django_settings_module = "blogapi.settings"

0 commit comments

Comments
 (0)