From 2d1be28a4cf2415db8550d569e7a27e327f071b1 Mon Sep 17 00:00:00 2001 From: WajahatKanju Date: Tue, 6 Feb 2024 22:31:13 +0500 Subject: [PATCH 1/4] add django extensions, add faker, add Django model factories for accounts --- accounts/models.py | 430 ++++++++++++------------- config/settings.py | 1 + requirements/local.txt | 17 +- scripts/__init__.py | 0 scripts/generate_fake_accounts_data.py | 165 ++++++++++ 5 files changed, 391 insertions(+), 222 deletions(-) create mode 100644 scripts/__init__.py create mode 100644 scripts/generate_fake_accounts_data.py diff --git a/accounts/models.py b/accounts/models.py index 23e5906..e743065 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -1,215 +1,215 @@ -from django.db import models -from django.urls import reverse -from django.contrib.auth.models import AbstractUser, UserManager -from django.conf import settings - -from django.db.models import Q -from PIL import Image - -from course.models import Program -from .validators import ASCIIUsernameValidator - - -# LEVEL_COURSE = "Level course" -BACHLOAR_DEGREE = "Bachloar" -MASTER_DEGREE = "Master" - -LEVEL = ( - # (LEVEL_COURSE, "Level course"), - (BACHLOAR_DEGREE, "Bachloar Degree"), - (MASTER_DEGREE, "Master Degree"), -) - -FATHER = "Father" -MOTHER = "Mother" -BROTHER = "Brother" -SISTER = "Sister" -GRAND_MOTHER = "Grand mother" -GRAND_FATHER = "Grand father" -OTHER = "Other" - -RELATION_SHIP = ( - (FATHER, "Father"), - (MOTHER, "Mother"), - (BROTHER, "Brother"), - (SISTER, "Sister"), - (GRAND_MOTHER, "Grand mother"), - (GRAND_FATHER, "Grand father"), - (OTHER, "Other"), -) - - -class CustomUserManager(UserManager): - def search(self, query=None): - queryset = self.get_queryset() - if query is not None: - or_lookup = ( - Q(username__icontains=query) - | Q(first_name__icontains=query) - | Q(last_name__icontains=query) - | Q(email__icontains=query) - ) - queryset = queryset.filter( - or_lookup - ).distinct() # distinct() is often necessary with Q lookups - return queryset - - -GENDERS = (("M", "Male"), ("F", "Female")) - - -class User(AbstractUser): - is_student = models.BooleanField(default=False) - is_lecturer = models.BooleanField(default=False) - is_parent = models.BooleanField(default=False) - is_dep_head = models.BooleanField(default=False) - gender = models.CharField(max_length=1, choices=GENDERS, blank=True, null=True) - phone = models.CharField(max_length=60, blank=True, null=True) - address = models.CharField(max_length=60, blank=True, null=True) - picture = models.ImageField( - upload_to="profile_pictures/%y/%m/%d/", default="default.png", null=True - ) - email = models.EmailField(blank=True, null=True) - - username_validator = ASCIIUsernameValidator() - - objects = CustomUserManager() - - class Meta: - ordering = ("-date_joined",) - - @property - def get_full_name(self): - full_name = self.username - if self.first_name and self.last_name: - full_name = self.first_name + " " + self.last_name - return full_name - - @classmethod - def get_student_count(cls): - return cls.objects.filter(is_student=True).count() - - @classmethod - def get_lecturer_count(cls): - return cls.objects.filter(is_lecturer=True).count() - - @classmethod - def get_superuser_count(cls): - return cls.objects.filter(is_superuser=True).count() - - def __str__(self): - return "{} ({})".format(self.username, self.get_full_name) - - @property - def get_user_role(self): - if self.is_superuser: - role = "Admin" - elif self.is_student: - role = "Student" - elif self.is_lecturer: - role = "Lecturer" - elif self.is_parent: - role = "Parent" - - return role - - def get_picture(self): - try: - return self.picture.url - except: - no_picture = settings.MEDIA_URL + "default.png" - return no_picture - - def get_absolute_url(self): - return reverse("profile_single", kwargs={"id": self.id}) - - def save(self, *args, **kwargs): - super().save(*args, **kwargs) - try: - img = Image.open(self.picture.path) - if img.height > 300 or img.width > 300: - output_size = (300, 300) - img.thumbnail(output_size) - img.save(self.picture.path) - except: - pass - - def delete(self, *args, **kwargs): - if self.picture.url != settings.MEDIA_URL + "default.png": - self.picture.delete() - super().delete(*args, **kwargs) - - -class StudentManager(models.Manager): - def search(self, query=None): - qs = self.get_queryset() - if query is not None: - or_lookup = Q(level__icontains=query) | Q(program__icontains=query) - qs = qs.filter( - or_lookup - ).distinct() # distinct() is often necessary with Q lookups - return qs - - -class Student(models.Model): - student = models.OneToOneField(User, on_delete=models.CASCADE) - # id_number = models.CharField(max_length=20, unique=True, blank=True) - level = models.CharField(max_length=25, choices=LEVEL, null=True) - program = models.ForeignKey(Program, on_delete=models.CASCADE, null=True) - - objects = StudentManager() - - class Meta: - ordering = ("-student__date_joined",) - - def __str__(self): - return self.student.get_full_name - - @classmethod - def get_gender_count(cls): - males_count = Student.objects.filter(student__gender="M").count() - females_count = Student.objects.filter(student__gender="F").count() - - return {"M": males_count, "F": females_count} - - def get_absolute_url(self): - return reverse("profile_single", kwargs={"id": self.id}) - - def delete(self, *args, **kwargs): - self.student.delete() - super().delete(*args, **kwargs) - - -class Parent(models.Model): - """ - Connect student with their parent, parents can - only view their connected students information - """ - - user = models.OneToOneField(User, on_delete=models.CASCADE) - student = models.OneToOneField(Student, null=True, on_delete=models.SET_NULL) - first_name = models.CharField(max_length=120) - last_name = models.CharField(max_length=120) - phone = models.CharField(max_length=60, blank=True, null=True) - email = models.EmailField(blank=True, null=True) - - # What is the relationship between the student and - # the parent (i.e. father, mother, brother, sister) - relation_ship = models.TextField(choices=RELATION_SHIP, blank=True) - - class Meta: - ordering = ("-user__date_joined",) - - def __str__(self): - return self.user.username - - -class DepartmentHead(models.Model): - user = models.OneToOneField(User, on_delete=models.CASCADE) - department = models.ForeignKey(Program, on_delete=models.CASCADE, null=True) - - class Meta: - ordering = ("-user__date_joined",) - - def __str__(self): - return "{}".format(self.user) +from django.db import models +from django.urls import reverse +from django.contrib.auth.models import AbstractUser, UserManager +from django.conf import settings + +from django.db.models import Q +from PIL import Image + +from course.models import Program +from .validators import ASCIIUsernameValidator + + +# LEVEL_COURSE = "Level course" +BACHLOAR_DEGREE = "Bachloar" +MASTER_DEGREE = "Master" + +LEVEL = ( + # (LEVEL_COURSE, "Level course"), + (BACHLOAR_DEGREE, "Bachloar Degree"), + (MASTER_DEGREE, "Master Degree"), +) + +FATHER = "Father" +MOTHER = "Mother" +BROTHER = "Brother" +SISTER = "Sister" +GRAND_MOTHER = "Grand mother" +GRAND_FATHER = "Grand father" +OTHER = "Other" + +RELATION_SHIP = ( + (FATHER, "Father"), + (MOTHER, "Mother"), + (BROTHER, "Brother"), + (SISTER, "Sister"), + (GRAND_MOTHER, "Grand mother"), + (GRAND_FATHER, "Grand father"), + (OTHER, "Other"), +) + + +class CustomUserManager(UserManager): + def search(self, query=None): + queryset = self.get_queryset() + if query is not None: + or_lookup = ( + Q(username__icontains=query) + | Q(first_name__icontains=query) + | Q(last_name__icontains=query) + | Q(email__icontains=query) + ) + queryset = queryset.filter( + or_lookup + ).distinct() # distinct() is often necessary with Q lookups + return queryset + + +GENDERS = (("M", "Male"), ("F", "Female")) + + +class User(AbstractUser): + is_student = models.BooleanField(default=False) + is_lecturer = models.BooleanField(default=False) + is_parent = models.BooleanField(default=False) + is_dep_head = models.BooleanField(default=False) + gender = models.CharField(max_length=1, choices=GENDERS, blank=True, null=True) + phone = models.CharField(max_length=60, blank=True, null=True) + address = models.CharField(max_length=60, blank=True, null=True) + picture = models.ImageField( + upload_to="profile_pictures/%y/%m/%d/", default="default.png", null=True + ) + email = models.EmailField(blank=True, null=True) + + username_validator = ASCIIUsernameValidator() + + objects = CustomUserManager() + + class Meta: + ordering = ("-date_joined",) + + @property + def get_full_name(self): + full_name = self.username + if self.first_name and self.last_name: + full_name = self.first_name + " " + self.last_name + return full_name + + @classmethod + def get_student_count(cls): + return cls.objects.filter(is_student=True).count() + + @classmethod + def get_lecturer_count(cls): + return cls.objects.filter(is_lecturer=True).count() + + @classmethod + def get_superuser_count(cls): + return cls.objects.filter(is_superuser=True).count() + + def __str__(self): + return "{} ({})".format(self.username, self.get_full_name) + + @property + def get_user_role(self): + if self.is_superuser: + role = "Admin" + elif self.is_student: + role = "Student" + elif self.is_lecturer: + role = "Lecturer" + elif self.is_parent: + role = "Parent" + + return role + + def get_picture(self): + try: + return self.picture.url + except: + no_picture = settings.MEDIA_URL + "default.png" + return no_picture + + def get_absolute_url(self): + return reverse("profile_single", kwargs={"id": self.id}) + + def save(self, *args, **kwargs): + super().save(*args, **kwargs) + try: + img = Image.open(self.picture.path) + if img.height > 300 or img.width > 300: + output_size = (300, 300) + img.thumbnail(output_size) + img.save(self.picture.path) + except: + pass + + def delete(self, *args, **kwargs): + if self.picture.url != settings.MEDIA_URL + "default.png": + self.picture.delete() + super().delete(*args, **kwargs) + + +class StudentManager(models.Manager): + def search(self, query=None): + qs = self.get_queryset() + if query is not None: + or_lookup = Q(level__icontains=query) | Q(program__icontains=query) + qs = qs.filter( + or_lookup + ).distinct() # distinct() is often necessary with Q lookups + return qs + + +class Student(models.Model): + student = models.OneToOneField(User, on_delete=models.CASCADE) + # id_number = models.CharField(max_length=20, unique=True, blank=True) + level = models.CharField(max_length=25, choices=LEVEL, null=True) + program = models.ForeignKey(Program, on_delete=models.CASCADE, null=True) + + objects = StudentManager() + + class Meta: + ordering = ("-student__date_joined",) + + def __str__(self): + return self.student.get_full_name + + @classmethod + def get_gender_count(cls): + males_count = Student.objects.filter(student__gender="M").count() + females_count = Student.objects.filter(student__gender="F").count() + + return {"M": males_count, "F": females_count} + + def get_absolute_url(self): + return reverse("profile_single", kwargs={"id": self.id}) + + def delete(self, *args, **kwargs): + self.student.delete() + super().delete(*args, **kwargs) + + +class Parent(models.Model): + """ + Connect student with their parent, parents can + only view their connected students information + """ + + user = models.OneToOneField(User, on_delete=models.CASCADE) + student = models.OneToOneField(Student, null=True, on_delete=models.SET_NULL) + first_name = models.CharField(max_length=120) + last_name = models.CharField(max_length=120) + phone = models.CharField(max_length=60, blank=True, null=True) + email = models.EmailField(blank=True, null=True) + + # What is the relationship between the student and + # the parent (i.e. father, mother, brother, sister) + relation_ship = models.TextField(choices=RELATION_SHIP, blank=True) + + class Meta: + ordering = ("-user__date_joined",) + + def __str__(self): + return self.user.username + + +class DepartmentHead(models.Model): + user = models.OneToOneField(User, on_delete=models.CASCADE) + department = models.ForeignKey(Program, on_delete=models.CASCADE, null=True) + + class Meta: + ordering = ("-user__date_joined",) + + def __str__(self): + return "{}".format(self.user) diff --git a/config/settings.py b/config/settings.py index a7f6d17..7f0d409 100644 --- a/config/settings.py +++ b/config/settings.py @@ -37,6 +37,7 @@ AUTH_USER_MODEL = "accounts.User" DJANGO_APPS = [ "jet.dashboard", "jet", + "django_extensions", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", diff --git a/requirements/local.txt b/requirements/local.txt index f7a7141..23de88f 100644 --- a/requirements/local.txt +++ b/requirements/local.txt @@ -1,7 +1,10 @@ --r base.txt - -psycopg2-binary==2.9.5 # https://github.com/psycopg/psycopg2 - -# Code quality -# ------------------------------------------------------------------------------ -black==22.12.0 # https://github.com/psf/black \ No newline at end of file +-r base.txt + +psycopg2-binary==2.9.5 # https://github.com/psycopg/psycopg2 + +# Code quality +# ------------------------------------------------------------------------------ +black==22.12.0 # https://github.com/psf/black + +# Django Extensions +django-extensions==3.1.3 # https://github.com/django-extensions/django-extensions \ No newline at end of file diff --git a/scripts/__init__.py b/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scripts/generate_fake_accounts_data.py b/scripts/generate_fake_accounts_data.py new file mode 100644 index 0000000..b812a03 --- /dev/null +++ b/scripts/generate_fake_accounts_data.py @@ -0,0 +1,165 @@ +import os +import django +from typing import List, Tuple +from django.utils import timezone +from faker import Faker +from factory.django import DjangoModelFactory +from factory import SubFactory, LazyAttribute, Iterator +from django_extensions.management.commands import runscript + +# Set up Django environment +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings") +django.setup() + +from accounts.models import User, Student, Parent, DepartmentHead, LEVEL, RELATION_SHIP +from course.models import Program + +fake = Faker() + +class UserFactory(DjangoModelFactory): + """ + Factory for creating User instances with optional flags. + + Attributes: + username (str): The generated username. + first_name (str): The generated first name. + last_name (str): The generated last name. + email (str): The generated email. + date_joined (datetime): The current date and time. + phone (str): The generated phone number. + address (str): The generated address. + is_student (bool): Flag indicating if the user is a student. + is_lecturer (bool): Flag indicating if the user is a lecturer. + is_parent (bool): Flag indicating if the user is a parent. + is_dep_head (bool): Flag indicating if the user is a department head. + """ + + class Meta: + model = User + + username: str = LazyAttribute(lambda x: fake.user_name()) + first_name: str = LazyAttribute(lambda x: fake.first_name()) + last_name: str = LazyAttribute(lambda x: fake.last_name()) + email: str = LazyAttribute(lambda x: fake.email()) + date_joined: timezone.datetime = timezone.now() + phone: str = LazyAttribute(lambda x: fake.phone_number()) + address: str = LazyAttribute(lambda x: fake.address()) + is_student: bool = False + is_lecturer: bool = False + is_parent: bool = False + is_dep_head: bool = False + + @classmethod + def _create(cls, model_class: type, *args, **kwargs) -> User: + """ + Create a User instance with optional flags. + + Args: + model_class (type): The class of the model to create. + + Returns: + User: The created User instance. + """ + user: User = super()._create(model_class, *args, **kwargs) + + # Set the appropriate flags based on the user type + if cls.is_student: + user.is_student = True + elif cls.is_parent: + user.is_parent = True + + user.save() + return user + +class ProgramFactory(DjangoModelFactory): + """ + Factory for creating Program instances. + + Attributes: + title (str): The generated program title. + summary (str): The generated summary. + """ + + class Meta: + model = Program + + title: str = LazyAttribute(lambda x: fake.sentence(nb_words=3)) + summary: str = LazyAttribute(lambda x: fake.text()) + + @classmethod + def _create(cls, model_class: type, *args, **kwargs) -> Program: + """ + Create a Program instance using get_or_create to avoid duplicates. + + Args: + model_class (type): The class of the model to create. + + Returns: + Program: The created Program instance. + """ + program, created = Program.objects.get_or_create(title=kwargs.get("title"), defaults=kwargs) + return program + +class StudentFactory(DjangoModelFactory): + """ + Factory for creating Student instances with associated User and Program. + + Attributes: + student (User): The associated User instance. + level (str): The level of the student. + program (Program): The associated Program instance. + """ + + class Meta: + model = Student + + student: User = SubFactory(UserFactory, is_student=True) + level: str = Iterator([choice[0] for choice in LEVEL]) + program: Program = SubFactory(ProgramFactory) + +class ParentFactory(DjangoModelFactory): + """ + Factory for creating Parent instances with associated User, Student, and Program. + + Attributes: + user (User): The associated User instance. + student (Student): The associated Student instance. + first_name (str): The generated first name. + last_name (str): The generated last name. + phone (str): The generated phone number. + email (str): The generated email. + relation_ship (str): The relationship with the student. + """ + + class Meta: + model = Parent + + user: User = SubFactory(UserFactory, is_parent=True) + student: Student = SubFactory(StudentFactory) + first_name: str = LazyAttribute(lambda x: fake.first_name()) + last_name: str = LazyAttribute(lambda x: fake.last_name()) + phone: str = LazyAttribute(lambda x: fake.phone_number()) + email: str = LazyAttribute(lambda x: fake.email()) + relation_ship: str = Iterator([choice[0] for choice in RELATION_SHIP]) + + +def generate_fake_accounts_data(num_programs: int, num_students: int, num_parents: int) -> None: + """ + Generate fake data for Programs, Students, Parents, and DepartmentHeads. + + Args: + num_programs (int): Number of programs to generate. + num_students (int): Number of students to generate. + num_parents (int): Number of parents to generate. + """ + programs: List[Program] = ProgramFactory.create_batch(num_programs) + students: List[Student] = StudentFactory.create_batch(num_students) + parents: List[Parent] = ParentFactory.create_batch(num_parents) + + print(f"Created {len(programs)} programs.") + print(f"Created {len(students)} students.") + print(f"Created {len(parents)} parents.") + + + +generate_fake_accounts_data(10, 10, 10) \ No newline at end of file From 7169dca8a3bd2273dcc1745cd82b4bc7eccbd8fe Mon Sep 17 00:00:00 2001 From: WajahatKanju Date: Tue, 6 Feb 2024 23:00:24 +0500 Subject: [PATCH 2/4] add Django model factories for core --- scripts/generate_fake_core_data.py | 114 +++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 scripts/generate_fake_core_data.py diff --git a/scripts/generate_fake_core_data.py b/scripts/generate_fake_core_data.py new file mode 100644 index 0000000..7914051 --- /dev/null +++ b/scripts/generate_fake_core_data.py @@ -0,0 +1,114 @@ +import os +import django +import random +from typing import List +from django.utils import timezone +from faker import Faker +from factory.django import DjangoModelFactory +from factory import SubFactory, LazyAttribute, Iterator +from core.models import ActivityLog, NewsAndEvents, Session, Semester, SEMESTER, POST + +# Set up Django environment +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings") +django.setup() + +fake = Faker() + +class NewsAndEventsFactory(DjangoModelFactory): + """ + Factory for creating NewsAndEvents instances. + + Attributes: + title (str): The generated title for the news or event. + summary (str): The generated summary. + posted_as (str): The type of the post, either 'News' or 'Event'. + updated_date (datetime): The generated date and time of update. + upload_time (datetime): The generated date and time of upload. + """ + + class Meta: + model = NewsAndEvents + + title: str = LazyAttribute(lambda x: fake.sentence(nb_words=4)) + summary: str = LazyAttribute(lambda x: fake.paragraph(nb_sentences=3)) + posted_as: str = fake.random_element(elements=[choice[0] for choice in POST]) + updated_date: timezone.datetime = fake.date_time_this_year() + upload_time: timezone.datetime = fake.date_time_this_year() + +class SessionFactory(DjangoModelFactory): + """ + Factory for creating Session instances. + + Attributes: + session (str): The generated session name. + is_current_session (bool): Flag indicating if the session is current. + next_session_begins (date): The date when the next session begins. + """ + + class Meta: + model = Session + + session: str = LazyAttribute(lambda x: fake.sentence(nb_words=2)) + is_current_session: bool = fake.boolean(chance_of_getting_true=50) + next_session_begins = LazyAttribute(lambda x: fake.future_datetime()) + + +class SemesterFactory(DjangoModelFactory): + """ + Factory for creating Semester instances. + + Attributes: + semester (str): The generated semester name. + is_current_semester (bool): Flag indicating if the semester is current. + session (Session): The associated session. + next_semester_begins (date): The date when the next semester begins. + """ + + class Meta: + model = Semester + + semester: str = fake.random_element(elements=[choice[0] for choice in SEMESTER]) + is_current_semester: bool = fake.boolean(chance_of_getting_true=50) + session: Session = SubFactory(SessionFactory) + next_semester_begins = LazyAttribute(lambda x: fake.future_datetime()) + +class ActivityLogFactory(DjangoModelFactory): + """ + Factory for creating ActivityLog instances. + + Attributes: + message (str): The generated log message. + """ + + class Meta: + model = ActivityLog + + message: str = LazyAttribute(lambda x: fake.text()) + + +def generate_fake_core_data(num_news_and_events: int, num_sessions: int, num_semesters: int, num_activity_logs: int) -> None: + """ + Generate fake data for core models: NewsAndEvents, Session, Semester, and ActivityLog. + + Args: + num_news_and_events (int): Number of NewsAndEvents instances to generate. + num_sessions (int): Number of Session instances to generate. + num_semesters (int): Number of Semester instances to generate. + num_activity_logs (int): Number of ActivityLog instances to generate. + """ + # Generate fake NewsAndEvents instances + news_and_events: List[NewsAndEvents] = NewsAndEventsFactory.create_batch(num_news_and_events) + print(f"Generated {num_news_and_events} NewsAndEvents instances.") + + # Generate fake Session instances + sessions: List[Session] = SessionFactory.create_batch(num_sessions) + print(f"Generated {num_sessions} Session instances.") + + # Generate fake Semester instances + semesters: List[Semester] = SemesterFactory.create_batch(num_semesters) + print(f"Generated {num_semesters} Semester instances.") + + # Generate fake ActivityLog instances + activity_logs: List[ActivityLog] = ActivityLogFactory.create_batch(num_activity_logs) + print(f"Generated {num_activity_logs} ActivityLog instances.") + From 47e5d028d1c25ac64d919b8e6107202c348cf917 Mon Sep 17 00:00:00 2001 From: WajahatKanju Date: Tue, 6 Feb 2024 23:28:54 +0500 Subject: [PATCH 3/4] add Django model factories for courses --- scripts/generate_fake_accounts_data.py | 2 +- scripts/generate_fake_course_data.py | 179 +++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 scripts/generate_fake_course_data.py diff --git a/scripts/generate_fake_accounts_data.py b/scripts/generate_fake_accounts_data.py index b812a03..5f28770 100644 --- a/scripts/generate_fake_accounts_data.py +++ b/scripts/generate_fake_accounts_data.py @@ -161,5 +161,5 @@ def generate_fake_accounts_data(num_programs: int, num_students: int, num_parent print(f"Created {len(parents)} parents.") +generate_fake_accounts_data(10, 10, 10) -generate_fake_accounts_data(10, 10, 10) \ No newline at end of file diff --git a/scripts/generate_fake_course_data.py b/scripts/generate_fake_course_data.py new file mode 100644 index 0000000..8bebc77 --- /dev/null +++ b/scripts/generate_fake_course_data.py @@ -0,0 +1,179 @@ +from typing import Type +from factory.django import DjangoModelFactory +from factory import SubFactory, LazyAttribute, Iterator +from faker import Faker + +from course.models import Program, Course, CourseAllocation,Upload, UploadVideo,CourseOffer, SEMESTER +from accounts.models import User, DepartmentHead +from core.models import Session + +from .generate_fake_accounts_data import UserFactory, ProgramFactory +from .generate_fake_core_data import SessionFactory + +fake = Faker() + +class DepartmentHeadFactory(DjangoModelFactory): + class Meta: + model = DepartmentHead + + user = SubFactory(UserFactory) + department = SubFactory(ProgramFactory) + + +class ProgramFactory(DjangoModelFactory): + """ + Factory for creating Program instances. + + Attributes: + title (str): The generated title for the program. + summary (str): The generated summary for the program. + """ + + class Meta: + model = Program + + title: str = LazyAttribute(lambda x: fake.sentence(nb_words=3)) + summary: str = LazyAttribute(lambda x: fake.paragraph()) + +class CourseFactory(DjangoModelFactory): + """ + Factory for creating Course instances. + + Attributes: + slug (str): The generated slug for the course. + title (str): The generated title for the course. + code (str): The generated code for the course. + credit (int): The generated credit for the course. + summary (str): The generated summary for the course. + program (Program): The associated program for the course. + level (str): The generated level for the course. + year (int): The generated year for the course. + semester (str): The generated semester for the course. + is_elective (bool): The flag indicating if the course is elective. + """ + + class Meta: + model = Course + + slug: str = LazyAttribute(lambda x: fake.slug()) + title: str = LazyAttribute(lambda x: fake.sentence(nb_words=4)) + code: str = LazyAttribute(lambda x: fake.unique.word()) + credit: int = LazyAttribute(lambda x: fake.random_int(min=1, max=6)) + summary: str = LazyAttribute(lambda x: fake.paragraph()) + program: Type[Program] = SubFactory(ProgramFactory) + level: str = Iterator(["Beginner", "Intermediate", "Advanced"]) + year: int = LazyAttribute(lambda x: fake.random_int(min=1, max=4)) + semester: str = Iterator([choice[0] for choice in SEMESTER]) + is_elective: bool = LazyAttribute(lambda x: fake.boolean()) + +class CourseAllocationFactory(DjangoModelFactory): + """ + Factory for creating CourseAllocation instances. + + Attributes: + lecturer (User): The associated lecturer for the course allocation. + session (Session): The associated session for the course allocation. + """ + + class Meta: + model = CourseAllocation + + lecturer: Type[User] = SubFactory(UserFactory, is_lecturer=True) + session: Type[Session] = SubFactory(SessionFactory) + +class UploadFactory(DjangoModelFactory): + """ + Factory for creating Upload instances. + + Attributes: + title (str): The generated title for the upload. + course (Course): The associated course for the upload. + file (str): The generated file path for the upload. + updated_date (datetime): The generated updated date for the upload. + upload_time (datetime): The generated upload time for the upload. + """ + + class Meta: + model = Upload + + title: str = LazyAttribute(lambda x: fake.sentence(nb_words=3)) + course = SubFactory(CourseFactory) # Adjust 'yourapp' with your actual app name + file: str = LazyAttribute(lambda x: fake.file_path(extension="pdf")) + updated_date = fake.date_time_this_year() + upload_time = fake.date_time_this_year() + +class UploadVideoFactory(DjangoModelFactory): + """ + Factory for creating UploadVideo instances. + + Attributes: + title (str): The generated title for the video upload. + slug (str): The generated slug for the video upload. + course (Course): The associated course for the video upload. + video (str): The generated video path for the video upload. + summary (str): The generated summary for the video upload. + timestamp (datetime): The generated timestamp for the video upload. + """ + + class Meta: + model = UploadVideo + + title: str = LazyAttribute(lambda x: fake.sentence(nb_words=3)) + slug: str = LazyAttribute(lambda x: fake.slug()) + course = SubFactory(CourseFactory) # Adjust 'yourapp' with your actual app name + video: str = LazyAttribute(lambda x: fake.file_path(extension="mp4")) + summary: str = LazyAttribute(lambda x: fake.paragraph()) + timestamp = fake.date_time_this_year() + +class CourseOfferFactory(DjangoModelFactory): + """ + Factory for creating CourseOffer instances. + + Attributes: + dep_head (DepartmentHead): The associated department head for the course offer. + """ + + class Meta: + model = CourseOffer + + dep_head = SubFactory(DepartmentHeadFactory) + + +def generate_fake_course_data(num_programs: int, num_courses: int, num_course_allocations: int, num_uploads: int, num_upload_videos: int, num_course_offers: int) -> None: + """Generate fake data using various factories. + + Args: + num_programs (int): Number of fake programs to create. + num_courses (int): Number of fake courses to create. + num_course_allocations (int): Number of fake course allocations to create. + num_uploads (int): Number of fake uploads to create. + num_upload_videos (int): Number of fake upload videos to create. + num_course_offers (int): Number of fake course offers to create. + """ + # Generate fake programs + programs = ProgramFactory.create_batch(num_programs) + print(f"Created {len(programs)} programs.") + + # Generate fake courses + courses = CourseFactory.create_batch(num_courses) + print(f"Created {len(courses)} courses.") + + # Generate fake course allocations + course_allocations = CourseAllocationFactory.create_batch(num_course_allocations) + print(f"Created {len(course_allocations)} course allocations.") + + # Generate fake uploads + uploads = UploadFactory.create_batch(num_uploads) + print(f"Created {len(uploads)} uploads.") + + # Generate fake upload videos + upload_videos = UploadVideoFactory.create_batch(num_upload_videos) + print(f"Created {len(upload_videos)} upload videos.") + + # Generate fake course offers + course_offers = CourseOfferFactory.create_batch(num_course_offers) + print(f"Created {len(course_offers)} course offers.") + + + +generate_fake_course_data(10, 10, 10, 10, 10, 10) \ No newline at end of file From 3086d52ac1a484eb555463ab414de834889e2e7a Mon Sep 17 00:00:00 2001 From: WajahatKanju Date: Tue, 6 Feb 2024 23:29:19 +0500 Subject: [PATCH 4/4] finialized django factories --- scripts/{generate_fake_course_data.py => generate_fake_data.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/{generate_fake_course_data.py => generate_fake_data.py} (100%) diff --git a/scripts/generate_fake_course_data.py b/scripts/generate_fake_data.py similarity index 100% rename from scripts/generate_fake_course_data.py rename to scripts/generate_fake_data.py