Complete fake data loading via hopper

- Includes mods to task.created_date to allow overrides
This commit is contained in:
Scot Hacker 2018-04-05 00:27:53 -07:00
parent 403d1483f6
commit 1f27688aa4
9 changed files with 256 additions and 92 deletions

View file

@ -1,24 +1,19 @@
[[source]] [[source]]
url = "https://pypi.python.org/simple" url = "https://pypi.python.org/simple"
verify_ssl = true verify_ssl = true
name = "pypi" name = "pypi"
[packages] [packages]
django = "*" django = "*"
django-extensions = "*" django-extensions = "*"
"psycopg2-binary" = "*" "psycopg2-binary" = "*"
pytest = "*" pytest = "*"
pytest-django = "*" pytest-django = "*"
"flake8" = "*" "flake8" = "*"
factory-boy = "*"
titlecase = "*"
[dev-packages] [dev-packages]
[requires] [requires]
python_version = "3.6" python_version = "3.6"

142
Pipfile.lock generated
View file

@ -1,20 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "5a7237884b6690e23782690ae05e2d2ffd38a04d142f9fccc926860494073e9b" "sha256": "8aa62fe5923a75a6df757c643dbd98177e66bd0bc9e429d65006f042f73f5a32"
},
"host-environment-markers": {
"implementation_name": "cpython",
"implementation_version": "3.6.3",
"os_name": "posix",
"platform_machine": "x86_64",
"platform_python_implementation": "CPython",
"platform_release": "17.4.0",
"platform_system": "Darwin",
"platform_version": "Darwin Kernel Version 17.4.0: Sun Dec 17 09:19:54 PST 2017; root:xnu-4570.41.2~1/RELEASE_X86_64",
"python_full_version": "3.6.3",
"python_version": "3.6",
"sys_platform": "darwin"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@ -31,30 +18,48 @@
"default": { "default": {
"attrs": { "attrs": {
"hashes": [ "hashes": [
"sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450", "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9",
"sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9" "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450"
], ],
"version": "==17.4.0" "version": "==17.4.0"
}, },
"django": { "django": {
"hashes": [ "hashes": [
"sha256:3d9916515599f757043c690ae2b5ea28666afa09779636351da505396cbb2f19", "sha256:2d8b9eed8815f172a8e898678ae4289a5e9176bc08295676eff4228dd638ea61",
"sha256:769f212ffd5762f72c764fa648fca3b7f7dd4ec27407198b68e7c4abf4609fd0" "sha256:d81a1652963c81488e709729a80b510394050e312f386037f26b54912a3a10d0"
], ],
"version": "==2.0.3" "index": "pypi",
"version": "==2.0.4"
}, },
"django-extensions": { "django-extensions": {
"hashes": [ "hashes": [
"sha256:37a543af370ee3b0721ff50442d33c357dd083e6ea06c5b94a199283b6f9e361", "sha256:37a543af370ee3b0721ff50442d33c357dd083e6ea06c5b94a199283b6f9e361",
"sha256:bc9f2946c117bb2f49e5e0633eba783787790ae810ea112fe7fd82fa64de2ff1" "sha256:bc9f2946c117bb2f49e5e0633eba783787790ae810ea112fe7fd82fa64de2ff1"
], ],
"index": "pypi",
"version": "==2.0.6" "version": "==2.0.6"
}, },
"factory-boy": {
"hashes": [
"sha256:bd5a096d0f102d79b6c78cef1c8c0b650f2e1a3ecba351c735c6d2df8dabd29c",
"sha256:be2abc8092294e4097935a29b4e37f5b9ed3e4205e2e32df215c0315b625995e"
],
"index": "pypi",
"version": "==2.10.0"
},
"faker": {
"hashes": [
"sha256:9cc12b821f32ff45f6edfdc1ab7be3893b60b1224e952d68322a57e5b26a4a15",
"sha256:b06d0dc0166618298e668ced513ced7b10df34f3ad2045f22f1d7d88704e8e9c"
],
"version": "==0.8.12"
},
"flake8": { "flake8": {
"hashes": [ "hashes": [
"sha256:c7841163e2b576d435799169b78703ad6ac1bbb0f199994fc05f700b2a90ea37", "sha256:7253265f7abd8b313e3892944044a365e3f4ac3fcdcfb4298f55ee9ddf188ba0",
"sha256:7253265f7abd8b313e3892944044a365e3f4ac3fcdcfb4298f55ee9ddf188ba0" "sha256:c7841163e2b576d435799169b78703ad6ac1bbb0f199994fc05f700b2a90ea37"
], ],
"index": "pypi",
"version": "==3.5.0" "version": "==3.5.0"
}, },
"mccabe": { "mccabe": {
@ -66,8 +71,8 @@
}, },
"more-itertools": { "more-itertools": {
"hashes": [ "hashes": [
"sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e",
"sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea", "sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea",
"sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e",
"sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44" "sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44"
], ],
"version": "==4.1.0" "version": "==4.1.0"
@ -80,47 +85,48 @@
}, },
"psycopg2-binary": { "psycopg2-binary": {
"hashes": [ "hashes": [
"sha256:b287ddf4cafcfb632974907d1e7862119e36bb758228bdb07dd247553e4cdfc0",
"sha256:d1dd3eb8edd354083f5d27b968c5a17854c41347ba5a480b520be85ec1a8495c",
"sha256:cf3911fba0c47fc1313b5783183cda301032b14637a0b7a336766ae46998c7ee",
"sha256:b039f51bca1ddd70234cc3f84f94f42ad43861b931bdfb497f887c60c39a6565",
"sha256:83af04029bcb4b56c852e5876fef71340dcb465fa44fc99f80bac72e10fb0b74",
"sha256:3a14baeabcebd4662f12f4bff03e0574a2369a2e41baf829e6fb4a24c95cf88b",
"sha256:cb07184a4bfad304831f0a88b1c13fbd8cf9fcdf1f11e71c477dd6d7b1b078a0",
"sha256:d0972f062c73956332e9681dfdb133168618f0abfecc96e89f0205ac89cd454b",
"sha256:ab1db8f3e96570d9f7ebc45133ce2574804b2280499baade178e163d022107b5",
"sha256:d51c7ed810fce1e50464088c37cc8da05534de8afb12a732500827ebcc480081",
"sha256:b6b2b26590304d97ef2af28d153ee99ace6fe0806934f4618edfc87216c77f91",
"sha256:9b5ddbed85ec73293695d7116589d956ef0dd3fcf7bf3b2a3bc1e8e54c1d543a",
"sha256:02eb674e3d5810e19b4d5d00720b17130e182da1ba259dda608aaf33d787347d", "sha256:02eb674e3d5810e19b4d5d00720b17130e182da1ba259dda608aaf33d787347d",
"sha256:3a14baeabcebd4662f12f4bff03e0574a2369a2e41baf829e6fb4a24c95cf88b",
"sha256:436a503eda41f6adb08f292f40a3784fce0a5f351b6ae7b19a911904db53af93", "sha256:436a503eda41f6adb08f292f40a3784fce0a5f351b6ae7b19a911904db53af93",
"sha256:8014c06a9ed7b78ba81beff3ae71acd78c212390f8ed839e9ce22735880bd5b4",
"sha256:c4c6004d410c77bfa5389ae9485498ce32805447a67afbfe8db0d247a5c88fa1",
"sha256:d8940b5104588d6313315e037f0f5ed68d2e5f62ccc1c429d3cff11d2ba6de3f",
"sha256:c606bff0978ee4858d86d40f6b6ab0c4cac4474f627bd054683dc03a4fc1a366",
"sha256:9305d7cbc802aaefac5c75a3df725f2654797369f32b18d4d0adb382dfab6c09",
"sha256:4a1a5ea2fa4b53191637b162873a82822d92a85a08beefe28296b8eb5cf2fea5",
"sha256:a3d2cc0cb0b988dbfd0d11f7fac34058b25a6ce533ed5b8e88d6cb315e77d54a",
"sha256:86c0d2587f56776f25d52cca8e275adf495c8e01933fbfc2ca23b124610ab761",
"sha256:77a2fc622a1f2d08a707673c9be5769d521f03d867d305f172bb417fa7882754",
"sha256:4a4f23a08fbccbe40ecdb5384d807bcb469ea71dd87e6be2e80b036b8e6d47df",
"sha256:c8220c521a408b41c4f14036004a621ed0d965941286b978cd2ea2623fabd755",
"sha256:465ff1d427ed42c31e456dbbd9edab3552be18a0edaef7450c5b3e6fee745052", "sha256:465ff1d427ed42c31e456dbbd9edab3552be18a0edaef7450c5b3e6fee745052",
"sha256:4a1a5ea2fa4b53191637b162873a82822d92a85a08beefe28296b8eb5cf2fea5",
"sha256:4a4f23a08fbccbe40ecdb5384d807bcb469ea71dd87e6be2e80b036b8e6d47df",
"sha256:77a2fc622a1f2d08a707673c9be5769d521f03d867d305f172bb417fa7882754",
"sha256:8014c06a9ed7b78ba81beff3ae71acd78c212390f8ed839e9ce22735880bd5b4",
"sha256:83af04029bcb4b56c852e5876fef71340dcb465fa44fc99f80bac72e10fb0b74",
"sha256:86c0d2587f56776f25d52cca8e275adf495c8e01933fbfc2ca23b124610ab761",
"sha256:9305d7cbc802aaefac5c75a3df725f2654797369f32b18d4d0adb382dfab6c09",
"sha256:9b5ddbed85ec73293695d7116589d956ef0dd3fcf7bf3b2a3bc1e8e54c1d543a",
"sha256:a3d2cc0cb0b988dbfd0d11f7fac34058b25a6ce533ed5b8e88d6cb315e77d54a",
"sha256:ab1db8f3e96570d9f7ebc45133ce2574804b2280499baade178e163d022107b5",
"sha256:b039f51bca1ddd70234cc3f84f94f42ad43861b931bdfb497f887c60c39a6565",
"sha256:b287ddf4cafcfb632974907d1e7862119e36bb758228bdb07dd247553e4cdfc0",
"sha256:b6b2b26590304d97ef2af28d153ee99ace6fe0806934f4618edfc87216c77f91",
"sha256:c4c6004d410c77bfa5389ae9485498ce32805447a67afbfe8db0d247a5c88fa1",
"sha256:c606bff0978ee4858d86d40f6b6ab0c4cac4474f627bd054683dc03a4fc1a366",
"sha256:c8220c521a408b41c4f14036004a621ed0d965941286b978cd2ea2623fabd755",
"sha256:cb07184a4bfad304831f0a88b1c13fbd8cf9fcdf1f11e71c477dd6d7b1b078a0",
"sha256:cf3911fba0c47fc1313b5783183cda301032b14637a0b7a336766ae46998c7ee",
"sha256:d0972f062c73956332e9681dfdb133168618f0abfecc96e89f0205ac89cd454b",
"sha256:d1dd3eb8edd354083f5d27b968c5a17854c41347ba5a480b520be85ec1a8495c",
"sha256:d51c7ed810fce1e50464088c37cc8da05534de8afb12a732500827ebcc480081",
"sha256:d8940b5104588d6313315e037f0f5ed68d2e5f62ccc1c429d3cff11d2ba6de3f",
"sha256:de4f88f823037a71ea5ef3c1041d96b8a68d73343133edda684fd42f575bd9d7" "sha256:de4f88f823037a71ea5ef3c1041d96b8a68d73343133edda684fd42f575bd9d7"
], ],
"index": "pypi",
"version": "==2.7.4" "version": "==2.7.4"
}, },
"py": { "py": {
"hashes": [ "hashes": [
"sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a", "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881",
"sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881" "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a"
], ],
"version": "==1.5.3" "version": "==1.5.3"
}, },
"pycodestyle": { "pycodestyle": {
"hashes": [ "hashes": [
"sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9", "sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766",
"sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766" "sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9"
], ],
"version": "==2.3.1" "version": "==2.3.1"
}, },
@ -136,6 +142,7 @@
"sha256:6266f87ab64692112e5477eba395cfedda53b1933ccd29478e671e73b420c19c", "sha256:6266f87ab64692112e5477eba395cfedda53b1933ccd29478e671e73b420c19c",
"sha256:fae491d1874f199537fd5872b5e1f0e74a009b979df9d53d1553fd03da1703e1" "sha256:fae491d1874f199537fd5872b5e1f0e74a009b979df9d53d1553fd03da1703e1"
], ],
"index": "pypi",
"version": "==3.5.0" "version": "==3.5.0"
}, },
"pytest-django": { "pytest-django": {
@ -143,28 +150,51 @@
"sha256:00995c2999b884a38ae9cd30a8c00ed32b3d38c1041250ea84caf18085589662", "sha256:00995c2999b884a38ae9cd30a8c00ed32b3d38c1041250ea84caf18085589662",
"sha256:038ccc5a9daa1b1b0eb739ab7dce54e495811eca5ea3af4815a2a3ac45152309" "sha256:038ccc5a9daa1b1b0eb739ab7dce54e495811eca5ea3af4815a2a3ac45152309"
], ],
"index": "pypi",
"version": "==3.1.2" "version": "==3.1.2"
}, },
"python-dateutil": {
"hashes": [
"sha256:3220490fb9741e2342e1cf29a503394fdac874bc39568288717ee67047ff29df",
"sha256:9d8074be4c993fbe4947878ce593052f71dac82932a677d49194d8ce9778002e"
],
"version": "==2.7.2"
},
"pytz": { "pytz": {
"hashes": [ "hashes": [
"sha256:ed6509d9af298b7995d69a440e2822288f2eca1681b8cce37673dbb10091e5fe",
"sha256:f93ddcdd6342f94cea379c73cddb5724e0d6d0a1c91c9bdef364dc0368ba4fda",
"sha256:61242a9abc626379574a166dc0e96a66cd7c3b27fc10868003fa210be4bff1c9",
"sha256:ba18e6a243b3625513d85239b3e49055a2f0318466e0b8a92b8fb8ca7ccdf55f",
"sha256:07edfc3d4d2705a20a6e99d97f0c4b61c800b8232dc1c04d87e8554f130148dd", "sha256:07edfc3d4d2705a20a6e99d97f0c4b61c800b8232dc1c04d87e8554f130148dd",
"sha256:3a47ff71597f821cd84a162e71593004286e5be07a340fd462f0d33a760782b5", "sha256:3a47ff71597f821cd84a162e71593004286e5be07a340fd462f0d33a760782b5",
"sha256:410bcd1d6409026fbaa65d9ed33bf6dd8b1e94a499e32168acfc7b332e4095c0",
"sha256:5bd55c744e6feaa4d599a6cbd8228b4f8f9ba96de2c38d56f08e534b3c9edf0d", "sha256:5bd55c744e6feaa4d599a6cbd8228b4f8f9ba96de2c38d56f08e534b3c9edf0d",
"sha256:61242a9abc626379574a166dc0e96a66cd7c3b27fc10868003fa210be4bff1c9",
"sha256:887ab5e5b32e4d0c86efddd3d055c1f363cbaa583beb8da5e22d2fa2f64d51ef", "sha256:887ab5e5b32e4d0c86efddd3d055c1f363cbaa583beb8da5e22d2fa2f64d51ef",
"sha256:410bcd1d6409026fbaa65d9ed33bf6dd8b1e94a499e32168acfc7b332e4095c0" "sha256:ba18e6a243b3625513d85239b3e49055a2f0318466e0b8a92b8fb8ca7ccdf55f",
"sha256:ed6509d9af298b7995d69a440e2822288f2eca1681b8cce37673dbb10091e5fe",
"sha256:f93ddcdd6342f94cea379c73cddb5724e0d6d0a1c91c9bdef364dc0368ba4fda"
], ],
"version": "==2018.3" "version": "==2018.3"
}, },
"six": { "six": {
"hashes": [ "hashes": [
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb", "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9" "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
], ],
"version": "==1.11.0" "version": "==1.11.0"
},
"text-unidecode": {
"hashes": [
"sha256:5a1375bb2ba7968740508ae38d92e1f889a0832913cb1c447d5e2046061a396d",
"sha256:801e38bd550b943563660a91de8d4b6fa5df60a542be9093f7abf819f86050cc"
],
"version": "==1.2"
},
"titlecase": {
"hashes": [
"sha256:84de7a97fb702c400e5ba11c6b30849944b39db12e20fbf4515a23c7538a0611",
"sha256:95d643a0c08097c02933aced707adfe1c275c335019e8e514dea782a465c5b84"
],
"index": "pypi",
"version": "==0.12.0"
} }
}, },
"develop": {} "develop": {}

View file

@ -1,8 +1,7 @@
from django import forms from django import forms
from django.forms import ModelForm
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.forms import ModelForm
from todo.models import Task, TaskList from todo.models import Task, TaskList
from django.contrib.auth import get_user_model
class AddTaskListForm(ModelForm): class AddTaskListForm(ModelForm):
@ -18,16 +17,18 @@ class AddTaskListForm(ModelForm):
class Meta: class Meta:
model = TaskList model = TaskList
exclude = [] exclude = ['created_date', ]
class AddEditTaskForm(ModelForm): class AddEditTaskForm(ModelForm):
"""The picklist showing the users to which a new task can be assigned """The picklist showing the users to which a new task can be assigned
must find other members of the groups the current list belongs to.""" must find other members of the group this TaskList is attached to."""
def __init__(self, user, *args, **kwargs): def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields['assigned_to'].queryset = get_user_model().objects.filter(groups__in=user.groups.all()).distinct() task_list = kwargs.get('initial').get('task_list')
members = task_list.group.user_set.all()
self.fields['assigned_to'].queryset = members
self.fields['assigned_to'].label_from_instance = lambda obj: "%s (%s)" % (obj.get_full_name(), obj.username) self.fields['assigned_to'].label_from_instance = lambda obj: "%s (%s)" % (obj.get_full_name(), obj.username)
self.fields['assigned_to'].widget.attrs = { self.fields['assigned_to'].widget.attrs = {
'id': 'id_assigned_to', 'class': "custom-select mb-3", 'name': 'assigned_to'} 'id': 'id_assigned_to', 'class': "custom-select mb-3", 'name': 'assigned_to'}

View file

@ -1,7 +1,39 @@
import factory
from faker import Faker
from titlecase import titlecase
import random
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from todo.models import Task, TaskList
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.utils.text import slugify
from todo.models import Task, TaskList
num_lists = 5
num_tasks_per_list = 10
def gen_title(tc=True):
# faker doesn't provide a way to generate headlines in Title Case, without periods, so make our own.
# With arg `tc=True`, Title Cases The Generated Text
fake = Faker()
thestr = fake.text(max_nb_chars=32).rstrip('.')
if tc:
thestr = titlecase(thestr)
return thestr
def gen_content():
# faker provides paragraphs as a list; convert with linebreaks
fake = Faker()
grafs = fake.paragraphs()
thestr = ''
for g in grafs:
thestr += "{}\n\n".format(g)
return thestr
class Command(BaseCommand): class Command(BaseCommand):
@ -9,25 +41,99 @@ class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
# Wipe out previous contents. Cascade deletes the Tasks from the TaskLists.
TaskList.objects.all().delete()
print("Content from previous run deleted.")
print("Working...")
fake = Faker() # Use to create user's names
# Create users and groups, add different users to different groups. Staff user is in both groups. # Create users and groups, add different users to different groups. Staff user is in both groups.
bw_group = Group.objects.create(name='Basket Weavers') sd_group, created = Group.objects.get_or_create(name='Scuba Divers')
sd_group = Group.objects.create(name='Scuba Divers') bw_group, created = Group.objects.get_or_create(name='Basket Weavers')
usernames = ['user1', 'user2', 'staff_user']
# Put user1 and user2 in one group, user3 and user4 in another
usernames = ['user1', 'user2', 'user3', 'user4', 'staffer']
for username in usernames: for username in usernames:
get_user_model().objects.create_user(username=username, password="todo") if get_user_model().objects.filter(username=username).exists():
user = get_user_model().objects.get(username=username)
else:
user = get_user_model().objects.create_user(
username=username,
first_name=fake.first_name(),
last_name=fake.last_name(),
email=fake.email(),
password="todo")
if username == 'user1': if username in ['user1', 'user2']:
u1 = get_user_model().objects.get(username=username) user.groups.add(bw_group)
u1.groups.add(bw_group)
if username == 'user2': if username in ['user3', 'user4']:
u2 = get_user_model().objects.get(username=username) user.groups.add(sd_group)
u2.groups.add(sd_group)
if username == 'staff_user': if username == 'staffer':
staffer = get_user_model().objects.get(username=username, is_staff=True,) user.is_staff = True
staffer.groups.add(bw_group) user.first_name = fake.first_name()
staffer.groups.add(sd_group) user.last_name = fake.last_name()
user.save()
user.groups.add(bw_group)
user.groups.add(sd_group)
# Create lists with tasks
TaskListFactory.create_batch(5, group=bw_group)
TaskListFactory.create_batch(5, group=sd_group)
print("For each of two groups, created {} fake tasks in each of {} fake lists.".format(
num_lists, num_tasks_per_list)
)
class TaskListFactory(factory.django.DjangoModelFactory):
"""Group not generated here - call with group as arg."""
class Meta:
model = TaskList
name = factory.LazyAttribute(lambda o: gen_title(tc=True))
slug = factory.LazyAttribute(lambda o: slugify(o.name))
group = None # Pass this in
@factory.post_generation
def add_tasks(self, build, extracted, **kwargs):
TaskFactory.create_batch(num_tasks_per_list, task_list=self)
class TaskFactory(factory.django.DjangoModelFactory):
"""TaskList not generated here - call with TaskList as arg."""
class Meta:
model = Task
title = factory.LazyAttribute(lambda o: gen_title(tc=False))
task_list = None # Pass this in
note = factory.LazyAttribute(lambda o: gen_content())
priority = factory.LazyAttribute(lambda o: random.randint(1, 100))
completed = factory.Faker('boolean', chance_of_getting_true=30)
created_by = get_user_model().objects.get(username='staffer') # Randomized in post
created_date = factory.Faker('date_this_year')
@factory.post_generation
def add_details(self, build, extracted, **kwargs):
fake = Faker() # Use to create user's names
taskgroup = self.task_list.group
self.created_by = taskgroup.user_set.all().order_by('?').first()
if self.completed:
self.completed_date = fake.date_this_year()
# 1/3 of generated tasks have a due_date
if random.randint(1, 3) == 1:
self.due_date = fake.date_this_year()
# 1/3 of generated tasks are assigned to someone in this tasks's group
if random.randint(1, 3) == 1:
self.assigned_to = taskgroup.user_set.all().order_by('?').first()
self.save()

View file

@ -0,0 +1,19 @@
# Generated by Django 2.0.4 on 2018-04-05 00:24
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('todo', '0006_rename_item_model'),
]
operations = [
migrations.AlterField(
model_name='task',
name='created_date',
field=models.DateField(blank=True, default=django.utils.timezone.now, null=True),
),
]

View file

@ -5,6 +5,7 @@ from django.conf import settings
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.db import models from django.db import models
from django.urls import reverse from django.urls import reverse
from django.utils import timezone
class TaskList(models.Model): class TaskList(models.Model):
@ -26,7 +27,7 @@ class TaskList(models.Model):
class Task(models.Model): class Task(models.Model):
title = models.CharField(max_length=140) title = models.CharField(max_length=140)
task_list = models.ForeignKey(TaskList, on_delete=models.CASCADE, null=True) task_list = models.ForeignKey(TaskList, on_delete=models.CASCADE, null=True)
created_date = models.DateField(auto_now=True) created_date = models.DateField(default=timezone.now, blank=True, null=True)
due_date = models.DateField(blank=True, null=True, ) due_date = models.DateField(blank=True, null=True, )
completed = models.BooleanField(default=False) completed = models.BooleanField(default=False)
completed_date = models.DateField(blank=True, null=True) completed_date = models.DateField(blank=True, null=True)

View file

@ -3,6 +3,7 @@
<form action="" name="add_task" method="post"> <form action="" name="add_task" method="post">
{% csrf_token %} {% csrf_token %}
<div id="AddEditTask" class="collapse mt-3"> <div id="AddEditTask" class="collapse mt-3">
<div class="form-group"> <div class="form-group">
<label for="id_title" name="title">Task</label> <label for="id_title" name="title">Task</label>

View file

@ -34,9 +34,17 @@
<li class="list-group-item"> <li class="list-group-item">
<strong>Due date:</strong> {{ task.due_date }} <strong>Due date:</strong> {{ task.due_date }}
</li> </li>
{% if task.completed %}
<li class="list-group-item">
<strong>Completed on:</strong> {{ task.completed_date}}
</li>
{% else %}
<li class="list-group-item"> <li class="list-group-item">
<strong>Completed:</strong> {{ task.completed|yesno:"Yes,No" }} <strong>Completed:</strong> {{ task.completed|yesno:"Yes,No" }}
</li> </li>
{% endif %}
<li class="list-group-item"> <li class="list-group-item">
<strong>In list:</strong> <strong>In list:</strong>
<a href="{% url 'todo:list_detail' task.task_list.id task.task_list.slug %}"> <a href="{% url 'todo:list_detail' task.task_list.id task.task_list.slug %}">

View file

@ -13,6 +13,7 @@ from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render, redirect from django.shortcuts import get_object_or_404, render, redirect
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
from django.utils import timezone
from todo.forms import AddTaskListForm, AddEditTaskForm, AddExternalTaskForm, SearchForm from todo.forms import AddTaskListForm, AddEditTaskForm, AddExternalTaskForm, SearchForm
from todo.models import Task, TaskList, Comment from todo.models import Task, TaskList, Comment
@ -157,10 +158,12 @@ def list_detail(request, list_id=None, list_slug=None, view_completed=False):
}) })
if form.is_valid(): if form.is_valid():
new_task = form.save() new_task = form.save(commit=False)
new_task.created_date = timezone.now()
form.save()
# Send email alert only if Notify checkbox is checked AND assignee is not same as the submitter # Send email alert only if Notify checkbox is checked AND assignee is not same as the submitter
if "notify" in request.POST and new_task.assigned_to != request.user: if "notify" in request.POST and new_task.assigned_to and new_task.assigned_to != request.user:
send_notify_mail(new_task) send_notify_mail(new_task)
messages.success(request, "New task \"{t}\" has been added.".format(t=new_task.title)) messages.success(request, "New task \"{t}\" has been added.".format(t=new_task.title))
@ -171,7 +174,7 @@ def list_detail(request, list_id=None, list_slug=None, view_completed=False):
form = AddEditTaskForm(request.user, initial={ form = AddEditTaskForm(request.user, initial={
'assigned_to': request.user.id, 'assigned_to': request.user.id,
'priority': 999, 'priority': 999,
'task_list': task_list 'task_list': task_list,
}) })
context = { context = {