From fls
Create test data with factory_boy and SiteAwareFactory. Use when creating factories, writing test data setup, or when the user mentions factory_boy or test data.
npx claudepluginhub preludetech/django-craftThis skill is limited to using the following tools:
Every Django app that has models should have a `factories.py` file at `freedom_ls/<app>/factories.py`. Always check existing factories before creating new ones.
Generates realistic test data, fixtures, factories, seeds, and edge cases using Faker.js, Fishery, pytest fixtures for JS/TS/Python apps and databases.
Generates realistic, consistent test data using factories, fixtures, builders, and faker libraries for unit/integration tests, mocks, seeds, and edge cases.
Creates factory patterns for test data in automation suites with Jest and pytest. Useful for unit/integration testing, mocking, and TDD.
Share bugs, ideas, or general feedback.
Every Django app that has models should have a factories.py file at freedom_ls/<app>/factories.py. Always check existing factories before creating new ones.
All site-aware models must use SiteAwareFactory from freedom_ls/site_aware_models/factories.py. It automatically sets the site field from the thread-local request context (provided by the mock_site_context fixture) and bypasses custom site-aware managers during creation.
from freedom_ls.site_aware_models.factories import SiteAwareFactory
class MyModelFactory(SiteAwareFactory):
class Meta:
model = MyModel
name = factory.Sequence(lambda n: f"Item {n}")
factories.pySiteAwareFactory from freedom_ls.site_aware_models.factoriesSiteAwareFactory (not factory.django.DjangoModelFactory directly)Meta.model to the model classGenerate unique values:
email = factory.Sequence(lambda n: f"user{n}@example.com")
title = factory.Sequence(lambda n: f"Topic {n}")
Create related objects automatically:
student = factory.SubFactory(StudentFactory)
course = factory.SubFactory(CourseFactory)
Derive a field from other fields:
slug = factory.LazyAttribute(lambda obj: slugify(obj.title))
Call a function with no arguments:
deadline = factory.LazyFunction(lambda: timezone.now() + timedelta(days=30))
Define reusable field combinations in Params:
class Params:
staff = factory.Trait(is_staff=True)
superuser = factory.Trait(is_staff=True, is_superuser=True)
# Usage:
UserFactory(staff=True)
UserFactory(superuser=True)
Run logic after the object is created (e.g., setting passwords):
class Meta:
skip_postgeneration_save = True
@factory.post_generation
def password(obj, create, extracted, **kwargs):
obj.set_password(extracted or obj.email)
if create:
obj.save(update_fields=["password"])
Use Meta.exclude and Params to accept a convenience parameter, then derive content_type and object_id via LazyAttribute:
class CohortDeadlineFactory(SiteAwareFactory):
class Meta:
model = CohortDeadline
exclude = ["content_item"]
class Params:
content_item = None
content_type = factory.LazyAttribute(
lambda obj: ContentType.objects.get_for_model(obj.content_item)
if obj.content_item else None
)
object_id = factory.LazyAttribute(
lambda obj: obj.content_item.pk if obj.content_item else None
)
# Usage:
topic = TopicFactory()
CohortDeadlineFactory(content_item=topic)
course = CourseFactory()
topic = TopicFactory()
ContentCollectionItemFactory(collection_object=course, child_object=topic)
Always use mock_site_context when working with site-aware factories:
@pytest.mark.django_db
def test_student_creation(mock_site_context):
student = StudentFactory()
assert student.user is not None
assert student.site is not None
@pytest.mark.django_db
def test_course_with_custom_title(mock_site_context):
course = CourseFactory(title="My Course")
assert course.title == "My Course"
assert course.slug == "my-course"
Override only the fields relevant to your test:
@pytest.mark.django_db
def test_cohort_membership(mock_site_context):
cohort = CohortFactory(name="Test Cohort")
membership = CohortMembershipFactory(cohort=cohort)
assert membership.cohort == cohort
# membership.student was auto-created by SubFactory