Merge pull request #3122 from normanjaeckel/ExampleData

Example data
This commit is contained in:
Norman Jäckel 2017-03-27 23:54:51 +02:00 committed by GitHub
commit 40c6957b21
8 changed files with 251 additions and 3 deletions

View File

@ -36,13 +36,13 @@ class UserManager(BaseUserManager):
'permissions',
queryset=Permission.objects.select_related('content_type')))))
def create_user(self, username, password, **kwargs):
def create_user(self, username, password, skip_autoupdate=False, **kwargs):
"""
Creates a new user only with a password and a username.
"""
user = self.model(username=username, **kwargs)
user.set_password(password)
user.save(using=self._db)
user.save(skip_autoupdate=skip_autoupdate, using=self._db)
return user
def create_or_reset_admin_user(self):

View File

@ -0,0 +1,13 @@
Example Data Generator
======================
This is a plugin to provide a management command to generate example data
for OpenSlides. Add this module to your personal settings.py.
INSTALLED_PLUGINS += (
'tests.example_data_generator',
)
Then run::
$ python manage.py create-example-data

View File

@ -0,0 +1 @@
default_app_config = 'tests.example_data_generator.apps.ExampleDataGeneratorAppConfig'

View File

@ -0,0 +1,8 @@
from django.apps import AppConfig
class ExampleDataGeneratorAppConfig(AppConfig):
name = 'tests.example_data_generator'
label = 'tests.example_data_generator'
verbose_name = 'Example Data Generator'
version = 'no specific version'

View File

@ -0,0 +1,226 @@
from textwrap import dedent
from django.contrib.auth.hashers import make_password
from django.core.management.base import BaseCommand, CommandError
from django.utils.crypto import get_random_string
from openslides.agenda.models import Item
from openslides.assignments.models import Assignment
from openslides.motions.models import Motion
from openslides.topics.models import Topic
from openslides.users.models import Group, User
MOTION_NUMBER_OF_PARAGRAPHS = 4
LOREM_IPSUM = [
"""\
<p>Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod
tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea
commodi consequat. Quis aute iure reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat
cupiditat non proident, sunt in culpa qui officia deserunt mollit anim
id est laborum.</p>
""",
"""\
<p>Sed ut perspiciatis, unde omnis iste natus error sit voluptatem
accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae
ab illo inventore veritatis et quasi architecto beatae vitae dicta
sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit,
aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos,
qui ratione voluptatem sequi nesciunt, neque porro quisquam est, qui
dolorem ipsum, quia dolor sit amet consectetur adipisci[ng] velit, sed
quia non numquam [do] eius modi tempora inci[di]dunt, ut labore et
dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam,
quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut
aliquid ex ea commodi consequatur? Quis autem vel eum iure
reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae
consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla
pariatur?</p>
""",
"""\
<p>At vero eos et accusamus et iusto odio dignissimos ducimus, qui
blanditiis praesentium voluptatum deleniti atque corrupti, quos dolores
et quas molestias excepturi sint, obcaecati cupiditate non provident,
similique sunt in culpa, qui officia deserunt mollitia animi, id est
laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita
distinctio. Nam libero tempore, cum soluta nobis est eligendi optio,
cumque nihil impedit, quo minus id, quod maxime placeat, facere
possimus, omnis voluptas assumenda est, omnis dolor repellendus.
Temporibus autem quibusdam et aut officiis debitis aut rerum
necessitatibus saepe eveniet, ut et voluptates repudiandae sint et
molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente
delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut
perferendis doloribus asperiores repellat</p>
""",
]
DEFAULT_NUMBER = 100
STAFF_USER_USERNAME = 'admin{}'
DEFAULT_USER_USERNAME = 'user{}'
PASSWORD = 'password'
class Command(BaseCommand):
"""
Command to create example data for OpenSlides.
"""
help = 'Create example data for OpenSlides.'
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
def add_arguments(self, parser):
"""
Adds arguments to the command parser. The default values for the apps
are set by DEFAULT_NUMBER.
"""
parser.add_argument(
'--only',
action='store_true',
help='Only the given objects are created i. e. all defaults are '
'set to 0.',
)
parser.add_argument(
'-t', '--topics',
type=int,
help='Number of topics to be created (default {}).'.format(
DEFAULT_NUMBER),
)
parser.add_argument(
'-m', '--motions',
type=int,
help='Number of motions to be created (default {}).'.format(
DEFAULT_NUMBER),
)
parser.add_argument(
'-a', '--assignments',
type=int,
help='Number of assignments to be created (default {}).'.format(
DEFAULT_NUMBER),
)
parser.add_argument(
'-u', '--users',
nargs=2,
type=int,
help='Number of users to be created. The first number of users is '
'added to the group "Staff" (default {}). The second number '
'of users is not added to any group (default {}).'.format(
DEFAULT_NUMBER, DEFAULT_NUMBER),
)
def handle(self, *args, **options):
self.create_topics(options)
self.create_motions(options)
self.create_assignments(options)
self.create_users(options)
def create_topics(self, options):
number_of_topics = options['topics']
if number_of_topics is None and not options['only']:
number_of_topics = DEFAULT_NUMBER
if number_of_topics is not None and number_of_topics > 0:
self.stdout.write('Start creating {} topcis ...'.format(number_of_topics))
current_topics = list(Topic.objects.values_list('id', flat=True))
new_topics = []
for i in range(number_of_topics):
new_topics.append(Topic(title=get_random_string(20, self.chars)))
Topic.objects.bulk_create(new_topics)
items = []
for topic in Topic.objects.exclude(pk__in=current_topics):
items.append(Item(content_object=topic, type=Item.AGENDA_ITEM))
Item.objects.bulk_create(items)
self.stdout.write(self.style.SUCCESS('{} topcis successfully created.'.format(number_of_topics)))
elif number_of_topics is not None and number_of_topics < 0:
raise CommandError('Number for topics must not be negative.')
def create_motions(self, options):
number_of_motions = options['motions']
if number_of_motions is None and not options['only']:
number_of_motions = DEFAULT_NUMBER
if number_of_motions is not None and number_of_motions > 0:
self.stdout.write('Start creating {} motions ... (sorry, this might be slow) ...'.format(number_of_motions))
text = ''
for i in range(MOTION_NUMBER_OF_PARAGRAPHS):
text += dedent(LOREM_IPSUM[i % 3])
for i in range(number_of_motions):
motion = Motion(
title=get_random_string(20, self.chars),
text=text,
)
motion.save(skip_autoupdate=True)
self.stdout.write(self.style.SUCCESS('{} motions successfully created.'.format(number_of_motions)))
elif number_of_motions is not None and number_of_motions < 0:
raise CommandError('Number for motions must not be negative.')
def create_assignments(self, options):
number_of_assignments = options['assignments']
if number_of_assignments is None and not options['only']:
number_of_assignments = DEFAULT_NUMBER
if number_of_assignments is not None and number_of_assignments > 0:
self.stdout.write('Start creating {} assignments ...'.format(number_of_assignments))
current_assignments = list(Assignment.objects.values_list('id', flat=True))
new_assignments = []
for i in range(number_of_assignments):
new_assignments.append(Assignment(title=get_random_string(20, self.chars), open_posts=1))
Assignment.objects.bulk_create(new_assignments)
items = []
for assignment in Assignment.objects.exclude(pk__in=current_assignments):
items.append(Item(content_object=assignment))
Item.objects.bulk_create(items)
self.stdout.write(self.style.SUCCESS('{} assignments successfully created.'.format(number_of_assignments)))
elif number_of_assignments is not None and number_of_assignments < 0:
raise CommandError('Number for assignments must not be negative.')
def create_users(self, options):
self.create_staff_users(options)
self.create_default_users(options)
def create_staff_users(self, options):
if options['users'] is None and not options['only']:
staff_users = DEFAULT_NUMBER
elif options['users'] is None:
staff_users = None
else:
staff_users = options['users'][0]
if staff_users is not None and staff_users > 0:
self.stdout.write('Start creating {} staff users ... (sorry, this might be slow) ...'.format(staff_users))
group_staff = Group.objects.get(name='Staff')
hashed_password = make_password(PASSWORD, '', 'md5')
current_users = list(User.objects.values_list('id', flat=True))
new_users = []
for i in range(staff_users):
new_users.append(User(
username=STAFF_USER_USERNAME.format(i),
default_password=PASSWORD,
password=hashed_password
))
User.objects.bulk_create(new_users)
for user in User.objects.exclude(pk__in=current_users):
user.groups.add(group_staff)
self.stdout.write(self.style.SUCCESS('{} staff users successfully created.'.format(staff_users)))
elif staff_users is not None and staff_users < 0:
raise CommandError('Number for staff users must not be negative.')
def create_default_users(self, options):
if options['users'] is None and not options['only']:
default_users = DEFAULT_NUMBER
elif options['users'] is None:
default_users = None
else:
default_users = options['users'][1]
if default_users is not None and default_users > 0:
self.stdout.write('Start creating {} default users ...'.format(default_users))
hashed_password = make_password(PASSWORD, '', 'md5')
new_users = []
for i in range(default_users):
new_users.append(User(
username=DEFAULT_USER_USERNAME.format(i),
default_password=PASSWORD,
password=hashed_password
))
User.objects.bulk_create(new_users)
self.stdout.write(self.style.SUCCESS('{} default users successfully created.'.format(default_users)))
elif default_users is not None and default_users < 0:
raise CommandError('Number for default users must not be negative.')

View File

@ -18,7 +18,7 @@ class UserManagerTest(TestCase):
user_manager.model.assert_called_once_with(username='test_username', test_kwarg='test_kwarg')
user.set_password.assert_called_once_with('test_password')
user.save.assert_called_once_with(using='my_test_db')
user.save.assert_called_once_with(using='my_test_db', skip_autoupdate=False)
self.assertEqual(
return_user,
user,