Skip to content

Commit

Permalink
apps/projects: add topics as m2m relation
Browse files Browse the repository at this point in the history
  • Loading branch information
goapunk authored and m4ra committed Dec 11, 2023
1 parent 540fb14 commit 4d971c6
Show file tree
Hide file tree
Showing 12 changed files with 161 additions and 17 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,15 @@ lint:
$(VIRTUAL_ENV)/bin/isort --diff -c $(SOURCE_DIRS) || EXIT_STATUS=$$?; \
$(VIRTUAL_ENV)/bin/flake8 $(SOURCE_DIRS) --exclude migrations,settings || EXIT_STATUS=$$?; \
npm run lint || EXIT_STATUS=$$?; \
$(VIRTUAL_ENV)/bin/python manage.py makemigrations --dry-run --check --noinput || EXIT_STATUS=$$?; \
exit $${EXIT_STATUS}

.PHONY: lint-quick
lint-quick:
EXIT_STATUS=0; \
npm run lint-staged || EXIT_STATUS=$$?; \
$(VIRTUAL_ENV)/bin/python manage.py makemigrations --dry-run --check --noinput || EXIT_STATUS=$$?; \
exit $${EXIT_STATUS}

.PHONY: lint-python-files
lint-python-files:
Expand Down
10 changes: 4 additions & 6 deletions adhocracy4/projects/fields.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from django.conf import settings
from multiselectfield import MultiSelectField


class TopicField(MultiSelectField):
"""Deprecated, don't use"""

# TODO: remove once topic migrations are rolled out
def __init__(self, *args, **kwargs):
kwargs["max_length"] = 254
kwargs["max_choices"] = 2
Expand All @@ -11,11 +13,7 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

def contribute_to_class(self, cls, name, **kwargs):
"""Initialize the choices from the project's settings if they exist."""
if hasattr(settings, "A4_PROJECT_TOPICS"):
self.choices = settings.A4_PROJECT_TOPICS
else:
self.choices = ()
self.choices = ()

# Call the super method at last so that choices are already initialized
super().contribute_to_class(cls, name, **kwargs)
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 4.2 on 2023-11-29 13:18

import adhocracy4.projects.fields
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("a4projects", "0041_ckeditor5_iframes"),
]

operations = [
migrations.CreateModel(
name="Topic",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("code", models.CharField(blank=True, max_length=10, unique=True)),
],
),
migrations.AddField(
model_name="project",
name="m2mtopics",
field=models.ManyToManyField(to="a4projects.topic"),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Generated by Django 4.2 on 2023-11-29 13:20
import sys
import importlib

from django.db import migrations
from django.conf import settings


def add_topics_to_m2m_table(apps, schema_editor):
if hasattr(settings, "A4_PROJECT_TOPICS"):
project = apps.get_model("a4projects", "Project")
topic = apps.get_model("a4projects", "Topic")
for project in project.objects.all():
for topic_code in project.topics:
proj_topic, _ = topic.objects.get_or_create(
code=topic_code,
)
project.m2mtopics.add(proj_topic)
else:
pass


def reverse_func(apps, schema_editor):
if hasattr(settings, "A4_PROJECT_TOPICS"):
project = apps.get_model("a4projects", "Project")
for project in project.objects.all():
for topic in project.m2mtopics.all():
project.m2mtopics.remove(topic)
else:
pass


class Migration(migrations.Migration):
dependencies = [
("a4projects", "0042_topic_alter_project_topics_project_m2mtopics"),
]

operations = [
migrations.RunPython(add_topics_to_m2m_table, reverse_func),
]
16 changes: 16 additions & 0 deletions adhocracy4/projects/migrations/0044_remove_project_field_topics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Generated by Django 4.2 on 2023-11-29 15:03

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("a4projects", "0043_migrate_topics_to_m2m_topics"),
]

operations = [
migrations.RemoveField(
model_name="project",
name="topics",
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Generated by Django 4.2 on 2023-11-29 15:14

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("a4projects", "0044_remove_project_field_topics"),
]

operations = [
migrations.RenameField(
model_name="project", old_name="m2mtopics", new_name="topics"
),
]
20 changes: 14 additions & 6 deletions adhocracy4/projects/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from django.urls import reverse
from django.utils import timezone
from django.utils.functional import cached_property
from django.utils.module_loading import import_string
from django.utils.translation import gettext_lazy as _
from django_ckeditor_5.fields import CKEditor5Field
from django_enumfield.enum import EnumField
Expand All @@ -19,11 +20,20 @@
from adhocracy4.models import base

from .enums import Access
from .fields import TopicField
from .utils import get_module_clusters
from .utils import get_module_clusters_dict


class Topic(models.Model):
code = models.CharField(blank=True, max_length=10, unique=True)

def __str__(self):
if hasattr(settings, "A4_PROJECT_TOPICS"):
topics_enum = import_string(settings.A4_PROJECT_TOPICS)
return str(topics_enum(self.code).label)
return self.code


class ProjectManager(models.Manager):
def get_by_natural_key(self, name):
return self.get(name=name)
Expand Down Expand Up @@ -259,9 +269,8 @@ class Project(
"dashboard."
),
)
topics = TopicField(
verbose_name=_("Project topics"), help_text=_("Add topics to your project.")
)
topics = models.ManyToManyField(Topic)

project_type = models.CharField(
blank=True, max_length=256, default="a4projects.Project"
)
Expand Down Expand Up @@ -321,8 +330,7 @@ def has_moderator(self, user):
@cached_property
def topic_names(self):
if hasattr(settings, "A4_PROJECT_TOPICS"):
choices = dict(settings.A4_PROJECT_TOPICS)
return [choices[topic] for topic in self.topics]
return [str(topic) for topic in self.topics.all()]
return []

@cached_property
Expand Down
6 changes: 6 additions & 0 deletions changelog/0007.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Changed

- apps/projects:
add topics model/table
make topics a m2m relation to projects
stop making use of django-multiselectfield as it's not maintained
3 changes: 3 additions & 0 deletions changelog/0008.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Changed

- apps/projects: topics should be first created and then added to project in migration
3 changes: 3 additions & 0 deletions changelog/0009.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Fixed

- apps/projects: project's topics_name property should iterate through m2m relation
22 changes: 22 additions & 0 deletions tests/project/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# fmt: off

from django.db import models
from django.utils.translation import gettext_lazy as _


class TopicEnum(models.TextChoices):
"""Choices for project topics."""

ANT = "ANT", _("Anti-discrimination"),
WOR = "WOR", _("Work & economy"),
BUI = "BUI", _("Building & living"),
EDU = "EDU", _("Education & research"),
CHI = "CHI", _("Children, youth & family"),
FIN = "FIN", _("Finances"),
HEA = "HEA", _("Health & sports"),
INT = "INT", _("Integration"),
CUL = "CUL", _("Culture & leisure"),
NEI = "NEI", _("Neighborhood & participation"),
URB = "URB", _("Urban development"),
ENV = "ENV", _("Environment & public green space"),
TRA = "TRA", _("Traffic")
6 changes: 1 addition & 5 deletions tests/project/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,11 +226,7 @@
},
}

A4_PROJECT_TOPICS = (
("ANT", "Anti-discrimination"),
("WOR", "Work & economy"),
("BUI", "Building & living"),
)
A4_PROJECT_TOPICS = "tests.project.enums.TopicEnum"

A4_COMMENT_CATEGORIES = (
("QUE", "Question"),
Expand Down

0 comments on commit 4d971c6

Please sign in to comment.