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,8 +1,7 @@
from django import forms
from django.forms import ModelForm
from django.contrib.auth.models import Group
from django.forms import ModelForm
from todo.models import Task, TaskList
from django.contrib.auth import get_user_model
class AddTaskListForm(ModelForm):
@ -18,16 +17,18 @@ class AddTaskListForm(ModelForm):
class Meta:
model = TaskList
exclude = []
exclude = ['created_date', ]
class AddEditTaskForm(ModelForm):
"""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):
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'].widget.attrs = {
'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.contrib.auth.models import Group
from todo.models import Task, TaskList
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):
@ -9,25 +41,99 @@ class Command(BaseCommand):
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.
bw_group = Group.objects.create(name='Basket Weavers')
sd_group = Group.objects.create(name='Scuba Divers')
usernames = ['user1', 'user2', 'staff_user']
sd_group, created = Group.objects.get_or_create(name='Scuba Divers')
bw_group, created = Group.objects.get_or_create(name='Basket Weavers')
# Put user1 and user2 in one group, user3 and user4 in another
usernames = ['user1', 'user2', 'user3', 'user4', 'staffer']
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':
u1 = get_user_model().objects.get(username=username)
u1.groups.add(bw_group)
if username in ['user1', 'user2']:
user.groups.add(bw_group)
if username == 'user2':
u2 = get_user_model().objects.get(username=username)
u2.groups.add(sd_group)
if username in ['user3', 'user4']:
user.groups.add(sd_group)
if username == 'staff_user':
staffer = get_user_model().objects.get(username=username, is_staff=True,)
staffer.groups.add(bw_group)
staffer.groups.add(sd_group)
if username == 'staffer':
user.is_staff = True
user.first_name = fake.first_name()
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.db import models
from django.urls import reverse
from django.utils import timezone
class TaskList(models.Model):
@ -26,7 +27,7 @@ class TaskList(models.Model):
class Task(models.Model):
title = models.CharField(max_length=140)
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, )
completed = models.BooleanField(default=False)
completed_date = models.DateField(blank=True, null=True)

View file

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

View file

@ -34,9 +34,17 @@
<li class="list-group-item">
<strong>Due date:</strong> {{ task.due_date }}
</li>
<li class="list-group-item">
<strong>Completed:</strong> {{ task.completed|yesno:"Yes,No" }}
</li>
{% if task.completed %}
<li class="list-group-item">
<strong>Completed on:</strong> {{ task.completed_date}}
</li>
{% else %}
<li class="list-group-item">
<strong>Completed:</strong> {{ task.completed|yesno:"Yes,No" }}
</li>
{% endif %}
<li class="list-group-item">
<strong>In list:</strong>
<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.template.loader import render_to_string
from django.views.decorators.csrf import csrf_exempt
from django.utils import timezone
from todo.forms import AddTaskListForm, AddEditTaskForm, AddExternalTaskForm, SearchForm
from todo.models import Task, TaskList, Comment
@ -120,7 +121,7 @@ def list_detail(request, list_id=None, list_slug=None, view_completed=False):
# Which tasks to show on this list view?
if list_slug == "mine":
tasks =Task.objects.filter(assigned_to=request.user)
tasks = Task.objects.filter(assigned_to=request.user)
else:
# Show a specific list, ensuring permissions.
@ -157,10 +158,12 @@ def list_detail(request, list_id=None, list_slug=None, view_completed=False):
})
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
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)
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={
'assigned_to': request.user.id,
'priority': 999,
'task_list': task_list
'task_list': task_list,
})
context = {