From c07c53a958ea0c432e3429aa0cfdc1334a102267 Mon Sep 17 00:00:00 2001 From: Elijah Date: Fri, 15 Dec 2023 14:32:49 +0100 Subject: [PATCH 1/6] Added custom command to create example data --- .../commands/create_example_data.py | 195 ++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 idhub/management/commands/create_example_data.py diff --git a/idhub/management/commands/create_example_data.py b/idhub/management/commands/create_example_data.py new file mode 100644 index 0000000..7b3f45c --- /dev/null +++ b/idhub/management/commands/create_example_data.py @@ -0,0 +1,195 @@ +import random +import string + +from django.core.management.base import BaseCommand +from django.db import IntegrityError +from idhub.models import Event, Rol, Service, UserRol +from idhub_auth.models import User + +DEFAULT_OBJECTS_CREATED = 30 +RANDOM_STRING_LENGTH = 30 +EMAIL_RANDOM_STRING_LENGTH = 10 + + +class Command(BaseCommand): + help = """ + Populate the database with dummy values. + You can either specify which model to create objects for, + or create objects for all models. + If no data is specified it will create 30 events, users, + services, roles, and user roles + + usage: create_example_data [-h] [--option args] + options: + --amount N Create N objects (includes events, users, services, + roles, and user roles) + --events N Create N events + --users N Create N users + --superusers N Create N superusers + --services N Create N services + --roles N Create N roles + --userroles N Create N user roles + --userrole u s Create a user role for user u and service s + """ + created_users = [] + created_roles = [] + created_services = [] + + def handle(self, *args, **options): + any_option_used = False + + if options["events"]: + self.create_events(options["events"]) + any_option_used = True + if options["users"]: + self.create_users(options["users"]) + any_option_used = True + if options["superusers"]: + self.create_superusers(options["superusers"]) + any_option_used = True + if options["services"]: + self.create_services(options["services"]) + any_option_used = True + if options["roles"]: + self.create_roles(options["roles"]) + any_option_used = True + if options["userroles"]: + self.create_user_roles(options["userroles"]) + any_option_used = True + if options["userrole"]: + user = options["userrole"][0] + service = options["userrole"][1] + self.create_user_roles(1, user, service) + any_option_used = True + + if options["amount"]: + self.create_all(options["amount"]) + any_option_used = True + + if not any_option_used: + self.create_all() + + def add_arguments(self, parser): + parser.add_argument("--amount", type=int, action='store') + parser.add_argument("--events", type=int) + parser.add_argument("--users", type=int) + parser.add_argument("--superusers", type=int) + parser.add_argument("--services", type=int) + parser.add_argument("--roles", type=int) + parser.add_argument("--userroles", type=int) + parser.add_argument("--userrole", nargs=2, type=str) + + def create_all(self, amount=DEFAULT_OBJECTS_CREATED): + self.create_events(amount) + self.create_users(amount) + self.create_roles(amount) + self.create_services(amount) + self.create_user_roles(amount) + + def create_events(self, amount, user=None): + created_event_amount = 0 + for value in range(0, amount): + try: + Event.objects.create( + type=random.randint(1, 30), + message=create_random_string(), + user=user + ) + created_event_amount += 1 + except IntegrityError: + self.stdout.write("Couldn't create event") + self.stdout.write(f"Created {created_event_amount} events") + + def create_users(self, amount): + created_user_amount = 0 + for value in range(0, amount): + email = create_random_string(EMAIL_RANDOM_STRING_LENGTH) + "@example.org" + try: + User.objects.create( + email=email, + # Could be improved, maybe using Faker + first_name=create_random_string(random.randint(5, 10)), + last_name=create_random_string(random.randint(5, 10)) + ) + self.created_users.append(email) + created_user_amount += 1 + except IntegrityError: + self.stdout.write("Couldn't create user " + email) + + self.stdout.write(f"Created {created_user_amount} users") + + def create_superusers(self, amount=0): + """Superusers can only be created from the specific command""" + created_superuser_amount = 0 + for value in range(0, amount): + email = create_random_string(EMAIL_RANDOM_STRING_LENGTH) + try: + User.objects.create_superuser(email) + created_superuser_amount += 1 + except IntegrityError: + self.stdout.write("Couldn't create superuser " + email) + self.stdout.write(f"Created {created_superuser_amount} users") + + def create_services(self, amount): + created_service_amount = 0 + for value in range(0, amount): + domain = create_random_string(random.randint(5, 15)) + try: + service = Service.objects.create( + domain=domain, + description=create_random_string( + random.randint(50, 100)) + ) + self.created_services.append(domain) + try: + associated_rol = Rol.objects.get(name=random.choice( + self.created_roles)) + service.rol.add(associated_rol.id) + except IntegrityError: + self.stdout.write( + f"Couldn't associate role with service {domain}") + created_service_amount += 1 + except IntegrityError: + self.stdout.write("Couldn't create service " + domain) + self.stdout.write(f"Created {created_service_amount} services") + + def create_roles(self, amount): + created_role_amount = 0 + for value in range(0, amount): + # Could be improved, maybe using Faker + name = create_random_string(random.randint(5, 10)) + try: + Rol.objects.create(name=name, + description=create_random_string( + random.randint(50, 100))) + created_role_amount += 1 + except IntegrityError: + self.stdout.write("Couldn't create role " + name) + self.created_roles.append(name) + self.stdout.write(f"Created {created_role_amount} roles") + + def create_user_roles(self, amount, user_id=None, service_id=None): + created_user_role_amount = 0 + user_id = user_id if user_id is not None else random.choice( + self.created_users) + service_id = service_id if service_id is not None else random.choice( + self.created_services) + for value in range(0, amount): + try: + user = User.objects.get(email=user_id) + service = Service.objects.get(domain=service_id) + UserRol.objects.create( + user=user, + service=service + ) + created_user_role_amount += 1 + except IntegrityError: + self.stdout.write("Couldn't create user role for user " + user.email) + user_id = random.choice(self.created_users) + service_id = random.choice(self.created_services) + self.stdout.write(f"Created {created_user_role_amount} user roles") + + +def create_random_string(string_length=RANDOM_STRING_LENGTH): + return ''.join(random.choices(string.ascii_uppercase + string.digits, + k=string_length)) From 592b0fd98030ae842c4da842a7ef874ef67ead93 Mon Sep 17 00:00:00 2001 From: Elijah Date: Fri, 15 Dec 2023 14:45:34 +0100 Subject: [PATCH 2/6] Fixed help tooltip to reflect the appropriate information --- .../commands/create_example_data.py | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/idhub/management/commands/create_example_data.py b/idhub/management/commands/create_example_data.py index 7b3f45c..62a04a3 100644 --- a/idhub/management/commands/create_example_data.py +++ b/idhub/management/commands/create_example_data.py @@ -12,25 +12,15 @@ EMAIL_RANDOM_STRING_LENGTH = 10 class Command(BaseCommand): - help = """ + """ Populate the database with dummy values. You can either specify which model to create objects for, or create objects for all models. If no data is specified it will create 30 events, users, - services, roles, and user roles - - usage: create_example_data [-h] [--option args] - options: - --amount N Create N objects (includes events, users, services, - roles, and user roles) - --events N Create N events - --users N Create N users - --superusers N Create N superusers - --services N Create N services - --roles N Create N roles - --userroles N Create N user roles - --userrole u s Create a user role for user u and service s + services, roles, and user roles. """ + + help = 'Populate the database with dummy values for testing.' created_users = [] created_roles = [] created_services = [] @@ -70,14 +60,27 @@ class Command(BaseCommand): self.create_all() def add_arguments(self, parser): - parser.add_argument("--amount", type=int, action='store') - parser.add_argument("--events", type=int) - parser.add_argument("--users", type=int) - parser.add_argument("--superusers", type=int) - parser.add_argument("--services", type=int) - parser.add_argument("--roles", type=int) - parser.add_argument("--userroles", type=int) - parser.add_argument("--userrole", nargs=2, type=str) + parser.add_argument( + '--amount', type=int, action='store', + help='Create N objects (includes events, users, services, roles, and user roles)' + ) + parser.add_argument('--events', type=int, + help='Create the specified number of events') + parser.add_argument('--users', type=int, + help='Create the specified number of users') + parser.add_argument('--superusers', type=int, + help='Create the specified number of superusers') + parser.add_argument('--services', type=int, + help='Create the specified number of services') + parser.add_argument('--roles', type=int, + help='Create the specified number of roles') + parser.add_argument('--userroles', type=int, + help='Create the specified number of user roles') + parser.add_argument( + '--userrole', nargs=2, type=str, + help='Create a user role for user U and service S', + metavar=('U', 'S'), + ) def create_all(self, amount=DEFAULT_OBJECTS_CREATED): self.create_events(amount) From 7a5d42f5860a1cd67a4c504382848728591fdded Mon Sep 17 00:00:00 2001 From: Elijah Date: Fri, 15 Dec 2023 17:33:35 +0100 Subject: [PATCH 3/6] Added commands to create custom user and superuser --- .../commands/create_example_data.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/idhub/management/commands/create_example_data.py b/idhub/management/commands/create_example_data.py index 62a04a3..54c8385 100644 --- a/idhub/management/commands/create_example_data.py +++ b/idhub/management/commands/create_example_data.py @@ -51,6 +51,14 @@ class Command(BaseCommand): service = options["userrole"][1] self.create_user_roles(1, user, service) any_option_used = True + if options["register"]: + email = options["register"][0] + password = options["register"][1] + self.create_user(email, password) + if options["register_superuser"]: + email = options["register_superuser"][0] + password = options["register_superuser"][1] + self.create_superuser(email, password) if options["amount"]: self.create_all(options["amount"]) @@ -81,6 +89,12 @@ class Command(BaseCommand): help='Create a user role for user U and service S', metavar=('U', 'S'), ) + parser.add_argument('--register', nargs=2, type=str, + help='Create a user with email E and password P', + metavar=('E', 'P')) + parser.add_argument('--register-superuser', nargs=2, type=str, + help='Create a superuser with email E and password P', + metavar=('E', 'P')) def create_all(self, amount=DEFAULT_OBJECTS_CREATED): self.create_events(amount) @@ -192,6 +206,12 @@ class Command(BaseCommand): service_id = random.choice(self.created_services) self.stdout.write(f"Created {created_user_role_amount} user roles") + def create_user(self, email, password): + User.objects.create_user(email, password) + + def create_superuser(self, email, password): + User.objects.create_superuser(email, password) + def create_random_string(string_length=RANDOM_STRING_LENGTH): return ''.join(random.choices(string.ascii_uppercase + string.digits, From b72129d627ad513773b946745503ddcf8f3937de Mon Sep 17 00:00:00 2001 From: Elijah Date: Fri, 15 Dec 2023 17:53:46 +0100 Subject: [PATCH 4/6] Added Faker to create_example_data to generate more realistic objects --- .../commands/create_example_data.py | 33 ++++++++----------- requirements.txt | 1 + 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/idhub/management/commands/create_example_data.py b/idhub/management/commands/create_example_data.py index 54c8385..89aa408 100644 --- a/idhub/management/commands/create_example_data.py +++ b/idhub/management/commands/create_example_data.py @@ -1,15 +1,18 @@ import random -import string from django.core.management.base import BaseCommand from django.db import IntegrityError from idhub.models import Event, Rol, Service, UserRol from idhub_auth.models import User +from faker import Faker + DEFAULT_OBJECTS_CREATED = 30 RANDOM_STRING_LENGTH = 30 EMAIL_RANDOM_STRING_LENGTH = 10 +fake = Faker() + class Command(BaseCommand): """ @@ -109,7 +112,7 @@ class Command(BaseCommand): try: Event.objects.create( type=random.randint(1, 30), - message=create_random_string(), + message=fake.paragraph(nb_sentences=3), user=user ) created_event_amount += 1 @@ -120,13 +123,12 @@ class Command(BaseCommand): def create_users(self, amount): created_user_amount = 0 for value in range(0, amount): - email = create_random_string(EMAIL_RANDOM_STRING_LENGTH) + "@example.org" + email = fake.email() try: User.objects.create( email=email, - # Could be improved, maybe using Faker - first_name=create_random_string(random.randint(5, 10)), - last_name=create_random_string(random.randint(5, 10)) + first_name=fake.first_name(), + last_name=fake.last_name() ) self.created_users.append(email) created_user_amount += 1 @@ -139,7 +141,7 @@ class Command(BaseCommand): """Superusers can only be created from the specific command""" created_superuser_amount = 0 for value in range(0, amount): - email = create_random_string(EMAIL_RANDOM_STRING_LENGTH) + email = fake.email() try: User.objects.create_superuser(email) created_superuser_amount += 1 @@ -150,12 +152,11 @@ class Command(BaseCommand): def create_services(self, amount): created_service_amount = 0 for value in range(0, amount): - domain = create_random_string(random.randint(5, 15)) + domain = fake.text(max_nb_chars=200) try: service = Service.objects.create( domain=domain, - description=create_random_string( - random.randint(50, 100)) + description=fake.text(max_nb_chars=250) ) self.created_services.append(domain) try: @@ -173,12 +174,11 @@ class Command(BaseCommand): def create_roles(self, amount): created_role_amount = 0 for value in range(0, amount): - # Could be improved, maybe using Faker - name = create_random_string(random.randint(5, 10)) + name = fake.job() try: Rol.objects.create(name=name, - description=create_random_string( - random.randint(50, 100))) + description=fake.text(max_nb_chars=250) + ) created_role_amount += 1 except IntegrityError: self.stdout.write("Couldn't create role " + name) @@ -211,8 +211,3 @@ class Command(BaseCommand): def create_superuser(self, email, password): User.objects.create_superuser(email, password) - - -def create_random_string(string_length=RANDOM_STRING_LENGTH): - return ''.join(random.choices(string.ascii_uppercase + string.digits, - k=string_length)) diff --git a/requirements.txt b/requirements.txt index 9b19238..ae069eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,3 +13,4 @@ jsonref==1.1.0 pyld==2.0.3 more-itertools==10.1.0 dj-database-url==2.1.0 +faker==21.0.0 From 3a7f0a43c5987d911ef62f21a42e29e4a7cdfe6f Mon Sep 17 00:00:00 2001 From: Elijah Date: Fri, 22 Dec 2023 11:13:35 +0100 Subject: [PATCH 5/6] Fixed control flow bug that creates instances of all models after creating a user or superuser --- idhub/management/commands/create_example_data.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/idhub/management/commands/create_example_data.py b/idhub/management/commands/create_example_data.py index 89aa408..4c8b14f 100644 --- a/idhub/management/commands/create_example_data.py +++ b/idhub/management/commands/create_example_data.py @@ -58,10 +58,12 @@ class Command(BaseCommand): email = options["register"][0] password = options["register"][1] self.create_user(email, password) + any_option_used = True if options["register_superuser"]: email = options["register_superuser"][0] password = options["register_superuser"][1] self.create_superuser(email, password) + any_option_used = True if options["amount"]: self.create_all(options["amount"]) From d450819cd3786788591710d0397ab3fdf67ec06e Mon Sep 17 00:00:00 2001 From: Elijah Date: Wed, 27 Dec 2023 14:32:26 +0100 Subject: [PATCH 6/6] Bug fixes and refactored code for better reusability and extensibility --- .../commands/create_example_data.py | 342 +++++++++++------- 1 file changed, 210 insertions(+), 132 deletions(-) diff --git a/idhub/management/commands/create_example_data.py b/idhub/management/commands/create_example_data.py index 4c8b14f..4ee24bb 100644 --- a/idhub/management/commands/create_example_data.py +++ b/idhub/management/commands/create_example_data.py @@ -1,15 +1,18 @@ import random +from typing import Type, Callable, List from django.core.management.base import BaseCommand -from django.db import IntegrityError +from django.db import models, IntegrityError + from idhub.models import Event, Rol, Service, UserRol from idhub_auth.models import User from faker import Faker -DEFAULT_OBJECTS_CREATED = 30 -RANDOM_STRING_LENGTH = 30 -EMAIL_RANDOM_STRING_LENGTH = 10 +DEFAULT_OBJECTS_CREATED: int = 30 +RANDOM_STRING_LENGTH: int = 30 +EMAIL_RANDOM_STRING_LENGTH: int = 10 +EXISTING_EVENTS: int = 30 fake = Faker() @@ -24,54 +27,68 @@ class Command(BaseCommand): """ help = 'Populate the database with dummy values for testing.' - created_users = [] - created_roles = [] - created_services = [] + + def __init__(self, *args, **kwargs): + """ + In the context of a Django management command, + initializing lists like created_users in the constructor ensures + that each run of the command has its own set of users, services, + roles, etc., and does not unintentionally share or retain state + across different invocations of the command. + """ + super().__init__(*args, **kwargs) + self.created_users = [] + self.created_services = [] + self.created_roles = [] def handle(self, *args, **options): - any_option_used = False - - if options["events"]: - self.create_events(options["events"]) - any_option_used = True - if options["users"]: - self.create_users(options["users"]) - any_option_used = True - if options["superusers"]: - self.create_superusers(options["superusers"]) - any_option_used = True - if options["services"]: - self.create_services(options["services"]) - any_option_used = True - if options["roles"]: - self.create_roles(options["roles"]) - any_option_used = True - if options["userroles"]: - self.create_user_roles(options["userroles"]) - any_option_used = True - if options["userrole"]: - user = options["userrole"][0] - service = options["userrole"][1] - self.create_user_roles(1, user, service) - any_option_used = True - if options["register"]: - email = options["register"][0] - password = options["register"][1] - self.create_user(email, password) - any_option_used = True - if options["register_superuser"]: - email = options["register_superuser"][0] - password = options["register_superuser"][1] - self.create_superuser(email, password) - any_option_used = True - - if options["amount"]: - self.create_all(options["amount"]) - any_option_used = True + any_option_used = self.process_options(options) if not any_option_used: self.create_all() + def process_options(self, input_options): + option_methods = { + 'events': self.create_events, + 'users': self.create_users, + 'superusers': self.create_superusers, + 'services': self.create_services, + 'roles': self.create_roles, + 'userroles': self.create_user_roles, + 'userrole': self.create_specific_user_role, + 'register': self.register_user, + 'register_superuser': self.register_superuser, + 'amount': self.create_all + } + + any_option_used = self.match_input_to_options(input_options, + option_methods) + + return any_option_used + + def match_input_to_options(self, input_options, option_methods): + any_option_used = False + + for option, method in option_methods.items(): + is_valid_option = option in input_options and input_options[ + option] is not None + if is_valid_option: + self.call_selected_method(input_options, method, option) + any_option_used = True + + return any_option_used + + def call_selected_method(self, input_options, method, option): + args = self.create_argument_list(input_options, option) + method(*args) + + def create_argument_list(self, input_options, option): + if isinstance(input_options[option], list): + args = input_options[option] + else: + args = [input_options[option]] + return args + def add_arguments(self, parser): parser.add_argument( '--amount', type=int, action='store', @@ -95,11 +112,32 @@ class Command(BaseCommand): metavar=('U', 'S'), ) parser.add_argument('--register', nargs=2, type=str, - help='Create a user with email E and password P', - metavar=('E', 'P')) + help='Create a user with email EMAIL and password PW', + metavar=('EMAIL', 'PW')) parser.add_argument('--register-superuser', nargs=2, type=str, - help='Create a superuser with email E and password P', - metavar=('E', 'P')) + help='Create a superuser with email EMAIL and ' + 'password PW', + metavar=('EMAIL', 'PW')) + + def register_user(self, email: str, password: str): + """ + Register a new user with the given email and password from the command line. + """ + try: + self.create_user(email, password) + self.stdout.write(f"Successfully registered user: {email}") + except IntegrityError: + self.stdout.write(f"Failed to register user: {email}") + + def register_superuser(self, email: str, password: str): + """ + Register a new superuser with the given email and password from the command line. + """ + try: + self.create_superuser(email, password) + self.stdout.write(f"Successfully registered superuser: {email}") + except IntegrityError: + self.stdout.write(f"Failed to register superuser: {email}") def create_all(self, amount=DEFAULT_OBJECTS_CREATED): self.create_events(amount) @@ -108,36 +146,49 @@ class Command(BaseCommand): self.create_services(amount) self.create_user_roles(amount) - def create_events(self, amount, user=None): - created_event_amount = 0 - for value in range(0, amount): - try: - Event.objects.create( - type=random.randint(1, 30), - message=fake.paragraph(nb_sentences=3), - user=user - ) - created_event_amount += 1 - except IntegrityError: - self.stdout.write("Couldn't create event") - self.stdout.write(f"Created {created_event_amount} events") + def create_objects(self, model: Type[models.Model], + data_generator: Callable, amount: int) -> List[ + models.Model]: + """ + Generic method to create objects for a given model and keep track of them. - def create_users(self, amount): - created_user_amount = 0 - for value in range(0, amount): - email = fake.email() - try: - User.objects.create( - email=email, - first_name=fake.first_name(), - last_name=fake.last_name() - ) - self.created_users.append(email) - created_user_amount += 1 - except IntegrityError: - self.stdout.write("Couldn't create user " + email) + Args: + model: The Django model class for which objects are to be created. + data_generator: A function that returns a dictionary of attributes for creating a model instance. + amount: The number of objects to create. - self.stdout.write(f"Created {created_user_amount} users") + Returns: + A list of successfully created model instances. + """ + created_objects = [] + for _ in range(amount): + try: + model_instance = self.create_from_data(data_generator, model) + created_objects.append(model_instance) + except IntegrityError: + self.print_failure_message(model) + + self.print_amount_created(created_objects, model) + return created_objects + + def create_users(self, amount: int): + def user_data(): + return { + 'email': fake.email(), + 'first_name': fake.first_name(), + 'last_name': fake.last_name() + } + created_users = self.create_objects(User, user_data, amount) + self.created_users.extend(created_users) + + def create_events(self, amount: int, user=None): + def event_data(): + return { + 'type': random.randint(1, EXISTING_EVENTS), + 'message': fake.paragraph(nb_sentences=3), + 'user': user + } + self.create_objects(Event, event_data, amount) def create_superusers(self, amount=0): """Superusers can only be created from the specific command""" @@ -151,65 +202,92 @@ class Command(BaseCommand): self.stdout.write("Couldn't create superuser " + email) self.stdout.write(f"Created {created_superuser_amount} users") - def create_services(self, amount): - created_service_amount = 0 - for value in range(0, amount): + def create_services(self, amount: int): + def service_data(): domain = fake.text(max_nb_chars=200) - try: - service = Service.objects.create( - domain=domain, - description=fake.text(max_nb_chars=250) - ) - self.created_services.append(domain) - try: - associated_rol = Rol.objects.get(name=random.choice( - self.created_roles)) - service.rol.add(associated_rol.id) - except IntegrityError: - self.stdout.write( - f"Couldn't associate role with service {domain}") - created_service_amount += 1 - except IntegrityError: - self.stdout.write("Couldn't create service " + domain) - self.stdout.write(f"Created {created_service_amount} services") + description = fake.text(max_nb_chars=250) + return { + 'domain': domain, + 'description': description, + } - def create_roles(self, amount): - created_role_amount = 0 - for value in range(0, amount): + created_services = self.create_objects(Service, service_data, amount) + self.associate_random_roles(created_services) + self.created_services.extend(created_services) + + def create_roles(self, amount: int): + def role_data(): name = fake.job() - try: - Rol.objects.create(name=name, - description=fake.text(max_nb_chars=250) - ) - created_role_amount += 1 - except IntegrityError: - self.stdout.write("Couldn't create role " + name) - self.created_roles.append(name) - self.stdout.write(f"Created {created_role_amount} roles") + description = fake.text(max_nb_chars=250) + return {'name': name, 'description': description} - def create_user_roles(self, amount, user_id=None, service_id=None): - created_user_role_amount = 0 - user_id = user_id if user_id is not None else random.choice( - self.created_users) - service_id = service_id if service_id is not None else random.choice( - self.created_services) - for value in range(0, amount): - try: - user = User.objects.get(email=user_id) - service = Service.objects.get(domain=service_id) - UserRol.objects.create( - user=user, - service=service - ) - created_user_role_amount += 1 - except IntegrityError: - self.stdout.write("Couldn't create user role for user " + user.email) - user_id = random.choice(self.created_users) - service_id = random.choice(self.created_services) - self.stdout.write(f"Created {created_user_role_amount} user roles") + created_roles = self.create_objects(Rol, role_data, amount) + self.created_roles.extend(created_roles) - def create_user(self, email, password): + def create_user_roles(self, amount: int, user_id=None, service_id=None): + def user_role_data(): + user = self.get_or_create_user(user_id) + service = self.get_or_create_service(service_id) + return {"user": user, "service": service} + + self.create_objects(UserRol, user_role_data, amount) + + def create_specific_user_role(self, user, service): + self.create_user_roles(1, user, service) + + def create_user(self, email: str, password: str): User.objects.create_user(email, password) - def create_superuser(self, email, password): + def create_superuser(self, email: str, password: str): User.objects.create_superuser(email, password) + + def print_failure_message(self, model): + self.stdout.write(f"Couldn't create {model.__name__} object.") + + def print_amount_created(self, created_objects, model): + self.stdout.write(f"Created {len(created_objects)} " + f"{model.__name__} objects") + + def create_from_data(self, data_generator, model): + model_instance = model.objects.create(**data_generator()) + return model_instance + + def associate_random_roles(self, created_services): + for service in created_services: + self.associate_service_to_random_roles(service) + + def associate_service_to_random_roles(self, service): + associated_roles = [self.get_or_create_role() for _ in range( + random.randint(0, 2))] + service.rol.set(associated_roles) + + def get_or_create_user(self, user_id): + if user_id is not None: + user = User.objects.get(user_id=user_id) + elif len(self.created_users) != 0: + user = random.choice(self.created_users) + else: + self.create_users(1) + user = self.created_users[0] + + return user + + def get_or_create_service(self, service_id): + if service_id is not None: + service = Service.objects.get(service_id=service_id) + elif len(self.created_services) != 0: + service = random.choice(self.created_services) + else: + self.create_services(1) + service = self.created_services[0] + + return service + + def get_or_create_role(self): + if len(self.created_roles) != 0: + role = random.choice(self.created_roles) + else: + self.create_roles(1) + role = self.created_roles[0] + + return role \ No newline at end of file