15 Commits

Author SHA1 Message Date
moscap
6869c3e6ba AUTH form were added to gui 2021-04-22 10:18:17 +03:00
moscap
d46867a03e 'nts' 2021-04-22 08:10:36 +03:00
moscap
9fd811363a Initial commit by moscap 2021-04-19 12:57:31 +03:00
f43c652671 hotfix: Исправлено добавление списков и их элементов из API 2021-04-18 12:24:12 +03:00
Aleksey Lobanov
4886e2e9be Merge pull request #20 from AlekseyLobanov/feat_4.base_api
Добавлено базовое API + finished #4 #17
2021-04-17 15:01:03 +03:00
3f5083f8e4 feat: Реализовано базовое простое API
Минимальное, но самодостаточное
2021-04-17 15:00:04 +03:00
0f2f291c18 feat: Добавлена пагинация для API 2021-04-17 14:59:26 +03:00
8a26910651 db: Больше индексов для важных полей 2021-04-17 14:59:08 +03:00
64607efaf3 feat: Новая модель в админке и добавления поля finished 2021-04-17 14:58:49 +03:00
6352deda3c feat: Поддержка фильтрации на стороне Django 2021-04-17 14:57:38 +03:00
Aleksey Lobanov
920c7f52bd Merge pull request #18 from AlekseyLobanov/feat_6
Feat 6
2021-04-14 13:37:40 +03:00
Derinhelm
88e19efc0b feat: Зафиксирована версия drf-yasg 2021-04-14 13:27:05 +03:00
Derinhelm
df54d92ecc feat: В Swagger UI добавлена JWT-авторизация 2021-04-14 13:13:06 +03:00
Derinhelm
8bf990b5f6 feat: Добавлен Swagger UI
http://0.0.0.0:8000/swagger/
2021-04-14 00:13:00 +03:00
4e61029ce6 Merge pull request #12 from AlekseyLobanov/feat_base_empty_version
Первый PR, решает #2 #3 #5 #7 #8
2021-04-09 22:54:22 +03:00
9 changed files with 234 additions and 12 deletions

View File

@@ -1,6 +1,6 @@
from django.contrib import admin
from .models import ToDoList
from .models import ToDoList, ToDoItem
class ToDoListAdmin(admin.ModelAdmin):
@@ -9,4 +9,11 @@ class ToDoListAdmin(admin.ModelAdmin):
list_editable = ["title"]
class ToDoItemAdmin(admin.ModelAdmin):
model = ToDoItem
list_display = ["parent", "finished", "text", "created_at"]
list_editable = ["finished", "text"]
admin.site.register(ToDoList, ToDoListAdmin)
admin.site.register(ToDoItem, ToDoItemAdmin)

View File

@@ -1,20 +1,62 @@
from rest_framework import viewsets, serializers, permissions
from rest_framework import routers
from django_filters.rest_framework import DjangoFilterBackend
from .models import ToDoList
from .models import ToDoList, ToDoItem
class ToDoListField(serializers.PrimaryKeyRelatedField):
def get_queryset(self):
user = self.context["request"].user
return ToDoList.objects.filter(user=user)
class ToDoItemSerializer(serializers.HyperlinkedModelSerializer):
parent = ToDoListField(many=False, read_only=False, help_text="ID родительского списка")
class Meta:
model = ToDoItem
fields = ["id", "text", "finished", "created_at", "parent"]
class ToDoItemViewSet(viewsets.ModelViewSet):
serializer_class = ToDoItemSerializer
permission_classes = [permissions.IsAuthenticated]
filter_backends = [DjangoFilterBackend]
filterset_fields = ["parent", "finished"]
def get_queryset(self):
user = self.request.user
if not user.is_authenticated:
# ветка только для генерации схемы
return ToDoItem.objects.all()
return ToDoItem.objects.filter(parent__user=user)
class ToDoListSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ToDoList
fields = ["title", "created_at"]
fields = ["id", "title", "created_at"]
def create(self, validated_data):
todo_list = ToDoList.objects.create(
user=self.context["request"].user, title=validated_data["title"]
)
return todo_list
class ToDoListViewSet(viewsets.ModelViewSet):
queryset = ToDoList.objects.all()
serializer_class = ToDoListSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
user = self.request.user
if not user.is_authenticated:
# ветка только для генерации схемы
return ToDoList.objects.all()
return ToDoList.objects.filter(user=user)
router = routers.DefaultRouter()
router.register(r"lists", ToDoListViewSet)
router.register(r"lists", ToDoListViewSet, basename="ToDoLists")
router.register(r"todo_items", ToDoItemViewSet, basename="ToDoItems")

View File

@@ -0,0 +1,18 @@
# Generated by Django 3.2 on 2021-04-17 11:15
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("backend", "0001_initial"),
]
operations = [
migrations.AddField(
model_name="todoitem",
name="finished",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,28 @@
# Generated by Django 3.2 on 2021-04-17 11:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("backend", "0002_todoitem_finished"),
]
operations = [
migrations.AlterField(
model_name="todoitem",
name="created_at",
field=models.DateTimeField(auto_now_add=True, db_index=True),
),
migrations.AlterField(
model_name="todoitem",
name="finished",
field=models.BooleanField(db_index=True, default=False),
),
migrations.AlterField(
model_name="todolist",
name="created_at",
field=models.DateTimeField(auto_now_add=True, db_index=True),
),
]

View File

@@ -5,10 +5,11 @@ from django.contrib.auth.models import User
class ToDoList(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=False, default=None)
title = models.CharField(max_length=250)
created_at = models.DateTimeField(auto_now_add=True)
created_at = models.DateTimeField(auto_now_add=True, db_index=True)
class ToDoItem(models.Model):
parent = models.ForeignKey(ToDoList, on_delete=models.CASCADE, null=False, default=None)
text = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
finished = models.BooleanField(default=False, null=False, db_index=True)
created_at = models.DateTimeField(auto_now_add=True, db_index=True)

View File

@@ -27,7 +27,8 @@ SECRET_KEY = "django-insecure-toz+*lt(ejm!l*)92w2ciqoh^1kz#a(abbpcn54-dbw(nxoy&7
DEBUG = True
ALLOWED_HOSTS = []
if DEBUG:
ALLOWED_HOSTS = ["0.0.0.0", "localhost", "127.0.0.1"]
# Application definition
@@ -40,8 +41,13 @@ INSTALLED_APPS = [
"django.contrib.messages",
"django.contrib.staticfiles",
"rest_framework",
"drf_yasg",
]
SWAGGER_SETTINGS = {
"SECURITY_DEFINITIONS": {"Bearer": {"type": "apiKey", "name": "Authorization", "in": "header"}}
}
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
@@ -118,7 +124,12 @@ SIMPLE_JWT = {
}
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ("rest_framework_simplejwt.authentication.JWTAuthentication",)
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
),
"DEFAULT_FILTER_BACKENDS": ["django_filters.rest_framework.DjangoFilterBackend"],
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination",
"PAGE_SIZE": 100,
}

View File

@@ -6,8 +6,21 @@ from rest_framework_simplejwt.views import (
TokenRefreshView,
)
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
from .api import router
schema_view = get_schema_view(
openapi.Info(
title="ToDo List",
default_version='v1',
description="Swagger Interface for ToDo List",
),
public=True,
permission_classes=(permissions.AllowAny,),
)
urlpatterns = [
path("admin/", admin.site.urls),
@@ -15,4 +28,5 @@ urlpatterns = [
path("api/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
path("api/", include(router.urls)),
path("api-auth/", include("rest_framework.urls", namespace="rest_framework")),
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
]

View File

@@ -1,4 +1,5 @@
djangorestframework==3.12.4
django-filter==2.4.0
markdown==3.3.4
appdirs==1.4.4
asgiref==3.3.4
@@ -21,3 +22,4 @@ toml==0.10.2
urllib3==1.26.4
djangorestframework-simplejwt==4.6.0
psycopg2-binary>=2.8
drf-yasg==1.20.0

View File

@@ -1,14 +1,113 @@
#!/usr/bin/env python3
import sys
import tkinter as tk
from tkinter import messagebox as mb
from user import User
if 'win' in sys.platform.lower():
DEFAULT_URL = "http://localhost:8000"
else:
DEFAULT_URL = "http://0.0.0.0:8000"
BASE_W = 580
BASE_H = 400
class Application(tk.Frame):
def __init__(self, master=None):
def __init__(self,
master=None
) -> None:
"""
Функция инициаизации класса
"""
super().__init__(master)
#Иницализируем параметры окна
self.master = master
self.pack(fill=tk.BOTH, expand=1)
self.grid(row=0, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
tk.Grid.rowconfigure(master, 0, weight=1)
tk.Grid.columnconfigure(master, 0, weight=1)
# Иницализируем параметры пользователя
self.user = User(url=DEFAULT_URL)
# Настраиваем размеры и включаем иницализацию
self.centerWindow()
self.initAUTH()
def centerWindow(self,
width: str = BASE_W,
heigh: str = BASE_H
) -> None:
"""
Центрирует приложение по центру экрана
:param width: ширина окна
:param heigh: высота окна
"""
sw = self.master.winfo_screenwidth()
sh = self.master.winfo_screenheight()
x = (sw - width) / 2
y = (sh - heigh) / 2
self.master.geometry('%dx%d+%d+%d' % (width, heigh, x, y))
def login_clicked(self) -> None:
"""
Функция авторизации
"""
try:
self.user.auth(self.login.get(), self.password.get())
except Exception as ex:
print(ex)
self.show_info()
def show_info(selfб,
msg: str = None
) -> None:
"""
Показывает передаваемое сообщение в messagebox
:param msg: передаваемое сообщение
"""
if msg is None:
msg = "Неправильный логин или пароль"
mb.showinfo("Информация", msg)
def initAUTH(self) -> None:
"""
Создает окно авторизации программы
"""
#Конфигурируем сетку
for rows in range(25):
tk.Grid.rowconfigure(self, rows, weight=1)
for columns in range(25):
tk.Grid.columnconfigure(self, columns, weight=1)
# Подпись и поле ввода для логина
login_label = tk.Label(self, text="Введите логин")
login_label.grid(row=9, column=12, columnspan=3, rowspan=1, sticky="nsew")
self.login = tk.Entry(self)
self.login.grid(row=10, column=12, columnspan=3, rowspan=1, sticky="nsew")
# Подпись и поле ввода для пароля
password_label = tk.Label(self, text="Введите пароль")
password_label.grid(row=11, column=12, columnspan=3, rowspan=1, sticky="nsew")
self.password = tk.Entry(self, show="*")
self.password.grid(row=12, column=12, columnspan=3, rowspan=1, sticky="nsew")
# Кнопка авториазции
btn = tk.Button(self, text="Войти", command=self.login_clicked)
btn.grid(row=14, column=12, columnspan=3, rowspan=1, sticky="nsew")
if __name__ == "__main__":
app = Application()
master = tk.Tk()
app = Application(master)
app.master.title("ToDo")
app.mainloop()