Skip to content

Commit

Permalink
#938 Exapnd fixtures to product human readable results
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewtavis committed Sep 21, 2024
1 parent 6bfe0de commit 6ac1844
Show file tree
Hide file tree
Showing 24 changed files with 236 additions and 125 deletions.
2 changes: 1 addition & 1 deletion backend/authentication/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class UserAdmin(BaseUserAdmin):
add_form = UserCreationForm

# The fields to be used in displaying the User model.
list_display = ["email", "is_admin"]
list_display = ["username", "email", "is_admin"]
list_filter = ["is_admin"]
fieldsets = [
(None, {"fields": ["email", "password"]}),
Expand Down
1 change: 1 addition & 0 deletions backend/authentication/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class Meta:

username = factory.Faker("user_name")
name = factory.Faker("name")
location = factory.Faker("city")
description = factory.Faker("text", max_nb_chars=500)
verified = factory.Faker("boolean")
verification_method = factory.Faker("word")
Expand Down
1 change: 1 addition & 0 deletions backend/authentication/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class UserModel(AbstractUser, PermissionsMixin):
username = models.CharField(max_length=255, unique=True)
name = models.CharField(max_length=255, blank=True)
password = models.CharField(max_length=255)
location = models.CharField(max_length=100, blank=True)
description = models.TextField(max_length=500, blank=True)
verified = models.BooleanField(default=False)
verification_method = models.CharField(max_length=30, blank=True)
Expand Down
80 changes: 34 additions & 46 deletions backend/backend/management/commands/populate_db.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import random
from argparse import ArgumentParser
from typing import TypedDict, Unpack

from django.core.management.base import BaseCommand

from authentication.factories import UserFactory
from authentication.factories import UserFactory, UserTopicFactory
from authentication.models import UserModel
from content.models import Topic
from entities.factories import (
GroupFactory,
GroupTextFactory,
Expand All @@ -18,99 +20,85 @@

class Options(TypedDict):
users: int
orgs: int
groups: int
events: int
orgs_per_user: int
groups_per_org: int
events_per_org: int


class Command(BaseCommand):
help = "Populate the database with dummy data"

def add_arguments(self, parser: ArgumentParser) -> None:
parser.add_argument("--users", type=int, default=10)
parser.add_argument("--opu", type=int, default=1) # orgs per user
parser.add_argument("--gpo", type=int, default=1) # groups per org
parser.add_argument("--epo", type=int, default=1) # events per org
parser.add_argument("--orgs-per-user", type=int, default=1)
parser.add_argument("--groups-per-org", type=int, default=1)
parser.add_argument("--events-per-org", type=int, default=1)

def handle(self, *args: str, **options: Unpack[Options]) -> None:
n_users = options.get("users")
n_orgs_per_user = options.get("opu")
n_groups_per_org = options.get("gpo")
n_events_per_org = options.get("epo")
num_users = options.get("users")
num_orgs_per_user = options.get("orgs_per_user")
num_groups_per_org = options.get("groups_per_org")
num_events_per_org = options.get("events_per_org")

# Clear all tables before creating new data.
UserModel.objects.exclude(username="admin").delete()
Organization.objects.all().delete()
Group.objects.all().delete()
Event.objects.all().delete()

topics = Topic.objects.all()

try:
users = [
UserFactory(username=f"activist_{i}", name=f"Activist {i}")
for i in range(n_users)
for i in range(num_users)
]

for i, user in enumerate(users):
user_location = "Berlin"
user_topic = "Climate"
for u, user in enumerate(users):
user_topic = random.choice(topics)
UserTopicFactory(user_id=user, topic_id=user_topic)

for _ in range(n_orgs_per_user):
for o in range(num_orgs_per_user):
user_org = OrganizationFactory(
name=f"{user_location} {user_topic} Organization {i}",
name=f"{user_topic.name} Organization (u: {u} o: {o})",
created_by=user,
)

OrganizationTextFactory(
org_id=user_org,
iso="en",
primary=True,
description="This is an org",
get_involved="Get involved!",
donate_prompt="Donate!",
)
OrganizationTextFactory(org_id=user_org, iso="en", primary=True)

for g in range(n_groups_per_org):
for g in range(num_groups_per_org):
user_org_group = GroupFactory(
org_id=user_org,
name=f"{user_location} {user_topic} Group {i}-{g}",
name=f"{user_topic.name} Group (u: {u} o: {o} g: {g})",
created_by=user,
)

GroupTextFactory(
group_id=user_org_group,
iso="en",
primary=True,
description="This is a group",
get_involved="Get involved!",
donate_prompt="Donate!",
group_id=user_org_group, iso="en", primary=True
)

for e in range(n_events_per_org):
for e in range(num_events_per_org):
user_org_event = EventFactory(
name=f"{user_location} {user_topic} Event {i}-{e}",
name=f"{user_topic.name} Event (u: {u} o: {o} e: {e})",
created_by=user,
)

EventTextFactory(
event_id=user_org_event,
iso="en",
primary=True,
description="This is a group",
get_involved="Get involved!",
event_id=user_org_event, iso="en", primary=True
)

self.stdout.write(
self.style.ERROR(
f"Number of users created: {n_users}\n"
f"Number of organizations created: {n_users * n_orgs_per_user}\n"
f"Number of groups created: {n_users * n_orgs_per_user * n_groups_per_org}\n"
f"Number of events created: {n_users * n_orgs_per_user * n_events_per_org}\n"
f"Number of users created: {num_users}\n"
f"Number of organizations created: {num_users * num_orgs_per_user}\n"
f"Number of groups created: {num_users * num_orgs_per_user * num_groups_per_org}\n"
f"Number of events created: {num_users * num_orgs_per_user * num_events_per_org}\n"
)
)

except Exception as error:
except TypeError as error:
self.stdout.write(
self.style.ERROR(
f"An error occurred during the creation of dummy data: {error}"
f"A type error occurred during the creation of dummy data: {error}. Make sure to use dashes for populate_db arguments and that they're of the appropriate types."
)
)
2 changes: 1 addition & 1 deletion backend/backend/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@
"rest_framework.throttling.AnonRateThrottle",
"rest_framework.throttling.UserRateThrottle",
],
"DEFAULT_THROTTLE_RATES": {"anon": "7/min", "user": "10/min"},
"DEFAULT_THROTTLE_RATES": {"anon": "20/min", "user": "30/min"},
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
"DEFAULT_PAGINATION_ORDERS_OBJECTS": False,
Expand Down
4 changes: 2 additions & 2 deletions backend/content/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,13 @@ class Meta:
fields = "__all__"

def validate(self, data: Dict[str, Union[str, int]]) -> Dict[str, Union[str, int]]:
if data["active"] is True and data["deprecation_date"] is not None:
if data["active"] is True and data.get("deprecation_date") is not None:
raise serializers.ValidationError(
_("Active topics cannot have a deprecation date."),
code="active_topic_with_deprecation_error",
)

if data["active"] is False and data["deprecation_date"] is None:
if data["active"] is False and data.get("deprecation_date") is None:
raise serializers.ValidationError(
_("Deprecated topics must have a deprecation date."),
code="inactive_topic_no_deprecation_error",
Expand Down
12 changes: 6 additions & 6 deletions backend/entities/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ class Meta:
group_id = factory.SubFactory(GroupFactory)
iso = factory.Faker("word")
primary = factory.Faker("boolean")
description = factory.Faker("text")
get_involved = factory.Faker("text")
donate_prompt = factory.Faker("text")
description = factory.Faker(provider="text", locale="la", max_nb_chars=1000)
get_involved = factory.Faker(provider="text", locale="la")
donate_prompt = factory.Faker(provider="text", locale="la")


class GroupTopicFactory(factory.django.DjangoModelFactory):
Expand Down Expand Up @@ -190,9 +190,9 @@ class Meta:
org_id = factory.SubFactory(OrganizationFactory)
iso = "en"
primary = factory.Faker("boolean")
description = factory.Faker("text")
get_involved = factory.Faker("text")
donate_prompt = factory.Faker("text")
description = factory.Faker(provider="text", locale="la", max_nb_chars=1000)
get_involved = factory.Faker(provider="text", locale="la")
donate_prompt = factory.Faker(provider="text", locale="la")


class OrganizationTopicFactory(factory.django.DjangoModelFactory):
Expand Down
5 changes: 3 additions & 2 deletions backend/entities/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from django.db import models

from authentication import enums
from utils.models import ISO_CHOICES

# MARK: Main Tables

Expand Down Expand Up @@ -129,7 +130,7 @@ def __str__(self) -> str:

class GroupText(models.Model):
group_id = models.ForeignKey(Group, on_delete=models.CASCADE)
iso = models.CharField(max_length=2)
iso = models.CharField(max_length=2, choices=ISO_CHOICES)
primary = models.BooleanField(default=False)
description = models.TextField(max_length=500)
get_involved = models.TextField(max_length=500, blank=True)
Expand Down Expand Up @@ -216,7 +217,7 @@ def __str__(self) -> str:

class OrganizationText(models.Model):
org_id = models.ForeignKey(Organization, on_delete=models.CASCADE)
iso = models.CharField(max_length=2)
iso = models.CharField(max_length=2, choices=ISO_CHOICES)
primary = models.BooleanField(default=False)
description = models.TextField(max_length=2500)
get_involved = models.TextField(max_length=500, blank=True)
Expand Down
3 changes: 2 additions & 1 deletion backend/entities/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ def validate(self, data: dict[str, Any]) -> dict[str, Any]:
raise serializers.ValidationError(
"You must accept the terms of service to create an organization."
)
return data

return data

def create(self, validated_data: dict[str, Any]) -> Organization:
description = validated_data.pop("description", None)
Expand All @@ -90,6 +90,7 @@ def create(self, validated_data: dict[str, Any]) -> Organization:
org_id=org, description=description
)
org.org_text = org_text

return org


Expand Down
14 changes: 7 additions & 7 deletions backend/entities/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from django.utils import timezone
from rest_framework import status, viewsets
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.throttling import AnonRateThrottle, UserRateThrottle
Expand Down Expand Up @@ -116,18 +116,15 @@ class OrganizationViewSet(viewsets.ModelViewSet[Organization]):
serializer_class = OrganizationSerializer
pagination_class = CustomPagination
throttle_classes = [AnonRateThrottle, UserRateThrottle]
permission_classes = [
IsAuthenticated,
]
authentication_classes = [
TokenAuthentication,
]
permission_classes = [IsAuthenticatedOrReadOnly]
authentication_classes = [TokenAuthentication]

def create(self, request: Request) -> Response:
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
org = serializer.save(created_by=request.user)
OrganizationApplication.objects.create(org_id=org)

return Response(serializer.data, status=status.HTTP_201_CREATED)

def retrieve(self, request: Request, pk: str | None = None) -> Response:
Expand All @@ -139,6 +136,7 @@ def retrieve(self, request: Request, pk: str | None = None) -> Response:

def list(self, request: Request) -> Response:
serializer = self.get_serializer(self.get_queryset(), many=True)

return Response(serializer.data, status=status.HTTP_200_OK)

def update(self, request: Request, pk: str | None = None) -> Response:
Expand All @@ -157,6 +155,7 @@ def update(self, request: Request, pk: str | None = None) -> Response:
serializer = self.get_serializer(org, data=request.data, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save()

return Response(serializer.data, status.HTTP_200_OK)

def partial_update(self, request: Request, pk: str | None = None) -> Response:
Expand All @@ -175,6 +174,7 @@ def partial_update(self, request: Request, pk: str | None = None) -> Response:
serializer = self.get_serializer(org, data=request.data, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save()

return Response(serializer.data, status.HTTP_200_OK)

def destroy(self, request: Request, pk: str | None = None) -> Response:
Expand Down
4 changes: 2 additions & 2 deletions backend/events/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ class Meta:
event_id = factory.SubFactory(EventFactory)
iso = factory.Faker("word")
primary = factory.Faker("boolean")
description = factory.Faker("text")
get_involved = factory.Faker("text")
description = factory.Faker(provider="text", locale="la", max_nb_chars=1000)
get_involved = factory.Faker(provider="text", locale="la")


class EventTopicFactory(factory.django.DjangoModelFactory):
Expand Down
3 changes: 2 additions & 1 deletion backend/events/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from django.db import models

from backend.mixins.models import CreationDeletionMixin
from utils.models import ISO_CHOICES

# MARK: Main Tables

Expand Down Expand Up @@ -130,7 +131,7 @@ def __str__(self) -> str:

class EventText(models.Model):
event_id = models.ForeignKey(Event, on_delete=models.CASCADE)
iso = models.CharField(max_length=2)
iso = models.CharField(max_length=2, choices=ISO_CHOICES)
primary = models.BooleanField()
description = models.TextField(max_length=500)
get_involved = models.TextField(max_length=500, blank=True)
Expand Down
2 changes: 1 addition & 1 deletion backend/fixtures/superuser.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"email": "[email protected]",
"is_high_risk": false,
"is_active": true,
"is_admin": false,
"is_admin": true,
"is_confirmed": true,
"groups": [],
"user_permissions": []
Expand Down
Loading

0 comments on commit 6ac1844

Please sign in to comment.