Skip to content

Commit a22651b

Browse files
jamalexbjester
authored andcommitted
Don't defer validation of null foreignkey references
1 parent 9264674 commit a22651b

4 files changed

Lines changed: 93 additions & 1 deletion

File tree

morango/models/core.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,8 @@ def deferred_clean_fields(self):
900900
for field in self._meta.fields:
901901
if not isinstance(field, models.ForeignKey):
902902
continue
903+
if getattr(self, field.attname) is None:
904+
continue
903905
excluded_fields.append(field.name)
904906
deferred_fks[field.related_model.__name__].append(
905907
ForeignKeyReference(from_pk=self.pk, to_pk=getattr(self, field.attname))
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.11.29 on 2022-04-27 04:49
3+
from __future__ import unicode_literals
4+
5+
from django.conf import settings
6+
from django.db import migrations, models
7+
import django.db.models.deletion
8+
9+
10+
class Migration(migrations.Migration):
11+
12+
dependencies = [
13+
('facility_profile', '0001_initial'),
14+
]
15+
16+
operations = [
17+
migrations.AlterField(
18+
model_name='interactionlog',
19+
name='user',
20+
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
21+
),
22+
]

tests/testapp/facility_profile/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ class InteractionLog(FacilityDataSyncableModel):
9494
# Morango syncing settings
9595
morango_model_name = "contentinteractionlog"
9696

97-
user = models.ForeignKey(MyUser)
97+
user = models.ForeignKey(MyUser, blank=True, null=True)
9898
content_id = UUIDField(db_index=True, default=uuid.uuid4)
9999

100100
def calculate_source_id(self, *args, **kwargs):

tests/testapp/tests/sync/test_controller.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from django.test import TestCase
99
from facility_profile.models import Facility
1010
from facility_profile.models import MyUser
11+
from facility_profile.models import InteractionLog
1112
from facility_profile.models import SummaryLog
1213
from test.support import EnvironmentVarGuard
1314

@@ -616,6 +617,12 @@ def _test_deserialization_of_model_with_missing_parent(self, correct_self_ref_fk
616617
self.assertTrue(new_child.dirty_bit)
617618
self.assertIn("exist", new_child.deserialization_error)
618619

620+
621+
class ForeignKeyDeserializationTestCase(TestCase):
622+
def setUp(self):
623+
(self.current_id, _) = InstanceIDModel.get_or_create_current_instance()
624+
self.mc = MorangoProfileController("facilitydata")
625+
619626
def test_deserialization_of_model_with_missing_foreignkey_referent(self):
620627

621628
user = MyUser.objects.create(username="penguin")
@@ -636,6 +643,67 @@ def test_deserialization_of_model_with_missing_foreignkey_referent(self):
636643
self.assertTrue(new_log.dirty_bit)
637644
self.assertIn("missing MyUser", new_log.deserialization_error)
638645

646+
def test_deserialization_of_model_with_disallowed_null_foreignkey(self):
647+
648+
user = MyUser.objects.create(username="penguin")
649+
log = SummaryLog.objects.create(user=user)
650+
self.mc.serialize_into_store()
651+
652+
new_log = Store.objects.get(id=log.id)
653+
data = json.loads(new_log.serialized)
654+
new_log.id = data["id"] = "f" * 32
655+
data["user_id"] = None
656+
new_log.serialized = json.dumps(data)
657+
new_log.dirty_bit = True
658+
new_log.save()
659+
660+
self.mc.deserialize_from_store()
661+
662+
new_log.refresh_from_db()
663+
self.assertTrue(new_log.dirty_bit)
664+
self.assertIn("cannot be null", new_log.deserialization_error)
665+
666+
def test_deserialization_of_model_with_allowed_null_foreignkey(self):
667+
668+
user = MyUser.objects.create(username="penguin")
669+
log = InteractionLog.objects.create(user=user)
670+
self.mc.serialize_into_store()
671+
672+
new_log = Store.objects.get(id=log.id)
673+
data = json.loads(new_log.serialized)
674+
new_log.id = data["id"] = "f" * 32
675+
data["user_id"] = None
676+
new_log.serialized = json.dumps(data)
677+
new_log.dirty_bit = True
678+
new_log.save()
679+
680+
self.mc.deserialize_from_store()
681+
682+
new_log.refresh_from_db()
683+
self.assertFalse(new_log.dirty_bit)
684+
self.assertTrue(new_log.deserialization_error == "")
685+
self.assertTrue(InteractionLog.objects.filter(id=new_log.id).exists())
686+
687+
def test_deserialization_of_model_with_valid_foreignkey_referent(self):
688+
689+
user = MyUser.objects.create(username="penguin")
690+
log = SummaryLog.objects.create(user=user)
691+
self.mc.serialize_into_store()
692+
693+
new_log = Store.objects.get(id=log.id)
694+
data = json.loads(new_log.serialized)
695+
new_log.id = data["id"] = "f" * 32
696+
new_log.serialized = json.dumps(data)
697+
new_log.dirty_bit = True
698+
new_log.save()
699+
700+
self.mc.deserialize_from_store()
701+
702+
new_log.refresh_from_db()
703+
self.assertFalse(new_log.dirty_bit)
704+
self.assertTrue(new_log.deserialization_error == "")
705+
self.assertTrue(SummaryLog.objects.filter(id=new_log.id).exists())
706+
639707

640708
class SessionControllerTestCase(SimpleTestCase):
641709
def setUp(self):

0 commit comments

Comments
 (0)