├── .gitignore
├── LICENSE
├── README.md
├── azure-pipelines.yml
├── requirements.txt
├── results
└── django-to-do.gif
└── todo
├── manage.py
├── static
├── css
│ └── custom.css
└── images
│ ├── dexter.gif
│ ├── dexter.png
│ ├── tasker.png
│ └── wa.png
├── tasks
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│ ├── 0001_initial.py
│ ├── 0002_task_priority.py
│ ├── 0003_task_complete.py
│ ├── 0004_auto_20180506_0853.py
│ ├── 0005_auto_20180506_0932.py
│ ├── 0006_auto_20180506_0940.py
│ ├── 0007_auto_20180506_0946.py
│ ├── 0008_auto_20180507_0326.py
│ ├── 0009_auto_20180507_0328.py
│ └── __init__.py
├── models.py
├── templates
│ ├── base.html
│ └── tasks.html
├── templatetags
│ └── tags.py
├── tests.py
├── urls.py
└── views.py
└── todo
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__/
2 | *.pyc
3 | *.sqlite3
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Omkar Pathak
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 | # Django-to-do
2 | A dead simple Django ToDo Web App
3 |
4 | This is a sample project that a novice django developer can use to get started.
5 |
6 | ## Working
7 |
8 | 
9 |
10 | ## Features
11 |
12 | - Dead simple
13 | - Easily add, delete
14 | - Simple UI
15 | - Blazing fast
16 |
17 | ## Setup
18 |
19 | - Download the files from this repo
20 | - Change the directory to the folder where you downloaded files
21 | - For installing required packages, execute the following command in terminal:
22 |
23 | ```bash
24 | $pip install -r requirements.txt
25 | ```
26 |
27 | - After successful installation execute the following commands:
28 |
29 | ```bash
30 | $python manage.py migrate
31 | $python manage.py runserver
32 | ```
33 |
34 | - Visit `127.0.0.1:8000` in your browser to enjoy the awesome app!
35 |
36 | Built with ♥ by [`Omkar Pathak`](http://www.omkarpathak.in/)
37 |
38 | # Donation
39 |
40 | If you have found my softwares to be of any use to you, do consider helping me pay my internet bills. This would encourage me to create many such softwares :)
41 |
42 | | PayPal | |
43 | |:-------------------------------------------:|:-------------------------------------------------------------:|
44 | | ₹ (INR) |
|
45 |
--------------------------------------------------------------------------------
/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | # Python Django
2 | # Test a Django project on multiple versions of Python.
3 | # Add steps that analyze code, save build artifacts, deploy, and more:
4 | # https://docs.microsoft.com/vsts/pipelines/languages/python
5 |
6 | pool:
7 | vmImage: 'Ubuntu 16.04'
8 | strategy:
9 | matrix:
10 | Python35:
11 | PYTHON_VERSION: '3.5'
12 | Python36:
13 | PYTHON_VERSION: '3.6'
14 | Python37:
15 | PYTHON_VERSION: '3.7'
16 | maxParallel: 3
17 |
18 | steps:
19 | - task: UsePythonVersion@0
20 | inputs:
21 | versionSpec: '$(PYTHON_VERSION)'
22 | architecture: 'x64'
23 |
24 | - task: PythonScript@0
25 | displayName: 'Export project path'
26 | inputs:
27 | scriptSource: 'inline'
28 | script: |
29 | """Search all subdirectories for `manage.py`."""
30 | from glob import iglob
31 | from os import path
32 | # Python >= 3.5
33 | manage_py = next(iglob(path.join('**', 'manage.py'), recursive=True), None)
34 | if not manage_py:
35 | raise SystemExit('Could not find a Django project')
36 | project_location = path.dirname(path.abspath(manage_py))
37 | print('Found Django project in', project_location)
38 | print('##vso[task.setvariable variable=projectRoot]{}'.format(project_location))
39 |
40 | - script: |
41 | python -m pip install --upgrade pip setuptools wheel
42 | pip install -r requirements.txt
43 | pip install unittest-xml-reporting
44 | displayName: 'Install prerequisites'
45 |
46 | - script: |
47 | pushd '$(projectRoot)'
48 | python manage.py test --testrunner xmlrunner.extra.djangotestrunner.XMLTestRunner --no-input
49 | condition: succeededOrFailed()
50 | displayName: 'Run tests'
51 |
52 | - task: PublishTestResults@2
53 | inputs:
54 | testResultsFiles: "**/TEST-*.xml"
55 | testRunTitle: 'Python $(PYTHON_VERSION)'
56 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | Django==2.0.8
2 | pytz==2018.4
3 |
--------------------------------------------------------------------------------
/results/django-to-do.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OmkarPathak/Django-to-do/3acbb8d91e375fb18fbc0b53931d76a5ca5a7b06/results/django-to-do.gif
--------------------------------------------------------------------------------
/todo/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "todo.settings")
7 | try:
8 | from django.core.management import execute_from_command_line
9 | except ImportError as exc:
10 | raise ImportError(
11 | "Couldn't import Django. Are you sure it's installed and "
12 | "available on your PYTHONPATH environment variable? Did you "
13 | "forget to activate a virtual environment?"
14 | ) from exc
15 | execute_from_command_line(sys.argv)
16 |
--------------------------------------------------------------------------------
/todo/static/css/custom.css:
--------------------------------------------------------------------------------
1 | .adanger{
2 | color: #dc3545; /* red */
3 | }
4 |
5 | .bwarning{
6 | color: #ffc107; /* orange */
7 | }
8 |
9 | .csuccess{
10 | color: #28a745; /* green */
11 | }
12 |
13 | .dprimary{
14 | color: #007bff; /* blue */
15 | }
16 |
17 | .adanger:hover{
18 | color: #dc3545; /* red */
19 | }
20 |
21 | .bwarning:hover{
22 | color: #ffc107; /* orange */
23 | }
24 |
25 | .csuccess:hover{
26 | color: #28a745; /* green */
27 | }
28 |
29 | .dprimary:hover{
30 | color: #007bff; /* blue */
31 | }
32 |
--------------------------------------------------------------------------------
/todo/static/images/dexter.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OmkarPathak/Django-to-do/3acbb8d91e375fb18fbc0b53931d76a5ca5a7b06/todo/static/images/dexter.gif
--------------------------------------------------------------------------------
/todo/static/images/dexter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OmkarPathak/Django-to-do/3acbb8d91e375fb18fbc0b53931d76a5ca5a7b06/todo/static/images/dexter.png
--------------------------------------------------------------------------------
/todo/static/images/tasker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OmkarPathak/Django-to-do/3acbb8d91e375fb18fbc0b53931d76a5ca5a7b06/todo/static/images/tasker.png
--------------------------------------------------------------------------------
/todo/static/images/wa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OmkarPathak/Django-to-do/3acbb8d91e375fb18fbc0b53931d76a5ca5a7b06/todo/static/images/wa.png
--------------------------------------------------------------------------------
/todo/tasks/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OmkarPathak/Django-to-do/3acbb8d91e375fb18fbc0b53931d76a5ca5a7b06/todo/tasks/__init__.py
--------------------------------------------------------------------------------
/todo/tasks/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from .models import Task, Username
3 |
4 | # Register your models here.
5 | class MyModelAdmin(admin.ModelAdmin):
6 | class Meta:
7 | model = Task
8 |
9 | class UsernameAdmin(admin.ModelAdmin):
10 | class Meta:
11 | model = Username
12 |
13 | admin.site.register(Task, MyModelAdmin)
14 | admin.site.register(Username, UsernameAdmin)
15 |
--------------------------------------------------------------------------------
/todo/tasks/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class TasksConfig(AppConfig):
5 | name = 'tasks'
6 |
--------------------------------------------------------------------------------
/todo/tasks/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.5 on 2018-05-03 09:49
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | initial = True
9 |
10 | dependencies = [
11 | ]
12 |
13 | operations = [
14 | migrations.CreateModel(
15 | name='Task',
16 | fields=[
17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18 | ('title', models.CharField(max_length=200)),
19 | ('description', models.CharField(blank=True, max_length=1000)),
20 | ('date_of_creation', models.DateTimeField(auto_now_add=True)),
21 | ],
22 | ),
23 | ]
24 |
--------------------------------------------------------------------------------
/todo/tasks/migrations/0002_task_priority.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.5 on 2018-05-04 10:14
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('tasks', '0001_initial'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='task',
15 | name='priority',
16 | field=models.CharField(choices=[('danger', 'Priority 1'), ('warning', 'Priority 2'), ('success', 'Priority 3'), ('primary', 'Priority 4')], default='danger', max_length=30),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/todo/tasks/migrations/0003_task_complete.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.4 on 2018-05-05 04:06
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('tasks', '0002_task_priority'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='task',
15 | name='complete',
16 | field=models.IntegerField(default=0),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/todo/tasks/migrations/0004_auto_20180506_0853.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.5 on 2018-05-06 08:53
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('tasks', '0003_task_complete'),
10 | ]
11 |
12 | operations = [
13 | migrations.CreateModel(
14 | name='Username',
15 | fields=[
16 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17 | ('username', models.CharField(max_length=50)),
18 | ],
19 | ),
20 | migrations.AlterField(
21 | model_name='task',
22 | name='priority',
23 | field=models.CharField(choices=[('adanger', 'Priority 1'), ('bwarning', 'Priority 2'), ('csuccess', 'Priority 3'), ('dprimary', 'Priority 4')], default='adanger', max_length=30),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/todo/tasks/migrations/0005_auto_20180506_0932.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.5 on 2018-05-06 09:32
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('tasks', '0004_auto_20180506_0853'),
10 | ]
11 |
12 | operations = [
13 | migrations.DeleteModel(
14 | name='Username',
15 | ),
16 | migrations.AddField(
17 | model_name='task',
18 | name='username',
19 | field=models.CharField(default='omkar', max_length=50, unique=True),
20 | preserve_default=False,
21 | ),
22 | ]
23 |
--------------------------------------------------------------------------------
/todo/tasks/migrations/0006_auto_20180506_0940.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.5 on 2018-05-06 09:40
2 |
3 | from django.db import migrations, models
4 | import django.db.models.deletion
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('tasks', '0005_auto_20180506_0932'),
11 | ]
12 |
13 | operations = [
14 | migrations.CreateModel(
15 | name='Username',
16 | fields=[
17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18 | ('username', models.CharField(max_length=50, unique=True)),
19 | ],
20 | ),
21 | migrations.AlterField(
22 | model_name='task',
23 | name='username',
24 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tasks.Username'),
25 | ),
26 | ]
27 |
--------------------------------------------------------------------------------
/todo/tasks/migrations/0007_auto_20180506_0946.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.5 on 2018-05-06 09:46
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('tasks', '0006_auto_20180506_0940'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='task',
15 | name='id',
16 | field=models.AutoField(primary_key=True, serialize=False),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/todo/tasks/migrations/0008_auto_20180507_0326.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.5 on 2018-05-07 03:26
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('tasks', '0007_auto_20180506_0946'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='task',
15 | name='priority',
16 | field=models.CharField(choices=[('adanger', 'Priority 1'), ('bwarning', 'Priority 2'), ('csuccess', 'Priority 3'), ('dprimary', 'Priority 4')], default='Select Priority', max_length=30),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/todo/tasks/migrations/0009_auto_20180507_0328.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.5 on 2018-05-07 03:28
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('tasks', '0008_auto_20180507_0326'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='task',
15 | name='priority',
16 | field=models.CharField(choices=[('adanger', 'Priority High'), ('bwarning', 'Priority Medium'), ('csuccess', 'Priority Low')], default='adanger', max_length=30),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/todo/tasks/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OmkarPathak/Django-to-do/3acbb8d91e375fb18fbc0b53931d76a5ca5a7b06/todo/tasks/migrations/__init__.py
--------------------------------------------------------------------------------
/todo/tasks/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from django.forms import ModelForm
3 | from django import forms
4 |
5 | PRIORITIES = (
6 | ('adanger', 'Priority High'),
7 | ('bwarning', 'Priority Medium'),
8 | ('csuccess', 'Priority Low')
9 | )
10 |
11 | # Create your models here.
12 | class Username(models.Model):
13 | username = models.CharField(max_length=50, unique=True)
14 |
15 | def __str__(self):
16 | return self.username
17 |
18 | class Task(models.Model):
19 | id = models.AutoField(primary_key=True)
20 | username = models.ForeignKey(Username, on_delete=models.CASCADE)
21 | title = models.CharField(max_length=200)
22 | description = models.CharField(max_length=1000, blank=True)
23 | date_of_creation = models.DateTimeField(auto_now_add=True)
24 | priority = models.CharField(
25 | max_length=30,
26 | choices=PRIORITIES,
27 | default=PRIORITIES[0][0]
28 | )
29 | complete = models.IntegerField(default=0)
30 |
31 | class TaskForm(ModelForm):
32 | class Meta:
33 | model = Task
34 | fields = '__all__'
35 | exclude = ['complete', 'date_of_creation', 'username']
36 | widgets = {
37 | 'title': forms.TextInput(attrs={'placeholder': "What's on your mind today?"}),
38 | 'description': forms.Textarea(attrs={'placeholder': "Describe your task ..", 'cols': 80, 'rows': 3}),
39 | }
40 |
41 | class UsernameForm(ModelForm):
42 | class Meta:
43 | model = Username
44 | fields = '__all__'
45 |
46 | widgets = {
47 | 'username': forms.TextInput(attrs={'placeholder': "Enter a username"}),
48 | }
49 |
50 | def clean_username(self):
51 | username = self.cleaned_data.get('username')
52 | queryset = Username.objects.filter(username=username).count()
53 | if queryset > 0:
54 | raise forms.ValidationError('This username is already taken! Try a different one :)')
55 | return username
56 |
--------------------------------------------------------------------------------
/todo/tasks/templates/base.html:
--------------------------------------------------------------------------------
1 |
2 | {% load static %}
3 |
4 |