Browse Source
feat(transmitters): introduce reusable ScholarlyOpinion model and link to TransmitterOpinion
feat(transmitters): introduce reusable ScholarlyOpinion model and link to TransmitterOpinion
- Create ScholarlyOpinion model for standalone reusable scholarly opinions with status and multilingual text - Add foreign key link from TransmitterOpinion to ScholarlyOpinion with automatic backward sync - Create data migration 0053 to populate ScholarlyOpinion records from existing transmitter opinions - Expose DovodiScholarlyOpinionViewSet and register route /dovodi-opinions/ in admin router - Update TransmitterOpinion serializers and views to prioritize linked ScholarlyOpinion datamaster
7 changed files with 258 additions and 33 deletions
-
79apps/hadis/migrations/0053_scholarlyopinion_and_transmitteropinion_opinion.py
-
73apps/hadis/models/transmitter.py
-
59apps/hadis/serializers/hadis.py
-
37apps/hadis/serializers/serializers_admin.py
-
3apps/hadis/urls.py
-
7apps/hadis/views/transmitter.py
-
33apps/hadis/views_admin.py
@ -0,0 +1,79 @@ |
|||||
|
# Generated by Django 4.2.30 on 2026-10-19 06:30 |
||||
|
|
||||
|
import json |
||||
|
from django.db import migrations, models |
||||
|
import django.db.models.deletion |
||||
|
|
||||
|
|
||||
|
def migrate_existing_opinions_forward(apps, schema_editor): |
||||
|
ScholarlyOpinion = apps.get_model("hadis", "ScholarlyOpinion") |
||||
|
TransmitterOpinion = apps.get_model("hadis", "TransmitterOpinion") |
||||
|
|
||||
|
cache = {} |
||||
|
for to in TransmitterOpinion.objects.all().order_by("id"): |
||||
|
if to.opinion_id: |
||||
|
continue |
||||
|
raw_text = to.opinion_text if isinstance(to.opinion_text, list) else [] |
||||
|
try: |
||||
|
key = (to.status_id, json.dumps(raw_text, sort_keys=True, ensure_ascii=False)) |
||||
|
except Exception: |
||||
|
key = (to.status_id, str(raw_text)) |
||||
|
|
||||
|
scholarly_op = cache.get(key) |
||||
|
if scholarly_op is None: |
||||
|
scholarly_op = ScholarlyOpinion.objects.create( |
||||
|
opinion_text=raw_text, |
||||
|
status_id=to.status_id, |
||||
|
) |
||||
|
cache[key] = scholarly_op |
||||
|
|
||||
|
to.opinion_id = scholarly_op.id |
||||
|
to.save(update_fields=["opinion"]) |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
("hadis", "0052_transmitters_gender"), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.CreateModel( |
||||
|
name="ScholarlyOpinion", |
||||
|
fields=[ |
||||
|
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), |
||||
|
("opinion_text", models.JSONField(default=list, verbose_name="Opinion Text")), |
||||
|
("created_at", models.DateTimeField(auto_now_add=True, verbose_name="created at")), |
||||
|
("updated_at", models.DateTimeField(auto_now=True, verbose_name="updated at")), |
||||
|
( |
||||
|
"status", |
||||
|
models.ForeignKey( |
||||
|
blank=True, |
||||
|
null=True, |
||||
|
on_delete=django.db.models.deletion.CASCADE, |
||||
|
related_name="scholarly_opinions", |
||||
|
to="hadis.opinionstatus", |
||||
|
verbose_name="opinion status", |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
options={ |
||||
|
"verbose_name": "Scholarly Opinion", |
||||
|
"verbose_name_plural": "Scholarly Opinions", |
||||
|
"ordering": ("-id",), |
||||
|
}, |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name="transmitteropinion", |
||||
|
name="opinion", |
||||
|
field=models.ForeignKey( |
||||
|
blank=True, |
||||
|
null=True, |
||||
|
on_delete=django.db.models.deletion.CASCADE, |
||||
|
related_name="transmitter_opinions", |
||||
|
to="hadis.scholarlyopinion", |
||||
|
verbose_name="Scholarly Opinion", |
||||
|
), |
||||
|
), |
||||
|
migrations.RunPython(migrate_existing_opinions_forward, migrations.RunPython.noop), |
||||
|
] |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue