title: In Django, is it better to store complex chaining save methods in models, or in views?
body: <p>Lets say I have models similar to something like this:</p>
  
  <pre><code>from django.db import models, transaction
  
  
  class X(models.Model):
      ...
  
      def do_something(self):
          ...
  
  
  class Y(models.Model):
      ...
      x = models.ForeignKey(X, on_delete=models.CASCADE)
  
      def do_something(self):
          ...
  
      def save(self, *args, **kwargs):
          super(Y, self).save(*args, **kwargs)
          self.x.do_something()
          self.x.save()
  
  
  class Z(models.Model):
      ...
      y = models.ForeignKey(Y, on_delete=models.CASCADE)
  
      @transaction.atomic
      def save(self, *args, **kwargs):
          super(Z, self).save(*args, **kwargs)
          self.y.do_something()
          self.y.save()
  </code></pre>
  
  <p>In other words, if a <code>Z</code> object is saved, its referenced <code>Y</code> object is updated and saved, which in turn saves its referenced <code>X</code> object. Right now, as it clear from the code, the complex save process is stored entirely in the models module.</p>
  
  <p>Anyway, my question is this: should this sort of logic be stored in views instead? Like there could be a view like so:</p>
  
  <pre><code>from django.db import transaction
  
  @transaction.atomic
  def my_view(request, z_pk):
      z = Z.objects.select_related('y__x').get(pk=z_pk)
      z.save()
  
      y = z.y
      y.do_something()
      y.save()
  
      x = y.x
      x.do_something()
      x.save()
  
      ...
  </code></pre>
  
  <p>Obviously, for the above scenario, the model module would be simplified into something like this:</p>
  
  <pre><code>from django.db import models, transaction
  
  
  class X(models.Model):
      ...
  
      def do_something(self):
          ...
  
  
  class Y(models.Model):
      ...
      x = models.ForeignKey(X, on_delete=models.CASCADE)
  
      def do_something(self):
          ...
  
  
  class Z(models.Model):
      ...
      y = models.ForeignKey(Y, on_delete=models.CASCADE)
  </code></pre>
  
  <p>Which one of these approaches is best practices? I could not find anything particular to this in the docs. I apologize if this question is a matter of preference thing. Thanks for any answers.</p>