on_delete not getting called when ForeignKey is a property

11 views
Skip to first unread message

mccc

unread,
Mar 14, 2019, 11:01:32 AM3/14/19
to Django users
Hello,

I have set up this nice model:
class CustomGroup(models.Model):

    name = models.CharField(max_length=255)
    _parent = models.ForeignKey(
        "self", on_delete=models.CASCADE, null=True, related_name="descendants", db_column="parent"
    )
    _depth = models.IntegerField(default=1)

    @property
    def parent(self):
        return self._parent

    @property
    def depth(self):
        return self._depth

    @parent.setter
    def parent(self, value):
        if self == value:
            raise ValueError("parent must be different from self")
        p = value
        while value is not None:
            if self == value.parent:
                raise ValueError("parent cannot be a descendant")
            value = value.parent
        self._parent = p
        self.depth = (p.depth + 1) if p is not None else 1

    @depth.setter
    def depth(self, value):
        if value > MAX_GROUPS_DEPTH:
            raise ValueError("Too many nested groups")

        for descendant in self.descendants.all():
            descendant.depth = value + 1
            descendant.save()
        self._depth = value


and the CASCADE function is not getting fired when the parent gets deleted;
I tried adding another field without the property modifiers, and that worked as expected.

Is there any way I can have both my custom getter and setter, and the on_delete behaviour?

Thanks

Chetan Ganji

unread,
Mar 14, 2019, 11:22:15 AM3/14/19
to django...@googlegroups.com
Why do you need to do any calculations in the model code? 

I would do any calculations in the views and store them using models. That will remove the getters and setters from model. 
Everything should work fine then.

Hope it helps.


Regards,
Chetan Ganji
+91-900-483-4183


I’m protected online with Avast Free Antivirus. Get it here — it’s free forever.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/292cfb9d-c605-46ef-bb4a-5d69a8ecbb6b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

I’m protected online with Avast Free Antivirus. Get it here — it’s free forever.

Sithembewena L. Dube

unread,
Mar 14, 2019, 11:31:58 AM3/14/19
to django...@googlegroups.com
There is nothing wrong with having logic in models.

This is the principle of object orientation - encapsulating methods and properties in a class definition to group related behaviours and attributes of a specified type of entity.

See the section titled "Make ‘em Fat" here: https://django-best-practices.readthedocs.io/en/latest/applications.html


Kind regards,
Sithembewena


Sent with Shift

Chetan Ganji

unread,
Mar 14, 2019, 11:43:05 AM3/14/19
to django...@googlegroups.com
That approach is not working for the original poster. So I gave him a solution that solves the problem.

I meant, its my opinion to keep models slim and write utils to make the controllers slim. 
You don't have to follow it ;-)  Follow what makes sense to you. I prefer it that way. 


Regards,
Chetan Ganji
+91-900-483-4183


I’m protected online with Avast Free Antivirus. Get it here — it’s free forever.

mccc

unread,
Mar 14, 2019, 11:45:07 AM3/14/19
to Django users


On Thursday, March 14, 2019 at 4:22:15 PM UTC+1, Chetan Ganji wrote:
Why do you need to do any calculations in the model code? 

I would do any calculations in the views and store them using models. That will remove the getters and setters from model. 
Everything should work fine then.

Hope it helps.

No, nothing would work fine: in that case I would need to remember constantly to either copy the code to handle the behaviour or make a call to a view each time and in any place that handles those fields.
Plus the tests would need to check over and over for the same behaviour every time the field was involved.

I'm sorry, but it really doesn't help.

Chetan Ganji

unread,
Mar 14, 2019, 12:04:06 PM3/14/19
to django...@googlegroups.com
OK. 

One work around could be to fire the signal manually just after you set/delete the value? I have not checked it yet :P 

Do one thing, implement pre_delete and post_delete signals and check the values of  instance, sender and using. It might give you more information about what is happening. 


Regards,
Chetan Ganji
+91-900-483-4183


I’m protected online with Avast Free Antivirus. Get it here — it’s free forever.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
Reply all
Reply to author
Forward
0 new messages