Merge pull request #28 from WajahatKanju/feature/auto-populate-data

Dummy Data Generation Utility
This commit is contained in:
Adil Mohak 2024-02-09 21:00:02 +03:00 committed by GitHub
commit 6c8bc0a1a5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 684 additions and 219 deletions

View File

@ -54,15 +54,6 @@ class CustomUserManager(UserManager):
).distinct() # distinct() is often necessary with Q lookups ).distinct() # distinct() is often necessary with Q lookups
return queryset return queryset
def get_student_count(self):
return self.model.objects.filter(is_student=True).count()
def get_lecturer_count(self):
return self.model.objects.filter(is_lecturer=True).count()
def get_superuser_count(self):
return self.model.objects.filter(is_superuser=True).count()
GENDERS = (("M", "Male"), ("F", "Female")) GENDERS = (("M", "Male"), ("F", "Female"))
@ -94,6 +85,18 @@ class User(AbstractUser):
full_name = self.first_name + " " + self.last_name full_name = self.first_name + " " + self.last_name
return full_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): def __str__(self):
return "{} ({})".format(self.username, self.get_full_name) return "{} ({})".format(self.username, self.get_full_name)

View File

@ -37,6 +37,7 @@ AUTH_USER_MODEL = "accounts.User"
DJANGO_APPS = [ DJANGO_APPS = [
"jet.dashboard", "jet.dashboard",
"jet", "jet",
"django_extensions",
"django.contrib.admin", "django.contrib.admin",
"django.contrib.auth", "django.contrib.auth",
"django.contrib.contenttypes", "django.contrib.contenttypes",

View File

@ -5,3 +5,6 @@ psycopg2-binary==2.9.5 # https://github.com/psycopg/psycopg2
# Code quality # Code quality
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
black==22.12.0 # https://github.com/psf/black black==22.12.0 # https://github.com/psf/black
# Django Extensions
django-extensions==3.1.3 # https://github.com/django-extensions/django-extensions

0
scripts/__init__.py Normal file
View File

View File

@ -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)

View File

@ -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.")

View File

@ -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)