Skip to content

Commit b29348d

Browse files
committed
Update code
1 parent d6c0cbb commit b29348d

File tree

13 files changed

+121
-91
lines changed

13 files changed

+121
-91
lines changed

backend/apps/owasp/admin/chapter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class ChapterAdmin(admin.ModelAdmin, GenericEntityAdminMixin):
1111
"""Admin for Chapter model."""
1212

1313
autocomplete_fields = ("owasp_repository",)
14-
inlines = [EntityMemberInline]
14+
inlines = (EntityMemberInline,)
1515
list_display = (
1616
"name",
1717
"created_at",

backend/apps/owasp/admin/committee.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class CommitteeAdmin(admin.ModelAdmin, GenericEntityAdminMixin):
1111
"""Admin for Committee model."""
1212

1313
autocomplete_fields = ("owasp_repository",)
14-
inlines = [EntityMemberInline]
14+
inlines = (EntityMemberInline,)
1515
search_fields = ("name",)
1616

1717

backend/apps/owasp/admin/entity_member.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,32 @@
88
class EntityMemberAdmin(admin.ModelAdmin):
99
"""Admin for EntityMember records (generic link to any OWASP entity)."""
1010

11-
list_display = (
11+
autocomplete_fields = ("member",)
12+
fields = (
13+
"entity_type",
14+
"entity_id",
1215
"member",
1316
"kind",
14-
"is_reviewed",
1517
"order",
18+
"is_reviewed",
19+
"description",
1620
)
17-
list_filter = ("kind", "is_reviewed")
18-
search_fields = ("member__login", "member__name", "description", "object_id")
19-
fields = (
20-
"content_type",
21-
"object_id",
21+
list_display = (
2222
"member",
2323
"kind",
24+
"is_reviewed",
2425
"order",
26+
)
27+
list_filter = (
28+
"kind",
2529
"is_reviewed",
30+
)
31+
search_fields = (
32+
"member__login",
33+
"member__name",
2634
"description",
35+
"entity_id",
2736
)
28-
autocomplete_fields = ("member",)
2937

3038

3139
admin.site.register(EntityMember, EntityMemberAdmin)

backend/apps/owasp/admin/mixins.py

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,6 @@
77
from apps.owasp.models.entity_member import EntityMember
88

99

10-
class EntityMemberInline(GenericTabularInline):
11-
"""EntityMember inline for admin."""
12-
13-
model = EntityMember
14-
fields = ("member", "kind", "description", "order", "is_reviewed")
15-
raw_id_fields = ("member",)
16-
extra = 1
17-
ordering = ("order", "member__login")
18-
19-
2010
class BaseOwaspAdminMixin:
2111
"""Base mixin for OWASP admin classes providing common patterns."""
2212

@@ -44,6 +34,27 @@ def get_base_search_fields(self, *additional_fields):
4434
return self.search_field_names + additional_fields
4535

4636

37+
class EntityMemberInline(GenericTabularInline):
38+
"""EntityMember inline for admin."""
39+
40+
ct_field = "entity_type"
41+
ct_fk_field = "entity_id"
42+
extra = 1
43+
fields = (
44+
"member",
45+
"kind",
46+
"description",
47+
"order",
48+
"is_reviewed",
49+
)
50+
model = EntityMember
51+
ordering = (
52+
"order",
53+
"member__login",
54+
)
55+
raw_id_fields = ("member",)
56+
57+
4758
class GenericEntityAdminMixin(BaseOwaspAdminMixin):
4859
"""Mixin for generic entity admin with common entity functionality."""
4960

backend/apps/owasp/admin/project.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class ProjectAdmin(admin.ModelAdmin, GenericEntityAdminMixin):
1616
"owners",
1717
"repositories",
1818
)
19-
inlines = [EntityMemberInline]
19+
inlines = (EntityMemberInline,)
2020
list_display = (
2121
"custom_field_name",
2222
"created_at",

backend/apps/github/management/commands/github_match_users.py renamed to backend/apps/owasp/management/commands/owasp_update_leaders.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def process_entities(self, model_class, users_list, threshold):
6262

6363
new_members_to_create = []
6464

65-
content_type = ContentType.objects.get_for_model(model_class)
65+
entity_type = ContentType.objects.get_for_model(model_class)
6666

6767
for entity in model_class.objects.all():
6868
if not entity.leaders_raw:
@@ -78,8 +78,8 @@ def process_entities(self, model_class, users_list, threshold):
7878
new_members_to_create.extend(
7979
[
8080
EntityMember(
81-
content_type=content_type,
82-
object_id=entity.pk,
81+
entity_type=entity_type,
82+
entity_id=entity.pk,
8383
member_id=user["id"],
8484
kind=EntityMember.MemberKind.LEADER,
8585
is_reviewed=False,
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by Django 5.2.5 on 2025-08-13 06:33
1+
# Generated by Django 5.2.5 on 2025-08-14 23:53
22

33
import django.db.models.deletion
44
from django.db import migrations, models
@@ -8,34 +8,10 @@ class Migration(migrations.Migration):
88
dependencies = [
99
("contenttypes", "0002_remove_content_type_name"),
1010
("github", "0034_merge_20250804_1817"),
11-
("owasp", "0046_merge_0045_badge_0045_project_audience"),
11+
("owasp", "0047_delete_badge"),
1212
]
1313

1414
operations = [
15-
migrations.RemoveField(
16-
model_name="chapter",
17-
name="leaders",
18-
),
19-
migrations.RemoveField(
20-
model_name="chapter",
21-
name="suggested_leaders",
22-
),
23-
migrations.RemoveField(
24-
model_name="committee",
25-
name="leaders",
26-
),
27-
migrations.RemoveField(
28-
model_name="committee",
29-
name="suggested_leaders",
30-
),
31-
migrations.RemoveField(
32-
model_name="project",
33-
name="leaders",
34-
),
35-
migrations.RemoveField(
36-
model_name="project",
37-
name="suggested_leaders",
38-
),
3915
migrations.CreateModel(
4016
name="EntityMember",
4117
fields=[
@@ -45,31 +21,33 @@ class Migration(migrations.Migration):
4521
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
4622
),
4723
),
48-
("object_id", models.PositiveIntegerField()),
4924
(
5025
"description",
51-
models.TextField(blank=True, help_text="Optional role or description"),
26+
models.TextField(
27+
blank=True, default="", help_text="Optional role or description"
28+
),
5229
),
30+
("entity_id", models.PositiveIntegerField()),
5331
(
5432
"is_reviewed",
5533
models.BooleanField(
5634
default=False, help_text="Indicates if the membership is verified"
5735
),
5836
),
5937
(
60-
"order",
61-
models.PositiveIntegerField(
62-
default=0, help_text="Display order/priority of members"
38+
"kind",
39+
models.CharField(
40+
choices=[("leader", "Leader")], default="leader", max_length=6
6341
),
6442
),
6543
(
66-
"kind",
67-
models.CharField(
68-
choices=[("leader", "Leader")], default="leader", max_length=20
44+
"order",
45+
models.PositiveIntegerField(
46+
default=0, help_text="Display order/priority of members"
6947
),
7048
),
7149
(
72-
"content_type",
50+
"entity_type",
7351
models.ForeignKey(
7452
on_delete=django.db.models.deletion.CASCADE, to="contenttypes.contenttype"
7553
),
@@ -78,21 +56,21 @@ class Migration(migrations.Migration):
7856
"member",
7957
models.ForeignKey(
8058
on_delete=django.db.models.deletion.CASCADE,
81-
related_name="entity_memberships",
59+
related_name="+",
8260
to="github.user",
8361
),
8462
),
8563
],
8664
options={
87-
"verbose_name_plural": "Entity Members",
65+
"verbose_name_plural": "Entity members",
8866
"db_table": "owasp_entity_members",
8967
"indexes": [
9068
models.Index(
91-
fields=["content_type", "object_id"], name="owasp_entit_content_969a6f_idx"
69+
fields=["entity_type", "entity_id"], name="owasp_entit_entity__dda41b_idx"
9270
),
9371
models.Index(fields=["member"], name="owasp_entit_member__6e516f_idx"),
9472
],
95-
"unique_together": {("content_type", "object_id", "member", "kind")},
73+
"unique_together": {("entity_type", "entity_id", "member", "kind")},
9674
},
9775
),
9876
]

backend/apps/owasp/models/chapter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class Meta:
6464
latitude = models.FloatField(verbose_name="Latitude", blank=True, null=True)
6565
longitude = models.FloatField(verbose_name="Longitude", blank=True, null=True)
6666

67-
# Virtual fields
67+
# GRs.
6868
members = GenericRelation("owasp.EntityMember")
6969

7070
def __str__(self) -> str:

backend/apps/owasp/models/committee.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class Meta:
2828
db_table = "owasp_committees"
2929
verbose_name_plural = "Committees"
3030

31-
# Virtual fields
31+
# GRs.
3232
members = GenericRelation("owasp.EntityMember")
3333

3434
def __str__(self) -> str:

backend/apps/owasp/models/common.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,20 @@ class Meta:
7272
related_name="+",
7373
)
7474

75+
# M2Ms.
76+
leaders = models.ManyToManyField(
77+
"github.User",
78+
verbose_name="Leaders",
79+
related_name="assigned_%(class)s",
80+
blank=True,
81+
)
82+
suggested_leaders = models.ManyToManyField(
83+
"github.User",
84+
verbose_name="Suggested leaders",
85+
related_name="matched_%(class)s",
86+
blank=True,
87+
)
88+
7589
@property
7690
def github_url(self) -> str:
7791
"""Get GitHub URL."""
@@ -88,7 +102,7 @@ def index_md_url(self) -> str | None:
88102
)
89103

90104
@property
91-
def leaders(self) -> models.QuerySet[User]:
105+
def entity_leaders(self) -> models.QuerySet[User]:
92106
"""Return entity's leaders."""
93107
return User.objects.filter(
94108
pk__in=self.members.filter(kind=EntityMember.MemberKind.LEADER).values_list(

0 commit comments

Comments
 (0)