Coverage for website/utils/management/commands/createfixtures.py: 0.00%
504 statements
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
1"""Provides the command to generate fixtures."""
3import math
4import random
5import string
6from datetime import date, datetime, timedelta
7from decimal import Decimal
8from secrets import token_hex
10from django.contrib.auth import get_user_model
11from django.core.files.uploadedfile import SimpleUploadedFile
12from django.core.management.base import BaseCommand, CommandError
13from django.db.utils import IntegrityError
14from django.utils import timezone
15from django.utils.text import slugify
17import factory
18from faker import Faker
19from pydenticon import Generator as IconGenerator
21from activemembers.models import (
22 Board,
23 Committee,
24 MemberGroup,
25 MemberGroupMembership,
26 Society,
27)
28from documents.models import Document
29from education.models import Category, Course, Exam, Summary
30from events.models import (
31 EVENT_CATEGORIES,
32 Event,
33 EventRegistration,
34 registration_member_choices_limit,
35)
36from members.models import Member, Membership, Profile
37from newsletters.models import Newsletter, NewsletterEvent, NewsletterItem
38from partners.models import Partner, Vacancy, VacancyCategory
39from payments.models import Payment
40from payments.services import create_payment
41from photos.models import Album, Photo
42from pizzas.models import Product
43from utils.snippets import datetime_to_lectureyear
45_faker = Faker(["en_US"])
46_local_faker = Faker(["nl_NL"])
47_pizza_name_faker = Faker("it_IT")
48_current_tz = timezone.get_current_timezone()
51def _generate_title():
52 words = _faker.words(random.randint(2, 4))
53 return " ".join([word.capitalize() for word in words])
56def maintain_integrity(func):
57 def wrapper(*args, **kwargs):
58 try_amnt = 0
59 while True:
60 try:
61 return func(*args, **kwargs)
62 except IntegrityError as e:
63 try_amnt += 1
64 if try_amnt > 10:
65 raise CommandError("Unable to create an object") from e
67 return wrapper
70class _ProfileFactory(factory.Factory):
71 class Meta:
72 model = Profile
74 programme = random.choice(["computingscience", "informationscience"])
75 student_number = factory.LazyAttribute(lambda x: _faker.numerify(text="s#######"))
76 starting_year = factory.LazyAttribute(
77 lambda x: random.randint(1990, date.today().year)
78 )
80 address_street = factory.LazyAttribute(lambda x: _local_faker.street_address())
81 address_postal_code = factory.LazyAttribute(lambda x: _faker.postcode())
82 address_city = factory.LazyAttribute(lambda x: _faker.city())
83 address_country = random.choice(["NL", "DE", "BE"])
85 phone_number = f"+31{_faker.numerify(text='##########')}"
88def get_event_to_register_for(member):
89 for event in Event.objects.filter(published=True).order_by("?"):
90 if event.registration_required and not event.reached_participants_limit():
91 if member.id not in event.registrations.values_list("member", flat=True):
92 return event
93 return None
96class Command(BaseCommand):
97 """Command to create fake data to populate the site."""
99 help = "Creates fake data to test the site with"
101 def add_arguments(self, parser):
102 """Add arguments to the argument parser.
104 :param parser: the argument parser
105 """
106 parser.add_argument(
107 "-a",
108 "--all",
109 action="store_true",
110 help="Fully populate a database with fixtures",
111 )
112 parser.add_argument(
113 "-b", "--board", type=int, help="The amount of fake boards to add"
114 )
115 parser.add_argument(
116 "-c", "--committee", type=int, help="The amount of fake committees to add"
117 )
118 parser.add_argument(
119 "-d",
120 "--document",
121 type=int,
122 help="The amount of fake miscellaneous documents to add",
123 )
124 parser.add_argument(
125 "-e", "--event", type=int, help="The amount of fake events to add"
126 )
127 parser.add_argument(
128 "-n", "--newsletter", type=int, help="The amount of fake newsletters to add"
129 )
130 parser.add_argument(
131 "-p", "--partner", type=int, help="The amount of fake partners to add"
132 )
133 parser.add_argument(
134 "-i", "--pizza", type=int, help="The amount of fake pizzas to add"
135 )
136 parser.add_argument(
137 "-s", "--society", type=int, help="The amount of fake societies to add"
138 )
139 parser.add_argument(
140 "-u", "--user", type=int, help="The amount of fake users to add"
141 )
142 parser.add_argument(
143 "-w", "--vacancy", type=int, help="The amount of fake vacancies to add"
144 )
145 parser.add_argument("--course", type=int, help="The amount of courses to add")
146 parser.add_argument(
147 "-r",
148 "--registration",
149 type=int,
150 help="The amount of event registrations to add",
151 )
152 parser.add_argument("--payment", type=int, help="The amount of payments to add")
153 parser.add_argument(
154 "--photoalbum", type=int, help="The amount of photo albums to add"
155 )
157 def create_board(self, lecture_year):
158 """Create a new board.
160 :param int lecture_year: the lecture year this board was active
161 """
162 self.stdout.write("Creating a board")
163 members = Member.objects.all()
164 if len(members) < 6:
165 self.stdout.write("Your database does not contain 6 users.")
166 self.stdout.write(f"Creating {6 - len(members)} more users.")
167 for __ in range(6 - len(members)):
168 self.create_user()
170 board = Board()
172 board.name = f"Board {lecture_year}-{lecture_year+1}"
173 while Board.objects.filter(name=board.name).exists():
174 lecture_year = lecture_year - 1
175 board.name = f"Board {lecture_year}-{lecture_year+1}"
177 board.description = _faker.paragraph()
179 igen = IconGenerator(5, 5) # 5x5 blocks
180 icon = igen.generate(
181 board.name, 480, 480, padding=(10, 10, 10, 10), output_format="jpeg"
182 ) # 620x620 pixels, with 10 pixels padding on each side
183 board.photo = SimpleUploadedFile(f"{board.name}.jpg", icon, "image/jpeg")
185 board.since = date(year=lecture_year, month=9, day=1)
186 board.until = date(year=lecture_year + 1, month=8, day=31)
187 board.active = True
188 board.contact_email = _faker.safe_email()
190 board.full_clean()
191 board.save()
193 # Add members
194 board_members = random.sample(list(members), random.randint(5, 6))
195 for member in board_members:
196 self.create_member_group_membership(member, board)
198 # Make one member the chair
199 chair = random.choice(board.membergroupmembership_set.all())
200 chair.until = None
201 chair.chair = True
203 chair.full_clean()
204 chair.save()
206 @maintain_integrity
207 def create_member_group(self, group_model):
208 """Create a MemberGroup."""
209 self.stdout.write("Creating a membergroup")
210 members = Member.objects.all()
211 if len(members) < 6:
212 self.stdout.write("Your database does not contain 6 users.")
213 self.stdout.write(f"Creating {6 - len(members)} more users.")
214 for __ in range(6 - len(members)):
215 self.create_user()
216 members = Member.objects.all()
218 member_group = group_model()
220 member_group.name = _generate_title()
221 member_group.description = _faker.paragraph()
223 igen = IconGenerator(5, 5) # 5x5 blocks
224 icon = igen.generate(
225 member_group.name,
226 480,
227 480,
228 padding=(10, 10, 10, 10),
229 output_format="jpeg",
230 ) # 620x620 pixels, with 10 pixels padding on each side
231 member_group.photo = SimpleUploadedFile(
232 member_group.name + ".jpg", icon, "image/jpeg"
233 )
235 member_group.since = _faker.date_time_between("-10y", "+30d").date()
237 if random.random() < 0.1:
238 month = timedelta(days=30)
239 member_group.until = _faker.date_time_between_dates(
240 member_group.since + 12 * month, member_group.since + 60 * month
241 ).date()
243 member_group.active = random.random() < 0.9
244 member_group.contact_email = _faker.safe_email()
246 member_group.full_clean()
247 member_group.save()
249 # Add members
250 committee_members = random.sample(list(members), random.randint(2, 6))
251 for member in committee_members:
252 self.create_member_group_membership(member, member_group)
254 # Make one member the chair
255 chair = random.choice(member_group.membergroupmembership_set.all())
256 chair.until = None
257 chair.chair = True
259 chair.full_clean()
260 chair.save()
262 def create_member_group_membership(self, member, group):
263 """Create member group membership.
265 :param member: the member to add to the committee
266 :param group: the group to add the member to
267 """
268 self.stdout.write("Creating a group membership")
269 membership = MemberGroupMembership()
271 membership.member = member
272 membership.group = group
274 today = date.today()
275 membership.since = _faker.date_time_between_dates(
276 group.since,
277 group.until - timedelta(days=3)
278 if group.until
279 else group.since + timedelta(days=365),
280 ).date()
282 if random.random() < 0.2 and membership.since < today:
283 membership.until = _faker.date_time_between_dates(
284 membership.since,
285 group.until if group.until else group.since + timedelta(days=2 * 365),
286 ).date()
288 membership.full_clean()
289 membership.save()
291 @maintain_integrity
292 def create_event(self):
293 """Create an event."""
294 self.stdout.write("Creating an event")
295 groups = MemberGroup.objects.all()
296 if len(groups) == 0:
297 self.stdout.write("Your database does not contain any member groups.")
298 self.stdout.write("Creating a committee.")
299 self.create_member_group(Committee)
300 groups = MemberGroup.objects.all()
301 event = Event()
303 event.description = _faker.paragraph()
304 event.caption = _faker.sentence()
305 event.title = _generate_title()
306 event.start = _faker.date_time_between("-30d", "+120d", _current_tz)
307 duration = math.ceil(random.expovariate(0.2))
308 event.end = event.start + timedelta(hours=duration)
309 event.save()
310 event.organisers.add(*random.sample(list(groups), random.randint(1, 3)))
311 event.category = random.choice(EVENT_CATEGORIES)[0]
312 event.fine = 5
313 event.slug = slugify(event.title) + "-" + str(event.start.year)
315 if random.random() < 0.5:
316 week = timedelta(days=7)
317 event.registration_start = _faker.date_time_between_dates(
318 datetime_start=event.start - 4 * week,
319 datetime_end=event.start - week,
320 tzinfo=_current_tz,
321 )
322 event.registration_end = _faker.date_time_between_dates(
323 datetime_start=event.registration_start,
324 datetime_end=event.start,
325 tzinfo=_current_tz,
326 )
327 event.cancel_deadline = _faker.date_time_between_dates(
328 datetime_start=event.registration_end,
329 datetime_end=event.start,
330 tzinfo=_current_tz,
331 )
332 event.optional_registrations = False
334 event.location = _local_faker.street_address()
335 event.map_location = event.location
336 event.send_cancel_email = False
338 if random.random() < 0.5:
339 event.price = Decimal(random.randint(100, 2500)) / Decimal(100)
340 event.fine = max(
341 5.0,
342 Decimal(
343 random.randint(round(100 * event.price), round(500 * event.price))
344 )
345 / Decimal(100),
346 )
348 if random.random() < 0.5:
349 event.max_participants = random.randint(20, 200)
351 event.published = random.random() < 0.9
353 event.full_clean()
354 event.save()
356 @maintain_integrity
357 def create_partner(self, type="normal"):
358 """Create a new random partner."""
359 self.stdout.write("Creating a partner")
360 partner = Partner()
362 partner.name = f"{_faker.company()} {_faker.company_suffix()}"
363 partner.slug = _faker.slug()
364 partner.link = _faker.uri()
365 partner.company_profile = _faker.paragraph(nb_sentences=10)
366 igen = IconGenerator(5, 5) # 5x5 blocks
367 icon = igen.generate(
368 partner.name,
369 480,
370 480,
371 padding=(10, 10, 10, 10),
372 output_format="jpeg",
373 ) # 620x620 pixels, with 10 pixels padding on each side
374 partner.logo = SimpleUploadedFile(partner.name + ".jpg", icon, "image/jpeg")
376 partner.address = _local_faker.street_name() + " " + str(random.randint(1, 300))
377 partner.zip_code = _local_faker.postcode()
378 partner.city = _local_faker.city()
379 partner.country = random.choice(["NL", "DE", "BE", "GB"])
381 match type:
382 case "normal":
383 pass
384 case "main":
385 partner.is_main_partner = True
386 case "local":
387 partner.is_local_partner = True
388 case "inactive":
389 partner.is_active = False
391 partner.full_clean()
392 partner.save()
394 def create_pizza(self):
395 """Create a new random pizza product."""
396 self.stdout.write("Creating a pizza product")
398 product = Product()
400 product.name = f"Pizza {_pizza_name_faker.last_name()}"
401 product.description = _faker.sentence()
402 product.price = Decimal(random.randint(250, 1000)) / Decimal(100)
403 product.available = random.random() < 0.9
405 product.full_clean()
406 product.save()
408 @maintain_integrity
409 def create_user(self):
410 """Create a new random user."""
411 self.stdout.write("Creating a user")
413 fakeprofile = _faker.profile()
414 fakeprofile["password"] = "".join(
415 random.choice(string.ascii_uppercase + string.digits) for _ in range(16)
416 )
417 user = get_user_model().objects.create_user(
418 fakeprofile["username"],
419 fakeprofile["mail"],
420 fakeprofile["password"],
421 )
423 user.first_name = fakeprofile["name"].split()[0]
424 user.last_name = " ".join(fakeprofile["name"].split()[1:])
426 profile = _ProfileFactory()
427 profile.user_id = user.id
428 profile.birthday = fakeprofile["birthdate"]
429 profile.website = fakeprofile["website"][0]
431 igen = IconGenerator(5, 5) # 5x5 blocks
432 icon = igen.generate(
433 user.username,
434 480,
435 480,
436 padding=(10, 10, 10, 10),
437 output_format="jpeg",
438 ) # 620x620 pixels, with 10 pixels padding on each side
439 profile.photo = SimpleUploadedFile(
440 fakeprofile["username"] + ".jpg", icon, "image/jpeg"
441 )
443 membership = Membership()
444 membership.user_id = user.id
445 membership.since = _faker.date_time_between(
446 start_date="-4y", end_date="now", tzinfo=None
447 )
449 membership.until = _faker.date_time_between(
450 start_date=membership.since, end_date="+2y", tzinfo=None
451 )
453 membership.type = random.choice([t[0] for t in Membership.MEMBERSHIP_TYPES])
455 if membership.type == Membership.HONORARY:
456 membership.until = None
458 user.full_clean()
459 user.save()
460 profile.full_clean()
461 profile.save()
462 membership.full_clean()
463 membership.save()
465 def create_vacancy(self, partners, categories):
466 """Create a new random vacancy.
468 :param partners: the partners to choose a partner from
469 :param categories: the categories to choose this vacancy from
470 """
471 self.stdout.write("Creating a vacancy")
472 vacancy = Vacancy()
474 vacancy.title = _faker.job()
475 vacancy.description = _faker.paragraph(nb_sentences=10)
476 vacancy.link = _faker.uri()
478 if random.random() < 0.75:
479 vacancy.partner = random.choice(partners)
480 else:
481 vacancy.company_name = f"{_faker.company()} {_faker.company_suffix()}"
482 igen = IconGenerator(5, 5) # 5x5 blocks
483 icon = igen.generate(
484 vacancy.company_name,
485 480,
486 480,
487 padding=(10, 10, 10, 10),
488 output_format="jpeg",
489 ) # 620x620 pixels, with 10 pixels padding on each side
490 vacancy.company_logo = SimpleUploadedFile(
491 vacancy.company_name + ".jpg", icon, "image/jpeg"
492 )
494 vacancy.full_clean()
495 vacancy.save()
497 vacancy.categories.set(random.sample(list(categories), random.randint(0, 3)))
499 def create_vacancy_category(self):
500 """Create new random vacancy categories."""
501 self.stdout.write("Creating a new vacancy category")
502 category = VacancyCategory()
504 category.name = _faker.text(max_nb_chars=30)
505 category.slug = _faker.slug()
507 category.full_clean()
508 category.save()
510 def create_document(self):
511 """Create new random documents."""
512 self.stdout.write("Creating a document")
513 doc = Document()
515 doc.name = _faker.text(max_nb_chars=30)
516 doc.category = random.choice([c[0] for c in Document.DOCUMENT_CATEGORIES])
517 doc.members_only = random.random() < 0.75
518 doc.file = SimpleUploadedFile(
519 f"{doc.name}.txt", _faker.text(max_nb_chars=120).encode()
520 )
521 doc.full_clean()
522 doc.save()
524 def create_newsletter(self):
525 self.stdout.write("Creating a new newsletter")
526 newsletter = Newsletter()
528 newsletter.title = _generate_title()
529 newsletter.description = _faker.paragraph()
530 newsletter.date = _faker.date_time_between("-3m", "+3m", _current_tz)
532 newsletter.clean() # full_clean does not work because of rendered_file
533 newsletter.save()
535 for _ in range(random.randint(1, 5)):
536 item = NewsletterItem()
537 item.title = _generate_title()
538 item.description = _faker.paragraph()
539 item.newsletter = newsletter
540 item.full_clean()
541 item.save()
543 for _ in range(random.randint(1, 5)):
544 item = NewsletterEvent()
545 item.title = _generate_title()
546 item.description = _faker.paragraph()
547 item.newsletter = newsletter
549 item.what = item.title
550 item.where = _faker.city()
551 item.start_datetime = _faker.date_time_between("-1y", "+3m", _current_tz)
552 duration = math.ceil(random.expovariate(0.2))
553 item.end_datetime = item.start_datetime + timedelta(hours=duration)
555 if random.random() < 0.5:
556 item.show_costs_warning = True
557 item.price = Decimal(random.randint(100, 2500)) / Decimal(100)
558 item.penalty_costs = max(
559 5.0,
560 Decimal(
561 random.randint(round(100 * item.price), round(500 * item.price))
562 )
563 / Decimal(100),
564 )
565 item.full_clean()
566 item.save()
568 def create_course(self):
569 self.stdout.write("Creating a new course")
570 course = Course()
572 course.name = _generate_title()
573 course.ec = 3 if random.random() < 0.5 else 6
575 course.course_code = "NWI-" + "".join(random.choices(string.digits, k=5))
577 course.since = random.randint(2016, 2020)
578 if random.random() < 0.5:
579 course.until = max(course.since + random.randint(1, 5), datetime.now().year)
581 # Save so we can add categories
582 course.save()
584 for category in Category.objects.order_by("?")[: random.randint(1, 3)]:
585 course.categories.add(category)
587 course.full_clean()
588 course.save()
590 for _ in range(random.randint(0, 5)):
591 self.create_summary(course)
592 for _ in range(random.randint(0, 5)):
593 self.create_exam(course)
595 def create_exam(self, course):
596 self.stdout.write("Creating an exam")
597 exam = Exam()
599 exam.name = _generate_title()
600 exam.type = random.choice(Exam.EXAM_TYPES)[0]
601 exam.course = course
602 exam.uploader = Member.objects.order_by("?")[0]
603 exam.accepted = random.random() < 0.5
604 exam.exam_date = _faker.date_between("-1y", "today")
605 exam.file = SimpleUploadedFile(
606 f"{exam.name}.txt", _faker.text(max_nb_chars=120).encode()
607 )
608 exam.language = random.choice(Exam.language.field.choices)[0]
609 exam.download_count = random.randint(0, 100)
611 exam.name = _generate_title()
613 exam.full_clean()
614 exam.save()
616 def create_summary(self, course):
617 self.stdout.write("Creating a summary")
618 summary = Summary()
620 summary.name = _generate_title()
621 summary.course = course
622 summary.uploader = Member.objects.order_by("?")[0]
623 summary.year = random.randint(2016, 2020)
624 summary.author = _faker.name()
625 summary.accepted = random.random() < 0.5
626 summary.file = SimpleUploadedFile(
627 f"{summary.name}.txt", _faker.text(max_nb_chars=120).encode()
628 )
629 summary.language = random.choice(Summary.language.field.choices)[0]
630 summary.download_count = random.randint(0, 100)
632 summary.full_clean()
633 summary.save()
635 def create_event_registration(self, event_to_register_for=None):
636 self.stdout.write("Creating an event registration")
637 registration = EventRegistration()
639 eligible = Member.objects.filter(registration_member_choices_limit())
640 registration.member = eligible.order_by("?")[0]
642 possible_event = (
643 event_to_register_for
644 if event_to_register_for
645 else get_event_to_register_for(registration.member)
646 )
648 if not possible_event:
649 self.stdout.write("No possible events to register for")
650 self.stdout.write("Creating a new event")
651 self.create_event()
652 possible_event = get_event_to_register_for(registration.member)
654 if not possible_event:
655 self.stdout.write("Could not create event")
656 return None
658 registration.event = possible_event
660 registration.date = registration.event.registration_start
662 registration.full_clean()
663 registration.save()
665 return registration
667 def create_payment(self):
668 self.stdout.write("Creating a payment")
670 possible_events = list(
671 filter(
672 lambda e: e.registrations.exists(),
673 Event.objects.filter(price__gt=0).order_by("?"),
674 )
675 )
676 if len(possible_events) == 0:
677 print("No event where can be payed could be found, creating a new event")
678 self.create_event()
679 possible_events = list(
680 filter(
681 lambda e: e.registrations.exists(),
682 Event.objects.filter(price__gt=0).order_by("?"),
683 )
684 )
686 if len(possible_events) == 0:
687 print("Could not create the event for an unexpected reason.")
688 return
690 event = possible_events[0]
691 if len(event.registrations) == 0:
692 print("No registrations found. Create some more registrations first")
693 return
695 registration = event.registrations.order_by("?")[0]
697 superusers = Member.objects.filter(is_superuser=True)
698 if not superusers:
699 print(
700 "There is no member which is also a superuser. Creating payments without this isn't possible!"
701 )
702 print("Please add an membership to the superuser.")
703 return
705 payment = create_payment(
706 registration,
707 superusers[0],
708 random.choice([Payment.CASH, Payment.CARD, Payment.WIRE]),
709 )
711 payment.full_clean()
713 @maintain_integrity
714 def create_photo_album(self):
715 self.stdout.write("Creating a photo album")
716 album = Album()
718 album.title = _generate_title()
720 album.date = _faker.date_between("-1y", "today")
722 album.slug = slugify("-".join([str(album.date), album.title]))
724 # normally this is set in save(), but required for validation
725 album.dirname = album.slug
727 if random.random() < 0.25:
728 album.hidden = True
729 if random.random() < 0.5:
730 album.shareable = True
732 album.full_clean()
733 album.save()
735 for _ in range(random.randint(20, 30)):
736 self.create_photo(album)
738 def create_photo(self, album):
739 self.stdout.write("Creating a photo")
740 photo = Photo()
742 photo.album = album
744 name = _generate_title()
746 igen = IconGenerator(12, 12)
747 icon = igen.generate(
748 token_hex(16),
749 480,
750 480,
751 padding=(10, 10, 10, 10),
752 output_format="jpeg",
753 ) # 620x620 pixels, with 10 pixels padding on each side
754 photo.file = SimpleUploadedFile(f"{name}.jpg", icon, "image/jpeg")
756 photo.full_clean()
757 photo.save()
759 def handle(self, *args, **options):
760 """Handle the command being executed.
762 :param options: the passed-in options
763 """
764 opts = [
765 "all",
766 "board",
767 "committee",
768 "event",
769 "partner",
770 "pizza",
771 "user",
772 "vacancy",
773 "document",
774 "newsletter",
775 "course",
776 "registration",
777 "payment",
778 "photoalbum",
779 ]
781 if all(not options[opt] for opt in opts):
782 self.stdout.write(
783 "Use ./manage.py help createfixtures to find out"
784 " how to call this command"
785 )
787 if options["all"]:
788 self.stdout.write("all argument given, overwriting all other inputs")
789 options = {
790 "user": 20,
791 "board": 3,
792 "committee": 3,
793 "society": 3,
794 "event": 20,
795 "partner": 6,
796 "vacancy": 4,
797 "pizza": 5,
798 "newsletter": 2,
799 "document": 8,
800 "course": 10,
801 "registration": 20,
802 "payment": 5,
803 "photoalbum": 5,
804 }
806 # Users need to be generated before boards and committees
807 if options["user"]:
808 for __ in range(options["user"]):
809 self.create_user()
811 if options["board"]:
812 lecture_year = datetime_to_lectureyear(date.today())
813 for i in range(options["board"]):
814 self.create_board(lecture_year - i)
816 # Member groups need to be generated before events
817 if options["committee"]:
818 for __ in range(options["committee"]):
819 self.create_member_group(Committee)
821 if options["society"]:
822 for __ in range(options["society"]):
823 self.create_member_group(Society)
825 if options["event"]:
826 for __ in range(options["event"]):
827 self.create_event()
829 # Partners need to be generated before vacancies
830 if options["partner"]:
831 local_partners = options["partner"] // 3
832 for __ in range(local_partners):
833 self.create_partner("local")
834 other_partners = options["partner"] - local_partners
835 for __ in range(other_partners):
836 self.create_partner()
837 inactive_partners = options["partner"] // 5
838 for __ in range(inactive_partners):
839 self.create_partner("inactive")
841 # Make one of the partners the main partner
842 try:
843 Partner.objects.get(is_main_partner=True)
844 except Partner.DoesNotExist:
845 self.create_partner("main")
847 if options["vacancy"]:
848 categories = VacancyCategory.objects.all()
849 if not categories:
850 self.stdout.write("No vacancy categories found. Creating 5 categories.")
851 for __ in range(5):
852 self.create_vacancy_category()
853 categories = VacancyCategory.objects.all()
855 partners = Partner.objects.all()
856 for __ in range(options["vacancy"]):
857 self.create_vacancy(partners, categories)
859 if options["pizza"]:
860 for __ in range(options["pizza"]):
861 self.create_pizza()
863 if options["newsletter"]:
864 for __ in range(options["newsletter"]):
865 self.create_newsletter()
867 if options["document"]:
868 for __ in range(options["document"]):
869 self.create_document()
871 # Courses need to be created before exams and summaries
872 if options["course"]:
873 # Create course categories if needed
874 if len(Category.objects.all()) < 5:
875 for _ in range(5):
876 category = Category()
877 category.name = _generate_title()
879 category.save()
881 for _ in range(options["course"]):
882 self.create_course()
884 # Registrations need to be created before payments
885 if options["registration"]:
886 for _ in range(options["registration"]):
887 self.create_event_registration()
889 if options["payment"]:
890 for _ in range(options["payment"]):
891 self.create_payment()
893 if options["photoalbum"]:
894 for _ in range(options["photoalbum"]):
895 self.create_photo_album()