django ORM - prevent direct setting of model fields
<p>I have a Django class </p>

<pre><code>class Chat(models.Model):
    primary_node = models.ForeignKey('nodes.Node', blank=True, null=True, related_name='chats_at_this_pri_node', on_delete=models.SET_NULL)
    secondary_node = models.ForeignKey('nodes.Node', blank=True, null=True, related_name='chats_at_this_sec_node', on_delete=models.SET_NULL)
</code></pre>

<p>I want to forbid direct assigning of fields, such as</p>

<pre><code>chat.primary_node = some_node
</code></pre>

<p>and instead create a method <code>chat.assign_node(primary, secondary)</code> that updates nodes via Django <code>Chat.update()</code> model method. </p>

<p>The reason is that I want to log all changes to these nodes (count changes and update other model fields with the new count), but dont want myself and other developers to forget that we cannot assign fields directly, as this wouldn't trigger custom <code>assign_node</code> logic. </p>

<p>How Ñan I do that? </p>

<p>You could try do prevent assignment to these fields with <code>__setattr__</code>, but I recommend you don't do that for two reasons:</p>

<ol>
<li>this will probably introduce all kinds of unexpected side-effects</li>
<li>you are performing a check at runtime, to prevent something introduced at the time the code was written. That's like running a (tiny) unit-test on every request.</li>
</ol>

<p>I would simply rename the fields to <code>_primary_node</code> and <code>_secondary_node</code> to indicate that these are private fields and not intended to be used directly.</p>

<p>In addition, you could write a hook for your version control system that checks for assignments to these fields. This could be a simple grep for <code>_primary_node =</code> or something fancier like a plugin for a linter like flake8.</p>

python django