├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── TODO.md └── todo ├── account ├── __init__.py ├── admin.py ├── api │ ├── __init__.py │ ├── serializers.py │ ├── urls.py │ └── views.py ├── apps.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── templates │ ├── base.html │ ├── registration │ │ ├── login.html │ │ └── success.html │ └── signup.html ├── tests.py ├── urls.py └── views.py ├── db.sqlite3 ├── manage.py ├── todo ├── __init__.py ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py └── todo_app ├── __init__.py ├── admin.py ├── api ├── __init__.py ├── serializers.py ├── urls.py └── views.py ├── apps.py ├── forms.py ├── migrations ├── 0001_initial.py ├── 0002_auto_20210903_1032.py └── __init__.py ├── models.py ├── templates ├── add_task.html └── base.html ├── tests.py ├── urls.py └── views.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | 62 | # Flask stuff: 63 | instance/ 64 | .webassets-cache 65 | 66 | # Scrapy stuff: 67 | .scrapy 68 | 69 | # Sphinx documentation 70 | docs/_build/ 71 | 72 | # PyBuilder 73 | target/ 74 | 75 | # Jupyter Notebook 76 | .ipynb_checkpoints 77 | 78 | # IPython 79 | profile_default/ 80 | ipython_config.py 81 | 82 | # pyenv 83 | .python-version 84 | 85 | # pipenv 86 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 87 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 88 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 89 | # install all needed dependencies. 90 | #Pipfile.lock 91 | 92 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 93 | __pypackages__/ 94 | 95 | # Celery stuff 96 | celerybeat-schedule 97 | celerybeat.pid 98 | 99 | # SageMath parsed files 100 | *.sage.py 101 | 102 | # Environments 103 | .env 104 | .venv 105 | env/ 106 | venv/ 107 | ENV/ 108 | env.bak/ 109 | venv.bak/ 110 | 111 | # Spyder project settings 112 | .spyderproject 113 | .spyproject 114 | 115 | # Rope project settings 116 | .ropeproject 117 | 118 | # mkdocs documentation 119 | /site 120 | 121 | # mypy 122 | .mypy_cache/ 123 | .dmypy.json 124 | dmypy.json 125 | 126 | # Pyre type checker 127 | .pyre/ 128 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to TODO project 2 | 3 | If you want to contribute to this project: 4 | 5 | - Fork this repo in github 6 | - Clone your fork 7 | - Create a branch 8 | - Make your changes and commit 9 | - Push your branch to your fork 10 | - Send a pull request from your branch to this project 11 | 12 | Some notes: 13 | 14 | - If you are adding new feature, surely test that code before commiting 15 | - Do not change `README.md` directly, new fature will be added to the list after testing. 16 | 17 | ### Contribution ways 18 | 19 | - Adding new feature 20 | - Working on Front-End 21 | 22 | Tnx a lot. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 shahriaarrr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TODO app using Django freamwork 2 | 3 | TODO web application with Django freamwork. 4 | 5 | ### How to get and run 6 | 7 | **First clone the repo** 8 | 9 | ``` 10 | $ git clone https://github.com/shahriaarrr/todo-with-django 11 | $ cd todo-with-django 12 | ``` 13 | 14 | **Second run the project** 15 | 16 | ``` 17 | $ cd todo 18 | $ python3 manage.py runserver 19 | ``` 20 | 21 | **Now open browser and enter link below** 22 | 23 | ``` 24 | 127.0.0.1:8000 25 | ``` 26 | 27 | ### How to contribute? 28 | 29 | If you want to contribute in this project, read [CONTRIBUTING.md](https://github.com/shahriaarrr/todo-with-django/blob/master/CONTRIBUTING.md) for more information. 30 | 31 | 32 | Developing with ♥ by Shahriar Ghasempour. 2021 © 33 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # TODO app TODO list :) 2 | 3 | Here are list of tasks need to fix or start or create. 4 | 5 | - [ ] Front-End 6 | - [x] Make a nice README -------------------------------------------------------------------------------- /todo/account/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shahriaarrr/todo-with-django/83a02d4fa43f70260c16fb3b7ba831958b436942/todo/account/__init__.py -------------------------------------------------------------------------------- /todo/account/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.contrib.auth.admin import UserAdmin as DefaultUserAdmin 3 | 4 | from .models import User 5 | # Register your models here. 6 | @admin.register(User) 7 | class UserAdmin(DefaultUserAdmin): 8 | list_display = ( 9 | 'username', 10 | 'date_joined', 11 | 'email', 12 | 'is_staff', 13 | 'is_active', 14 | ) 15 | sortable_by = ['username', 'date_joined'] 16 | list_editable = ['is_staff', 'is_active'] 17 | search_fields = ['first_name', 'last_name', 'username', 'email'] 18 | readonly_fields = ['date_joined', 'last_login'] -------------------------------------------------------------------------------- /todo/account/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shahriaarrr/todo-with-django/83a02d4fa43f70260c16fb3b7ba831958b436942/todo/account/api/__init__.py -------------------------------------------------------------------------------- /todo/account/api/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from account.models import User 4 | 5 | class SignupSerializer(serializers.ModelSerializer): 6 | class Meta: 7 | model = User 8 | fields = ('username', 'password', 'first name', 'last name', 'email', 'age', 'gender') 9 | 10 | def validate(self, data): 11 | if data.get('first name') == data.get('last name'): 12 | raise serializers.ValidationError('Your first and last name should not be the same') 13 | 14 | return data 15 | 16 | def validate_password(self, value): 17 | if len(value) < 5: 18 | raise serializers.ValidationError('Your password should not be less than 5 characters') 19 | 20 | return value 21 | 22 | def validate_age(self, value): 23 | if value <= 0: 24 | error = 'Your age must be a positive number and greater than zero' 25 | raise serializers.ValidationError(error) 26 | 27 | return value 28 | -------------------------------------------------------------------------------- /todo/account/api/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from rest_framework.authtoken.views import obtain_auth_token 3 | 4 | from .views import * 5 | 6 | urlpatterns = [ 7 | path('signup/', SignupAPIView.as_view(), name='signupAPI'), 8 | path('login/', view=obtain_auth_token, name='LoginAPIview'), 9 | path('logout/', LogoutAPIView.as_view(), name='LogoutAPIview'), 10 | ] -------------------------------------------------------------------------------- /todo/account/api/views.py: -------------------------------------------------------------------------------- 1 | from account.models import User 2 | from rest_framework.response import Response 3 | from rest_framework.views import APIView 4 | from rest_framework.permissions import IsAuthenticated 5 | 6 | from .serializers import SignupSerializer 7 | 8 | class SignupAPIView(APIView): 9 | def post(self, request): 10 | signup_serializer = SignupSerializer(data=request.data) 11 | if signup_serializer.is_valid(): 12 | data = signup_serializer.validated_data 13 | User.objects.create_user(**data) 14 | return Response({'message' : 'User successfully signed up'}) 15 | 16 | return Response({'message' : signup_serializer.errors}) 17 | 18 | class LogoutAPIView(APIView): 19 | permission_classes = (IsAuthenticated, ) 20 | 21 | def post(self, request): 22 | request.user.auth_token.delete() 23 | return Response(data={'message': f"Bye {request.user.username}!"}) -------------------------------------------------------------------------------- /todo/account/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AccountConfig(AppConfig): 5 | name = 'account' 6 | -------------------------------------------------------------------------------- /todo/account/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django import forms 3 | from django.contrib.auth.forms import UserCreationForm 4 | from .models import * 5 | 6 | class Signup(UserCreationForm): 7 | pass 8 | 9 | 10 | class Login(forms.ModelForm): 11 | class Meta: 12 | model = User 13 | fields = ('username', 'password') -------------------------------------------------------------------------------- /todo/account/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.4 on 2021-08-21 06:46 2 | 3 | import django.contrib.auth.models 4 | import django.contrib.auth.validators 5 | from django.db import migrations, models 6 | import django.utils.timezone 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | initial = True 12 | 13 | dependencies = [ 14 | ('auth', '0012_alter_user_first_name_max_length'), 15 | ] 16 | 17 | operations = [ 18 | migrations.CreateModel( 19 | name='User', 20 | fields=[ 21 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 22 | ('password', models.CharField(max_length=128, verbose_name='password')), 23 | ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), 24 | ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), 25 | ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), 26 | ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), 27 | ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), 28 | ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), 29 | ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), 30 | ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), 31 | ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), 32 | ('gender', models.CharField(choices=[('w', 'woman'), ('M', 'Man'), ('u', 'unkhow')], default='unkhow', max_length=1)), 33 | ('age', models.PositiveIntegerField(null=True)), 34 | ('description', models.TextField(max_length=1000)), 35 | ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), 36 | ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), 37 | ], 38 | options={ 39 | 'verbose_name': 'user', 40 | 'verbose_name_plural': 'users', 41 | 'abstract': False, 42 | }, 43 | managers=[ 44 | ('objects', django.contrib.auth.models.UserManager()), 45 | ], 46 | ), 47 | ] 48 | -------------------------------------------------------------------------------- /todo/account/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shahriaarrr/todo-with-django/83a02d4fa43f70260c16fb3b7ba831958b436942/todo/account/migrations/__init__.py -------------------------------------------------------------------------------- /todo/account/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import AbstractUser 3 | # Create your models here. 4 | class User(AbstractUser): 5 | GENDER_CHOICE = ( 6 | ("w", "woman"), 7 | ("M", "Man"), 8 | ("u", "unkhow") 9 | ) 10 | gender = models.CharField(choices=GENDER_CHOICE, max_length=1, default="unkhow") 11 | age = models.PositiveIntegerField(null=True) 12 | description = models.TextField(max_length=1000, blank=False) 13 | 14 | def __str__(self): 15 | return self.username -------------------------------------------------------------------------------- /todo/account/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% block title %}{% endblock %} 8 | 9 | 10 | {% block content %}{% endblock %} 11 | 12 | -------------------------------------------------------------------------------- /todo/account/templates/registration/login.html: -------------------------------------------------------------------------------- 1 |

login form

2 |
{% csrf_token %} 3 | {{ form.as_p }} 4 | 5 |
6 | 7 | -------------------------------------------------------------------------------- /todo/account/templates/registration/success.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block title %}success{% endblock %} 4 | 5 | {% block content %} 6 |

Hello {{ username }}.

7 | {% endblock %} -------------------------------------------------------------------------------- /todo/account/templates/signup.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block title %}Signup{% endblock %} 4 | 5 | {% block content %} 6 |

Signup form

7 |
{% csrf_token %} 8 | {{ form.as_p }} 9 | 10 |
11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /todo/account/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /todo/account/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path, include 2 | 3 | from .views import * 4 | 5 | urlpatterns = [ 6 | path('', signup, name='signup'), 7 | ] -------------------------------------------------------------------------------- /todo/account/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.views.decorators.csrf import csrf_exempt 3 | 4 | from .forms import * 5 | # Create your views here. 6 | @csrf_exempt 7 | def signup(request): 8 | if request.method == "GET": 9 | form = Signup() 10 | return render(request, 'signup.html', {'form' : form}) 11 | if request.method == "POST": 12 | form = Signup(request.POST) 13 | if form.is_valid(): 14 | user = form.save() 15 | return render(request, 'seccess.html', {'username' : user.username}) -------------------------------------------------------------------------------- /todo/db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shahriaarrr/todo-with-django/83a02d4fa43f70260c16fb3b7ba831958b436942/todo/db.sqlite3 -------------------------------------------------------------------------------- /todo/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'todo.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /todo/todo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shahriaarrr/todo-with-django/83a02d4fa43f70260c16fb3b7ba831958b436942/todo/todo/__init__.py -------------------------------------------------------------------------------- /todo/todo/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for todo project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'todo.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /todo/todo/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for todo project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.1.4. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.1/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | 15 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 16 | BASE_DIR = Path(__file__).resolve().parent.parent 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'je*5foay=(_zg-dzan-a874ua01*+8zh%r$=xipp_j6*iz+=st' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | APPEND_SLASH = True 28 | 29 | ALLOWED_HOSTS = [] 30 | 31 | 32 | # Application definition 33 | 34 | INSTALLED_APPS = [ 35 | 'django.contrib.admin', 36 | 'django.contrib.auth', 37 | 'django.contrib.contenttypes', 38 | 'django.contrib.sessions', 39 | 'django.contrib.messages', 40 | 'django.contrib.staticfiles', 41 | 'todo_app.apps.TodoAppConfig', 42 | 'account.apps.AccountConfig', 43 | 'rest_framework', 44 | 'rest_framework.authtoken', 45 | ] 46 | 47 | MIDDLEWARE = [ 48 | 'django.middleware.security.SecurityMiddleware', 49 | 'django.contrib.sessions.middleware.SessionMiddleware', 50 | 'django.middleware.common.CommonMiddleware', 51 | 'django.middleware.csrf.CsrfViewMiddleware', 52 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 53 | 'django.contrib.messages.middleware.MessageMiddleware', 54 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 55 | ] 56 | 57 | ROOT_URLCONF = 'todo.urls' 58 | 59 | AUTH_USER_MODEL = 'account.User' 60 | 61 | REST_FRAMEWORK = { 62 | 'DEFAULT_AUTHENTICATION_CLASSES': [ 63 | 'rest_framework.authentication.TokenAuthentication', 64 | ], 65 | } 66 | 67 | TEMPLATES = [ 68 | { 69 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 70 | 'DIRS': [], 71 | 'APP_DIRS': True, 72 | 'OPTIONS': { 73 | 'context_processors': [ 74 | 'django.template.context_processors.debug', 75 | 'django.template.context_processors.request', 76 | 'django.contrib.auth.context_processors.auth', 77 | 'django.contrib.messages.context_processors.messages', 78 | ], 79 | }, 80 | }, 81 | ] 82 | 83 | WSGI_APPLICATION = 'todo.wsgi.application' 84 | 85 | 86 | # Database 87 | # https://docs.djangoproject.com/en/3.1/ref/settings/#databases 88 | 89 | DATABASES = { 90 | 'default': { 91 | 'ENGINE': 'django.db.backends.sqlite3', 92 | 'NAME': BASE_DIR / 'db.sqlite3', 93 | } 94 | } 95 | 96 | 97 | # Password validation 98 | # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators 99 | 100 | AUTH_PASSWORD_VALIDATORS = [ 101 | { 102 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 103 | }, 104 | { 105 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 106 | }, 107 | { 108 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 109 | }, 110 | { 111 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 112 | }, 113 | ] 114 | 115 | 116 | # Internationalization 117 | # https://docs.djangoproject.com/en/3.1/topics/i18n/ 118 | 119 | LANGUAGE_CODE = 'en-us' 120 | 121 | TIME_ZONE = 'UTC' 122 | 123 | USE_I18N = True 124 | 125 | USE_L10N = True 126 | 127 | USE_TZ = True 128 | 129 | 130 | # Static files (CSS, JavaScript, Images) 131 | # https://docs.djangoproject.com/en/3.1/howto/static-files/ 132 | 133 | STATIC_URL = '/static/' 134 | -------------------------------------------------------------------------------- /todo/todo/urls.py: -------------------------------------------------------------------------------- 1 | """todo URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.1/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path, include 18 | 19 | urlpatterns = [ 20 | path('admin/', admin.site.urls), 21 | path('', include('todo_app.urls')), 22 | path('accounts/', include('django.contrib.auth.urls')), 23 | path('signup/', include('account.urls')), 24 | path('api/account/', include('account.api.urls')), 25 | path('api/task/', include('todo_app.api.urls')), 26 | ] 27 | -------------------------------------------------------------------------------- /todo/todo/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for todo project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'todo.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /todo/todo_app/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shahriaarrr/todo-with-django/83a02d4fa43f70260c16fb3b7ba831958b436942/todo/todo_app/__init__.py -------------------------------------------------------------------------------- /todo/todo_app/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /todo/todo_app/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shahriaarrr/todo-with-django/83a02d4fa43f70260c16fb3b7ba831958b436942/todo/todo_app/api/__init__.py -------------------------------------------------------------------------------- /todo/todo_app/api/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from todo_app.models import Task 4 | 5 | class TaskSerializers(serializers.ModelSerializer): 6 | class Meta: 7 | model = Task 8 | fields = ('title', 'Priority', 'task_text', 'date') 9 | 10 | def validate(self, data): 11 | if data.get('title') == data.get('task_text'): 12 | raise serializers.ValidationError('The task title and its description can be the same') 13 | 14 | def validate_title(self, value): 15 | if len(value) > 10 or len(value) < 4: 16 | error='The task title should be a maximum of 10 characters and a minimum of 4 characters' 17 | raise serializers.ValidationError(error) 18 | 19 | return value 20 | 21 | class DeleteSerializers(serializers.ModelSerializer): 22 | class Meta: 23 | model = Task 24 | fields = ('title') 25 | 26 | def validate_title(self, value): 27 | tasks = Task.objects.get(title = value) 28 | if not tasks: 29 | raise serializers.ValidationError("your task should be add in database") 30 | 31 | return value -------------------------------------------------------------------------------- /todo/todo_app/api/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from .views import * 4 | 5 | urlpatterns = [ 6 | path('add-task', addTaskView.as_view()), 7 | path('delete-task', DeleteTaskAPIView.as_view()), 8 | ] 9 | -------------------------------------------------------------------------------- /todo/todo_app/api/views.py: -------------------------------------------------------------------------------- 1 | from rest_framework.response import Response 2 | from rest_framework.views import APIView 3 | from rest_framework.permissions import IsAuthenticated 4 | 5 | from .serializers import TaskSerializers, DeleteSerializers 6 | from todo_app.models import Task 7 | 8 | 9 | class addTaskView(APIView): 10 | permission_classes = (IsAuthenticated, ) 11 | 12 | def post(self, request): 13 | addTask = TaskSerializers(data=request.data) 14 | if addTask.is_valid(): 15 | data = TaskSerializers.validated_data 16 | Task.objects.create(**data) 17 | 18 | return Response({'message' : 'Your Task successfully add'}) 19 | 20 | class DeleteTaskAPIView(APIView): 21 | permission_classes = (IsAuthenticated, ) 22 | 23 | def post(self, request): 24 | delete_task = DeleteSerializers(data=request.data) 25 | if delete_task.is_valid(): 26 | data = DeleteSerializers.validated_data 27 | Task.objects.delete(**data) 28 | 29 | return Response({'message' : 'Your Task successfully deleted'}) -------------------------------------------------------------------------------- /todo/todo_app/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class TodoAppConfig(AppConfig): 5 | name = 'todo_app' 6 | -------------------------------------------------------------------------------- /todo/todo_app/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from .models import Task 4 | 5 | class TaskForm(forms.ModelForm): 6 | class Meta: 7 | model = Task 8 | fields = '__all__' -------------------------------------------------------------------------------- /todo/todo_app/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.4 on 2021-08-21 06:46 2 | 3 | import datetime 4 | from django.conf import settings 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | import django.db.models.manager 8 | from django.utils.timezone import utc 9 | 10 | 11 | class Migration(migrations.Migration): 12 | 13 | initial = True 14 | 15 | dependencies = [ 16 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 17 | ] 18 | 19 | operations = [ 20 | migrations.CreateModel( 21 | name='Task', 22 | fields=[ 23 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 24 | ('title', models.CharField(max_length=15)), 25 | ('Priority', models.CharField(choices=[('h', 'high'), ('l', 'low')], default='l', max_length=4)), 26 | ('task_text', models.TextField()), 27 | ('date', models.DateTimeField(default=datetime.datetime(2021, 8, 21, 6, 46, 1, 90495, tzinfo=utc))), 28 | ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 29 | ], 30 | managers=[ 31 | ('task', django.db.models.manager.Manager()), 32 | ], 33 | ), 34 | ] 35 | -------------------------------------------------------------------------------- /todo/todo_app/migrations/0002_auto_20210903_1032.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.6 on 2021-09-03 06:02 2 | 3 | import datetime 4 | from django.db import migrations, models 5 | from django.utils.timezone import utc 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('todo_app', '0001_initial'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterModelManagers( 16 | name='task', 17 | managers=[ 18 | ], 19 | ), 20 | migrations.AddField( 21 | model_name='task', 22 | name='done', 23 | field=models.BooleanField(default=False), 24 | ), 25 | migrations.AlterField( 26 | model_name='task', 27 | name='date', 28 | field=models.DateTimeField(default=datetime.datetime(2021, 9, 3, 6, 2, 2, 42706, tzinfo=utc)), 29 | ), 30 | ] 31 | -------------------------------------------------------------------------------- /todo/todo_app/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shahriaarrr/todo-with-django/83a02d4fa43f70260c16fb3b7ba831958b436942/todo/todo_app/migrations/__init__.py -------------------------------------------------------------------------------- /todo/todo_app/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.utils import timezone 3 | 4 | from account.models import User 5 | # Create your models here. 6 | class Task(models.Model): 7 | PRIORITY = ( 8 | ("h", "high"), 9 | ("l", "low"), 10 | ) 11 | author = models.ForeignKey(User, on_delete=models.CASCADE) 12 | title = models.CharField(max_length=15) 13 | Priority = models.CharField(max_length=4, choices=PRIORITY, default="l") 14 | task_text = models.TextField() 15 | done = models.BooleanField(default=False) 16 | date = models.DateTimeField(default=timezone.now()) 17 | 18 | def edit_title(self, new_title): 19 | self.title = new_title 20 | self.save() 21 | 22 | def edit_Priority(self, new_Priority): 23 | self.Priority = new_Priority 24 | self.save() 25 | 26 | def edit_task_text(self, new_text): 27 | self.task_text = new_text 28 | self.save() 29 | 30 | def edit_date(self, new_date): 31 | self.date = timezone.now() 32 | self.save() 33 | 34 | 35 | def __str__(self): 36 | return self.title 37 | -------------------------------------------------------------------------------- /todo/todo_app/templates/add_task.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block title %}Add Task{% endblock %} 4 | 5 | {% block content %} 6 |

your Task

7 |
{% csrf_token %} 8 | {{ form.as_p }} 9 | 10 |
11 | {% endblock %} -------------------------------------------------------------------------------- /todo/todo_app/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% block title %}{% endblock %} 8 | 9 | 10 | {% block content %}{% endblock %} 11 | 12 | -------------------------------------------------------------------------------- /todo/todo_app/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /todo/todo_app/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from .views import * 4 | 5 | urlpatterns = [ 6 | path('', home, name="main page"), 7 | path('add-task', addTask, name="addTask"), 8 | ] -------------------------------------------------------------------------------- /todo/todo_app/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.http import HttpResponse 3 | from django.views.decorators.csrf import csrf_exempt 4 | from django.contrib.auth.decorators import login_required 5 | 6 | 7 | from .forms import TaskForm 8 | # Create your views here. 9 | @csrf_exempt 10 | def home(request): 11 | return HttpResponse("

Welcom to Todo website

") 12 | 13 | 14 | @login_required(login_url='/accounts/login/') 15 | def addTask(request): 16 | #GET request 17 | if request.method == "GET": 18 | form = TaskForm() 19 | return render(request, 'add_task.html', {'form' : form}) 20 | 21 | #POST request 22 | if request.method == "POST": 23 | form = TaskForm(request.POST) 24 | if form.is_valid(): 25 | task = form.save() 26 | return HttpResponse(f"

your task({task.title}) seccessfuly add

") --------------------------------------------------------------------------------