2

I am trying to validate a related object (ForeignKey) when creating an object the base object with forms. The related object may or may not exist. Below I use MPTT but this is a general foreign key problem.

I have a model like this:

# model:
class MyMPTTModel(models.Model):
    name = models.CharField(max_length=256, unique=True) # this is set
    parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children') 

#form
class MyMPTTModelForm(forms.ModelForm):

    parent = mptt_forms.TreeNodeChoiceField(queryset=MyMPTTModel.objects.all())

    class Meta:
        model = MyMPTTModel
        fields = ['name', 'parent']

I want to atomically get_or_create a set of nodes with the form(set?).

Something like:

paths = ['each-part/of-the-path/is-the-name', 'each-part/of-the-path/could-have-mutliple-children']
for path in paths:
    parent = None
    nodes = []
    for p in path.split('/'):    
        nodes.append({'name': p, 'parent': parent })
        parent = p

    for node in nodes:
        name, parent = node.values()
        if parent:
            parent = MyMPTTModel.objects.get_or_create(name=parent)[0]
        MyMPTTModel.objects.get_or_create(name=name)

I'm struggling with the get_or_create part of the form as the parent may not exist and therefore is not a valid choice. I could create the parents before I create the next node, but then when it fails, it would create a bunch of orphan nodes since the children failed.

I want to validate each node and create them all together (or not).

Greg Samson
  • 1,267
  • 2
  • 11
  • 21
  • In what situation would children fail to be created? As far as I can see the was you are creating objects mean they would always be created. You are creating each parent before creating its child - so when would a parent ever not exist? – solarissmoke Jun 25 '18 at 04:50
  • The second example is what I’m trying to do in a form. I do not want to use get or create in case an object down the line fails to validate – Greg Samson Jun 26 '18 at 05:38
  • And how would an object fail to validate? – solarissmoke Jun 28 '18 at 04:35
  • this is a toy example.... it could fail in lots of ways in a real example. For this one, say the name is 257 characters long or there is another validation on name not listed. It doesn't really matter HOW it failed validation, only that it does. – Greg Samson Jun 28 '18 at 17:04
  • Have you tried wrapping the for loop in a `transactions.atomic()` context? If any exceptions within the context body are not handled, the database is rolled back. – CoffeeBasedLifeform Jun 29 '18 at 18:33
  • So im trying to do this without the for loop, but instead use forms. – Greg Samson Jun 29 '18 at 22:34

0 Answers0