mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
2653 lines
No EOL
355 KiB
HTML
2653 lines
No EOL
355 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<html lang="en" data-content_root="../../../../">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>django.db.models.base — Evennia latest documentation</title>
|
|
<link rel="stylesheet" type="text/css" href="../../../../_static/pygments.css?v=d75fae25" />
|
|
<link rel="stylesheet" type="text/css" href="../../../../_static/nature.css?v=279e0f84" />
|
|
<link rel="stylesheet" type="text/css" href="../../../../_static/custom.css?v=e4a91a55" />
|
|
<script src="../../../../_static/documentation_options.js?v=c6e86fd7"></script>
|
|
<script src="../../../../_static/doctools.js?v=9bcbadda"></script>
|
|
<script src="../../../../_static/sphinx_highlight.js?v=dc90522c"></script>
|
|
<link rel="icon" href="../../../../_static/favicon.ico"/>
|
|
<link rel="index" title="Index" href="../../../../genindex.html" />
|
|
<link rel="search" title="Search" href="../../../../search.html" />
|
|
</head><body>
|
|
<div class="related" role="navigation" aria-label="Related">
|
|
<h3>Navigation</h3>
|
|
<ul>
|
|
<li class="right" style="margin-right: 10px">
|
|
<a href="../../../../genindex.html" title="General Index"
|
|
accesskey="I">index</a></li>
|
|
<li class="right" >
|
|
<a href="../../../../py-modindex.html" title="Python Module Index"
|
|
>modules</a> |</li>
|
|
<li class="nav-item nav-item-0"><a href="../../../../index.html">Evennia</a> »</li>
|
|
<li class="nav-item nav-item-1"><a href="../../../index.html" accesskey="U">Module code</a> »</li>
|
|
<li class="nav-item nav-item-this"><a href="">django.db.models.base</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="document">
|
|
<div class="documentwrapper">
|
|
<div class="bodywrapper">
|
|
<div class="body" role="main">
|
|
|
|
<h1>Source code for django.db.models.base</h1><div class="highlight"><pre>
|
|
<span></span><span class="kn">import</span><span class="w"> </span><span class="nn">copy</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">inspect</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">warnings</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">collections</span><span class="w"> </span><span class="kn">import</span> <span class="n">defaultdict</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">functools</span><span class="w"> </span><span class="kn">import</span> <span class="n">partialmethod</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">itertools</span><span class="w"> </span><span class="kn">import</span> <span class="n">chain</span>
|
|
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">asgiref.sync</span><span class="w"> </span><span class="kn">import</span> <span class="n">sync_to_async</span>
|
|
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">django</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.apps</span><span class="w"> </span><span class="kn">import</span> <span class="n">apps</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.conf</span><span class="w"> </span><span class="kn">import</span> <span class="n">settings</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.core</span><span class="w"> </span><span class="kn">import</span> <span class="n">checks</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.core.exceptions</span><span class="w"> </span><span class="kn">import</span> <span class="p">(</span>
|
|
<span class="n">NON_FIELD_ERRORS</span><span class="p">,</span>
|
|
<span class="n">FieldDoesNotExist</span><span class="p">,</span>
|
|
<span class="n">FieldError</span><span class="p">,</span>
|
|
<span class="n">MultipleObjectsReturned</span><span class="p">,</span>
|
|
<span class="n">ObjectDoesNotExist</span><span class="p">,</span>
|
|
<span class="n">ObjectNotUpdated</span><span class="p">,</span>
|
|
<span class="n">ValidationError</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.db</span><span class="w"> </span><span class="kn">import</span> <span class="p">(</span>
|
|
<span class="n">DJANGO_VERSION_PICKLE_KEY</span><span class="p">,</span>
|
|
<span class="n">DatabaseError</span><span class="p">,</span>
|
|
<span class="n">connection</span><span class="p">,</span>
|
|
<span class="n">connections</span><span class="p">,</span>
|
|
<span class="n">router</span><span class="p">,</span>
|
|
<span class="n">transaction</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.db.models</span><span class="w"> </span><span class="kn">import</span> <span class="n">NOT_PROVIDED</span><span class="p">,</span> <span class="n">ExpressionWrapper</span><span class="p">,</span> <span class="n">IntegerField</span><span class="p">,</span> <span class="n">Max</span><span class="p">,</span> <span class="n">Value</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.db.models.constants</span><span class="w"> </span><span class="kn">import</span> <span class="n">LOOKUP_SEP</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.db.models.deletion</span><span class="w"> </span><span class="kn">import</span> <span class="n">CASCADE</span><span class="p">,</span> <span class="n">Collector</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.db.models.expressions</span><span class="w"> </span><span class="kn">import</span> <span class="n">DatabaseDefault</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.db.models.fields.composite</span><span class="w"> </span><span class="kn">import</span> <span class="n">CompositePrimaryKey</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.db.models.fields.related</span><span class="w"> </span><span class="kn">import</span> <span class="p">(</span>
|
|
<span class="n">ForeignObjectRel</span><span class="p">,</span>
|
|
<span class="n">OneToOneField</span><span class="p">,</span>
|
|
<span class="n">lazy_related_operation</span><span class="p">,</span>
|
|
<span class="n">resolve_relation</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.db.models.functions</span><span class="w"> </span><span class="kn">import</span> <span class="n">Coalesce</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.db.models.manager</span><span class="w"> </span><span class="kn">import</span> <span class="n">Manager</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.db.models.options</span><span class="w"> </span><span class="kn">import</span> <span class="n">Options</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.db.models.query</span><span class="w"> </span><span class="kn">import</span> <span class="n">F</span><span class="p">,</span> <span class="n">Q</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.db.models.signals</span><span class="w"> </span><span class="kn">import</span> <span class="p">(</span>
|
|
<span class="n">class_prepared</span><span class="p">,</span>
|
|
<span class="n">post_init</span><span class="p">,</span>
|
|
<span class="n">post_save</span><span class="p">,</span>
|
|
<span class="n">pre_init</span><span class="p">,</span>
|
|
<span class="n">pre_save</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.db.models.utils</span><span class="w"> </span><span class="kn">import</span> <span class="n">AltersData</span><span class="p">,</span> <span class="n">make_model_tuple</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.utils.encoding</span><span class="w"> </span><span class="kn">import</span> <span class="n">force_str</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.utils.hashable</span><span class="w"> </span><span class="kn">import</span> <span class="n">make_hashable</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.utils.text</span><span class="w"> </span><span class="kn">import</span> <span class="n">capfirst</span><span class="p">,</span> <span class="n">get_text_list</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.utils.translation</span><span class="w"> </span><span class="kn">import</span> <span class="n">gettext_lazy</span> <span class="k">as</span> <span class="n">_</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">Deferred</span><span class="p">:</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="s2">"<Deferred field>"</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="s2">"<Deferred field>"</span>
|
|
|
|
|
|
<span class="n">DEFERRED</span> <span class="o">=</span> <span class="n">Deferred</span><span class="p">()</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">subclass_exception</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="n">module</span><span class="p">,</span> <span class="n">attached_to</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Create exception subclass. Used by ModelBase below.</span>
|
|
|
|
<span class="sd"> The exception is created in a way that allows it to be pickled, assuming</span>
|
|
<span class="sd"> that the returned exception class will be added as an attribute to the</span>
|
|
<span class="sd"> 'attached_to' class.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">return</span> <span class="nb">type</span><span class="p">(</span>
|
|
<span class="n">name</span><span class="p">,</span>
|
|
<span class="n">bases</span><span class="p">,</span>
|
|
<span class="p">{</span>
|
|
<span class="s2">"__module__"</span><span class="p">:</span> <span class="n">module</span><span class="p">,</span>
|
|
<span class="s2">"__qualname__"</span><span class="p">:</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">.</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">attached_to</span><span class="o">.</span><span class="vm">__qualname__</span><span class="p">,</span> <span class="n">name</span><span class="p">),</span>
|
|
<span class="p">},</span>
|
|
<span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_has_contribute_to_class</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
|
|
<span class="c1"># Only call contribute_to_class() if it's bound.</span>
|
|
<span class="k">return</span> <span class="ow">not</span> <span class="n">inspect</span><span class="o">.</span><span class="n">isclass</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="ow">and</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="s2">"contribute_to_class"</span><span class="p">)</span>
|
|
|
|
|
|
<div class="viewcode-block" id="ModelBase">
|
|
<a class="viewcode-back" href="../../../../api/evennia.typeclasses.models.html#evennia.typeclasses.models.ModelBase">[docs]</a>
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">ModelBase</span><span class="p">(</span><span class="nb">type</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Metaclass for all models."""</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__new__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="n">attrs</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="n">super_new</span> <span class="o">=</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__new__</span>
|
|
|
|
<span class="c1"># Also ensure initialization is only performed for subclasses of Model</span>
|
|
<span class="c1"># (excluding Model class itself).</span>
|
|
<span class="n">parents</span> <span class="o">=</span> <span class="p">[</span><span class="n">b</span> <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">bases</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">ModelBase</span><span class="p">)]</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">parents</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">super_new</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="n">attrs</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Create the class.</span>
|
|
<span class="n">module</span> <span class="o">=</span> <span class="n">attrs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">"__module__"</span><span class="p">)</span>
|
|
<span class="n">new_attrs</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"__module__"</span><span class="p">:</span> <span class="n">module</span><span class="p">}</span>
|
|
<span class="n">classcell</span> <span class="o">=</span> <span class="n">attrs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">"__classcell__"</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">classcell</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">new_attrs</span><span class="p">[</span><span class="s2">"__classcell__"</span><span class="p">]</span> <span class="o">=</span> <span class="n">classcell</span>
|
|
<span class="n">attr_meta</span> <span class="o">=</span> <span class="n">attrs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">"Meta"</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
<span class="c1"># Pass all attrs without a (Django-specific) contribute_to_class()</span>
|
|
<span class="c1"># method to type.__new__() so that they're properly initialized</span>
|
|
<span class="c1"># (i.e. __set_name__()).</span>
|
|
<span class="n">contributable_attrs</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="k">for</span> <span class="n">obj_name</span><span class="p">,</span> <span class="n">obj</span> <span class="ow">in</span> <span class="n">attrs</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="n">_has_contribute_to_class</span><span class="p">(</span><span class="n">obj</span><span class="p">):</span>
|
|
<span class="n">contributable_attrs</span><span class="p">[</span><span class="n">obj_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">obj</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">new_attrs</span><span class="p">[</span><span class="n">obj_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">obj</span>
|
|
<span class="n">new_class</span> <span class="o">=</span> <span class="n">super_new</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="n">new_attrs</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
|
|
<span class="n">abstract</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">attr_meta</span><span class="p">,</span> <span class="s2">"abstract"</span><span class="p">,</span> <span class="kc">False</span><span class="p">)</span>
|
|
<span class="n">meta</span> <span class="o">=</span> <span class="n">attr_meta</span> <span class="ow">or</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">new_class</span><span class="p">,</span> <span class="s2">"Meta"</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
<span class="n">base_meta</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">new_class</span><span class="p">,</span> <span class="s2">"_meta"</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
|
|
<span class="n">app_label</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="c1"># Look for an application configuration to attach the model to.</span>
|
|
<span class="n">app_config</span> <span class="o">=</span> <span class="n">apps</span><span class="o">.</span><span class="n">get_containing_app_config</span><span class="p">(</span><span class="n">module</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">meta</span><span class="p">,</span> <span class="s2">"app_label"</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">app_config</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">abstract</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span>
|
|
<span class="s2">"Model class </span><span class="si">%s</span><span class="s2">.</span><span class="si">%s</span><span class="s2"> doesn't declare an explicit "</span>
|
|
<span class="s2">"app_label and isn't in an application in "</span>
|
|
<span class="s2">"INSTALLED_APPS."</span> <span class="o">%</span> <span class="p">(</span><span class="n">module</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">app_label</span> <span class="o">=</span> <span class="n">app_config</span><span class="o">.</span><span class="n">label</span>
|
|
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">add_to_class</span><span class="p">(</span><span class="s2">"_meta"</span><span class="p">,</span> <span class="n">Options</span><span class="p">(</span><span class="n">meta</span><span class="p">,</span> <span class="n">app_label</span><span class="p">))</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">abstract</span><span class="p">:</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">add_to_class</span><span class="p">(</span>
|
|
<span class="s2">"DoesNotExist"</span><span class="p">,</span>
|
|
<span class="n">subclass_exception</span><span class="p">(</span>
|
|
<span class="s2">"DoesNotExist"</span><span class="p">,</span>
|
|
<span class="nb">tuple</span><span class="p">(</span>
|
|
<span class="n">x</span><span class="o">.</span><span class="n">DoesNotExist</span>
|
|
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">parents</span>
|
|
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="s2">"_meta"</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">x</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">abstract</span>
|
|
<span class="p">)</span>
|
|
<span class="ow">or</span> <span class="p">(</span><span class="n">ObjectDoesNotExist</span><span class="p">,),</span>
|
|
<span class="n">module</span><span class="p">,</span>
|
|
<span class="n">attached_to</span><span class="o">=</span><span class="n">new_class</span><span class="p">,</span>
|
|
<span class="p">),</span>
|
|
<span class="p">)</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">add_to_class</span><span class="p">(</span>
|
|
<span class="s2">"MultipleObjectsReturned"</span><span class="p">,</span>
|
|
<span class="n">subclass_exception</span><span class="p">(</span>
|
|
<span class="s2">"MultipleObjectsReturned"</span><span class="p">,</span>
|
|
<span class="nb">tuple</span><span class="p">(</span>
|
|
<span class="n">x</span><span class="o">.</span><span class="n">MultipleObjectsReturned</span>
|
|
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">parents</span>
|
|
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="s2">"_meta"</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">x</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">abstract</span>
|
|
<span class="p">)</span>
|
|
<span class="ow">or</span> <span class="p">(</span><span class="n">MultipleObjectsReturned</span><span class="p">,),</span>
|
|
<span class="n">module</span><span class="p">,</span>
|
|
<span class="n">attached_to</span><span class="o">=</span><span class="n">new_class</span><span class="p">,</span>
|
|
<span class="p">),</span>
|
|
<span class="p">)</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">add_to_class</span><span class="p">(</span>
|
|
<span class="s2">"NotUpdated"</span><span class="p">,</span>
|
|
<span class="n">subclass_exception</span><span class="p">(</span>
|
|
<span class="s2">"NotUpdated"</span><span class="p">,</span>
|
|
<span class="nb">tuple</span><span class="p">(</span>
|
|
<span class="n">x</span><span class="o">.</span><span class="n">NotUpdated</span>
|
|
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">parents</span>
|
|
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="s2">"_meta"</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">x</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">abstract</span>
|
|
<span class="p">)</span>
|
|
<span class="c1"># Subclass DatabaseError as well for backward compatibility</span>
|
|
<span class="c1"># reasons as __subclasshook__ is not taken into account on</span>
|
|
<span class="c1"># exception handling.</span>
|
|
<span class="ow">or</span> <span class="p">(</span><span class="n">ObjectNotUpdated</span><span class="p">,</span> <span class="n">DatabaseError</span><span class="p">),</span>
|
|
<span class="n">module</span><span class="p">,</span>
|
|
<span class="n">attached_to</span><span class="o">=</span><span class="n">new_class</span><span class="p">,</span>
|
|
<span class="p">),</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">base_meta</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">base_meta</span><span class="o">.</span><span class="n">abstract</span><span class="p">:</span>
|
|
<span class="c1"># Non-abstract child classes inherit some attributes from their</span>
|
|
<span class="c1"># non-abstract parent (unless an ABC comes before it in the</span>
|
|
<span class="c1"># method resolution order).</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">meta</span><span class="p">,</span> <span class="s2">"ordering"</span><span class="p">):</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">ordering</span> <span class="o">=</span> <span class="n">base_meta</span><span class="o">.</span><span class="n">ordering</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">meta</span><span class="p">,</span> <span class="s2">"get_latest_by"</span><span class="p">):</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">get_latest_by</span> <span class="o">=</span> <span class="n">base_meta</span><span class="o">.</span><span class="n">get_latest_by</span>
|
|
|
|
<span class="n">is_proxy</span> <span class="o">=</span> <span class="n">new_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">proxy</span>
|
|
|
|
<span class="c1"># If the model is a proxy, ensure that the base class</span>
|
|
<span class="c1"># hasn't been swapped out.</span>
|
|
<span class="k">if</span> <span class="n">is_proxy</span> <span class="ow">and</span> <span class="n">base_meta</span> <span class="ow">and</span> <span class="n">base_meta</span><span class="o">.</span><span class="n">swapped</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
|
<span class="s2">"</span><span class="si">%s</span><span class="s2"> cannot proxy the swapped model '</span><span class="si">%s</span><span class="s2">'."</span> <span class="o">%</span> <span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">base_meta</span><span class="o">.</span><span class="n">swapped</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="c1"># Add remaining attributes (those with a contribute_to_class() method)</span>
|
|
<span class="c1"># to the class.</span>
|
|
<span class="k">for</span> <span class="n">obj_name</span><span class="p">,</span> <span class="n">obj</span> <span class="ow">in</span> <span class="n">contributable_attrs</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">add_to_class</span><span class="p">(</span><span class="n">obj_name</span><span class="p">,</span> <span class="n">obj</span><span class="p">)</span>
|
|
|
|
<span class="c1"># All the fields of any type declared on this model</span>
|
|
<span class="n">new_fields</span> <span class="o">=</span> <span class="n">chain</span><span class="p">(</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_fields</span><span class="p">,</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_many_to_many</span><span class="p">,</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">private_fields</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="n">field_names</span> <span class="o">=</span> <span class="p">{</span><span class="n">f</span><span class="o">.</span><span class="n">name</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">new_fields</span><span class="p">}</span>
|
|
|
|
<span class="c1"># Basic setup for proxy models.</span>
|
|
<span class="k">if</span> <span class="n">is_proxy</span><span class="p">:</span>
|
|
<span class="n">base</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">for</span> <span class="n">parent</span> <span class="ow">in</span> <span class="p">[</span><span class="n">kls</span> <span class="k">for</span> <span class="n">kls</span> <span class="ow">in</span> <span class="n">parents</span> <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">kls</span><span class="p">,</span> <span class="s2">"_meta"</span><span class="p">)]:</span>
|
|
<span class="k">if</span> <span class="n">parent</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">abstract</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">parent</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">fields</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
|
<span class="s2">"Abstract base class containing model fields not "</span>
|
|
<span class="s2">"permitted for proxy model '</span><span class="si">%s</span><span class="s2">'."</span> <span class="o">%</span> <span class="n">name</span>
|
|
<span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="k">if</span> <span class="n">base</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">base</span> <span class="o">=</span> <span class="n">parent</span>
|
|
<span class="k">elif</span> <span class="n">parent</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_model</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">base</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_model</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
|
<span class="s2">"Proxy model '</span><span class="si">%s</span><span class="s2">' has more than one non-abstract model base "</span>
|
|
<span class="s2">"class."</span> <span class="o">%</span> <span class="n">name</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">base</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
|
<span class="s2">"Proxy model '</span><span class="si">%s</span><span class="s2">' has no non-abstract model base class."</span> <span class="o">%</span> <span class="n">name</span>
|
|
<span class="p">)</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">setup_proxy</span><span class="p">(</span><span class="n">base</span><span class="p">)</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_model</span> <span class="o">=</span> <span class="n">base</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_model</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_model</span> <span class="o">=</span> <span class="n">new_class</span>
|
|
|
|
<span class="c1"># Collect the parent links for multi-table inheritance.</span>
|
|
<span class="n">parent_links</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="k">for</span> <span class="n">base</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">([</span><span class="n">new_class</span><span class="p">,</span> <span class="o">*</span><span class="n">parents</span><span class="p">]):</span>
|
|
<span class="c1"># Conceptually equivalent to `if base is Model`.</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="s2">"_meta"</span><span class="p">):</span>
|
|
<span class="k">continue</span>
|
|
<span class="c1"># Skip concrete parent classes.</span>
|
|
<span class="k">if</span> <span class="n">base</span> <span class="o">!=</span> <span class="n">new_class</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">base</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">abstract</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="c1"># Locate OneToOneField instances.</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">base</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_fields</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">field</span><span class="p">,</span> <span class="n">OneToOneField</span><span class="p">)</span> <span class="ow">and</span> <span class="n">field</span><span class="o">.</span><span class="n">remote_field</span><span class="o">.</span><span class="n">parent_link</span><span class="p">:</span>
|
|
<span class="n">related</span> <span class="o">=</span> <span class="n">resolve_relation</span><span class="p">(</span><span class="n">new_class</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">remote_field</span><span class="o">.</span><span class="n">model</span><span class="p">)</span>
|
|
<span class="n">parent_links</span><span class="p">[</span><span class="n">make_model_tuple</span><span class="p">(</span><span class="n">related</span><span class="p">)]</span> <span class="o">=</span> <span class="n">field</span>
|
|
|
|
<span class="c1"># Track fields inherited from base models.</span>
|
|
<span class="n">inherited_attributes</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
|
|
<span class="c1"># Do the appropriate setup for any model parents.</span>
|
|
<span class="k">for</span> <span class="n">base</span> <span class="ow">in</span> <span class="n">new_class</span><span class="o">.</span><span class="n">mro</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="n">base</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">parents</span> <span class="ow">or</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="s2">"_meta"</span><span class="p">):</span>
|
|
<span class="c1"># Things without _meta aren't functional models, so they're</span>
|
|
<span class="c1"># uninteresting parents.</span>
|
|
<span class="n">inherited_attributes</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="vm">__dict__</span><span class="p">)</span>
|
|
<span class="k">continue</span>
|
|
|
|
<span class="n">parent_fields</span> <span class="o">=</span> <span class="n">base</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_fields</span> <span class="o">+</span> <span class="n">base</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_many_to_many</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">base</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">abstract</span><span class="p">:</span>
|
|
<span class="c1"># Check for clashes between locally declared fields and those</span>
|
|
<span class="c1"># on the base classes.</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">parent_fields</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">name</span> <span class="ow">in</span> <span class="n">field_names</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">FieldError</span><span class="p">(</span>
|
|
<span class="s2">"Local field </span><span class="si">%r</span><span class="s2"> in class </span><span class="si">%r</span><span class="s2"> clashes with field of "</span>
|
|
<span class="s2">"the same name from base class </span><span class="si">%r</span><span class="s2">."</span>
|
|
<span class="o">%</span> <span class="p">(</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
|
<span class="n">name</span><span class="p">,</span>
|
|
<span class="n">base</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">inherited_attributes</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Concrete classes...</span>
|
|
<span class="n">base</span> <span class="o">=</span> <span class="n">base</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_model</span>
|
|
<span class="n">base_key</span> <span class="o">=</span> <span class="n">make_model_tuple</span><span class="p">(</span><span class="n">base</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">base_key</span> <span class="ow">in</span> <span class="n">parent_links</span><span class="p">:</span>
|
|
<span class="n">field</span> <span class="o">=</span> <span class="n">parent_links</span><span class="p">[</span><span class="n">base_key</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="ow">not</span> <span class="n">is_proxy</span><span class="p">:</span>
|
|
<span class="n">attr_name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">_ptr"</span> <span class="o">%</span> <span class="n">base</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">model_name</span>
|
|
<span class="n">field</span> <span class="o">=</span> <span class="n">OneToOneField</span><span class="p">(</span>
|
|
<span class="n">base</span><span class="p">,</span>
|
|
<span class="n">on_delete</span><span class="o">=</span><span class="n">CASCADE</span><span class="p">,</span>
|
|
<span class="n">name</span><span class="o">=</span><span class="n">attr_name</span><span class="p">,</span>
|
|
<span class="n">auto_created</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
|
|
<span class="n">parent_link</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">attr_name</span> <span class="ow">in</span> <span class="n">field_names</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">FieldError</span><span class="p">(</span>
|
|
<span class="s2">"Auto-generated field '</span><span class="si">%s</span><span class="s2">' in class </span><span class="si">%r</span><span class="s2"> for "</span>
|
|
<span class="s2">"parent_link to base class </span><span class="si">%r</span><span class="s2"> clashes with "</span>
|
|
<span class="s2">"declared field of the same name."</span>
|
|
<span class="o">%</span> <span class="p">(</span>
|
|
<span class="n">attr_name</span><span class="p">,</span>
|
|
<span class="n">name</span><span class="p">,</span>
|
|
<span class="n">base</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="c1"># Only add the ptr field if it's not already present;</span>
|
|
<span class="c1"># e.g. migrations will already have it specified</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">new_class</span><span class="p">,</span> <span class="n">attr_name</span><span class="p">):</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">add_to_class</span><span class="p">(</span><span class="n">attr_name</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">field</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">parents</span><span class="p">[</span><span class="n">base</span><span class="p">]</span> <span class="o">=</span> <span class="n">field</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">base_parents</span> <span class="o">=</span> <span class="n">base</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">parents</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
|
|
|
|
<span class="c1"># Add fields from abstract base class if it wasn't overridden.</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">parent_fields</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="p">(</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">field_names</span>
|
|
<span class="ow">and</span> <span class="n">field</span><span class="o">.</span><span class="n">name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">new_class</span><span class="o">.</span><span class="vm">__dict__</span>
|
|
<span class="ow">and</span> <span class="n">field</span><span class="o">.</span><span class="n">name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">inherited_attributes</span>
|
|
<span class="p">):</span>
|
|
<span class="n">new_field</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="n">field</span><span class="p">)</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">add_to_class</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">new_field</span><span class="p">)</span>
|
|
<span class="c1"># Replace parent links defined on this base by the new</span>
|
|
<span class="c1"># field. It will be appropriately resolved if required.</span>
|
|
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">one_to_one</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">parent</span><span class="p">,</span> <span class="n">parent_link</span> <span class="ow">in</span> <span class="n">base_parents</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="n">field</span> <span class="o">==</span> <span class="n">parent_link</span><span class="p">:</span>
|
|
<span class="n">base_parents</span><span class="p">[</span><span class="n">parent</span><span class="p">]</span> <span class="o">=</span> <span class="n">new_field</span>
|
|
|
|
<span class="c1"># Pass any non-abstract parent classes onto child.</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">parents</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">base_parents</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Inherit private fields (like GenericForeignKey) from the parent</span>
|
|
<span class="c1"># class if they are not overridden.</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">base</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">private_fields</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">name</span> <span class="ow">in</span> <span class="n">field_names</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">base</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">abstract</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">FieldError</span><span class="p">(</span>
|
|
<span class="s2">"Local field </span><span class="si">%r</span><span class="s2"> in class </span><span class="si">%r</span><span class="s2"> clashes with field of "</span>
|
|
<span class="s2">"the same name from base class </span><span class="si">%r</span><span class="s2">."</span>
|
|
<span class="o">%</span> <span class="p">(</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
|
<span class="n">name</span><span class="p">,</span>
|
|
<span class="n">base</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="p">(</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">new_class</span><span class="o">.</span><span class="vm">__dict__</span>
|
|
<span class="ow">and</span> <span class="n">field</span><span class="o">.</span><span class="n">name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">inherited_attributes</span>
|
|
<span class="p">):</span>
|
|
<span class="n">field</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="n">field</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">base</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">abstract</span><span class="p">:</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">mti_inherited</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">add_to_class</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Copy indexes so that index names are unique when models extend an</span>
|
|
<span class="c1"># abstract model.</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">indexes</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="n">idx</span><span class="p">)</span> <span class="k">for</span> <span class="n">idx</span> <span class="ow">in</span> <span class="n">new_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">indexes</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="k">if</span> <span class="n">abstract</span><span class="p">:</span>
|
|
<span class="c1"># Abstract base models can't be instantiated and don't appear in</span>
|
|
<span class="c1"># the list of models for an app. We do the final setup for them a</span>
|
|
<span class="c1"># little differently from normal models.</span>
|
|
<span class="n">attr_meta</span><span class="o">.</span><span class="n">abstract</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">Meta</span> <span class="o">=</span> <span class="n">attr_meta</span>
|
|
<span class="k">return</span> <span class="n">new_class</span>
|
|
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">_prepare</span><span class="p">()</span>
|
|
<span class="n">new_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">apps</span><span class="o">.</span><span class="n">register_model</span><span class="p">(</span><span class="n">new_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">app_label</span><span class="p">,</span> <span class="n">new_class</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">new_class</span>
|
|
|
|
<div class="viewcode-block" id="ModelBase.add_to_class">
|
|
<a class="viewcode-back" href="../../../../api/evennia.typeclasses.models.html#evennia.typeclasses.models.ModelBase.add_to_class">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">add_to_class</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">_has_contribute_to_class</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
|
|
<span class="n">value</span><span class="o">.</span><span class="n">contribute_to_class</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span></div>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_prepare</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Create some methods once self._meta has been populated."""</span>
|
|
<span class="n">opts</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span>
|
|
<span class="n">opts</span><span class="o">.</span><span class="n">_prepare</span><span class="p">(</span><span class="bp">cls</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">opts</span><span class="o">.</span><span class="n">order_with_respect_to</span><span class="p">:</span>
|
|
<span class="bp">cls</span><span class="o">.</span><span class="n">get_next_in_order</span> <span class="o">=</span> <span class="n">partialmethod</span><span class="p">(</span>
|
|
<span class="bp">cls</span><span class="o">.</span><span class="n">_get_next_or_previous_in_order</span><span class="p">,</span> <span class="n">is_next</span><span class="o">=</span><span class="kc">True</span>
|
|
<span class="p">)</span>
|
|
<span class="bp">cls</span><span class="o">.</span><span class="n">get_previous_in_order</span> <span class="o">=</span> <span class="n">partialmethod</span><span class="p">(</span>
|
|
<span class="bp">cls</span><span class="o">.</span><span class="n">_get_next_or_previous_in_order</span><span class="p">,</span> <span class="n">is_next</span><span class="o">=</span><span class="kc">False</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="c1"># Defer creating accessors on the foreign class until it has been</span>
|
|
<span class="c1"># created and registered. If remote_field is None, we're ordering</span>
|
|
<span class="c1"># with respect to a GenericForeignKey and don't know what the</span>
|
|
<span class="c1"># foreign class is - we'll add those accessors later in</span>
|
|
<span class="c1"># contribute_to_class().</span>
|
|
<span class="k">if</span> <span class="n">opts</span><span class="o">.</span><span class="n">order_with_respect_to</span><span class="o">.</span><span class="n">remote_field</span><span class="p">:</span>
|
|
<span class="n">wrt</span> <span class="o">=</span> <span class="n">opts</span><span class="o">.</span><span class="n">order_with_respect_to</span>
|
|
<span class="n">remote</span> <span class="o">=</span> <span class="n">wrt</span><span class="o">.</span><span class="n">remote_field</span><span class="o">.</span><span class="n">model</span>
|
|
<span class="n">lazy_related_operation</span><span class="p">(</span><span class="n">make_foreign_order_accessors</span><span class="p">,</span> <span class="bp">cls</span><span class="p">,</span> <span class="n">remote</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Give the class a docstring -- its definition.</span>
|
|
<span class="k">if</span> <span class="bp">cls</span><span class="o">.</span><span class="vm">__doc__</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="bp">cls</span><span class="o">.</span><span class="vm">__doc__</span> <span class="o">=</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">(</span><span class="si">%s</span><span class="s2">)"</span> <span class="o">%</span> <span class="p">(</span>
|
|
<span class="bp">cls</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span>
|
|
<span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">name</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">opts</span><span class="o">.</span><span class="n">fields</span><span class="p">),</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="n">get_absolute_url_override</span> <span class="o">=</span> <span class="n">settings</span><span class="o">.</span><span class="n">ABSOLUTE_URL_OVERRIDES</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
|
|
<span class="n">opts</span><span class="o">.</span><span class="n">label_lower</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">get_absolute_url_override</span><span class="p">:</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="s2">"get_absolute_url"</span><span class="p">,</span> <span class="n">get_absolute_url_override</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">opts</span><span class="o">.</span><span class="n">managers</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="nb">any</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s2">"objects"</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">opts</span><span class="o">.</span><span class="n">fields</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
|
<span class="s2">"Model </span><span class="si">%s</span><span class="s2"> must specify a custom Manager, because it has a "</span>
|
|
<span class="s2">"field named 'objects'."</span> <span class="o">%</span> <span class="bp">cls</span><span class="o">.</span><span class="vm">__name__</span>
|
|
<span class="p">)</span>
|
|
<span class="n">manager</span> <span class="o">=</span> <span class="n">Manager</span><span class="p">()</span>
|
|
<span class="n">manager</span><span class="o">.</span><span class="n">auto_created</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="bp">cls</span><span class="o">.</span><span class="n">add_to_class</span><span class="p">(</span><span class="s2">"objects"</span><span class="p">,</span> <span class="n">manager</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Set the name of _meta.indexes. This can't be done in</span>
|
|
<span class="c1"># Options.contribute_to_class() because fields haven't been added to</span>
|
|
<span class="c1"># the model at that point.</span>
|
|
<span class="k">for</span> <span class="n">index</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">indexes</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">index</span><span class="o">.</span><span class="n">name</span><span class="p">:</span>
|
|
<span class="n">index</span><span class="o">.</span><span class="n">set_name_with_model</span><span class="p">(</span><span class="bp">cls</span><span class="p">)</span>
|
|
|
|
<span class="n">class_prepared</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">sender</span><span class="o">=</span><span class="bp">cls</span><span class="p">)</span>
|
|
|
|
<span class="nd">@property</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_base_manager</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">base_manager</span>
|
|
|
|
<span class="nd">@property</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_default_manager</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">default_manager</span></div>
|
|
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">ModelStateFieldsCacheDescriptor</span><span class="p">:</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__get__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">instance</span><span class="p">,</span> <span class="bp">cls</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">instance</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="bp">self</span>
|
|
<span class="n">res</span> <span class="o">=</span> <span class="n">instance</span><span class="o">.</span><span class="n">fields_cache</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="k">return</span> <span class="n">res</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">ModelState</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""Store model instance state."""</span>
|
|
|
|
<span class="n">db</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="c1"># If true, uniqueness validation checks will consider this a new, unsaved</span>
|
|
<span class="c1"># object. Necessary for correct validation of new instances of objects with</span>
|
|
<span class="c1"># explicit (non-auto) PKs. This impacts validation only; it has no effect</span>
|
|
<span class="c1"># on the actual save.</span>
|
|
<span class="n">adding</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">fields_cache</span> <span class="o">=</span> <span class="n">ModelStateFieldsCacheDescriptor</span><span class="p">()</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">Model</span><span class="p">(</span><span class="n">AltersData</span><span class="p">,</span> <span class="n">metaclass</span><span class="o">=</span><span class="n">ModelBase</span><span class="p">):</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="c1"># Alias some things as locals to avoid repeat global lookups</span>
|
|
<span class="bp">cls</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span>
|
|
<span class="n">opts</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span>
|
|
<span class="n">_setattr</span> <span class="o">=</span> <span class="nb">setattr</span>
|
|
<span class="n">_DEFERRED</span> <span class="o">=</span> <span class="n">DEFERRED</span>
|
|
<span class="k">if</span> <span class="n">opts</span><span class="o">.</span><span class="n">abstract</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">"Abstract models cannot be instantiated."</span><span class="p">)</span>
|
|
|
|
<span class="n">pre_init</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">sender</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="o">=</span><span class="n">kwargs</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Set up the storage for instance state</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_state</span> <span class="o">=</span> <span class="n">ModelState</span><span class="p">()</span>
|
|
|
|
<span class="c1"># There is a rather weird disparity here; if kwargs, it's set, then</span>
|
|
<span class="c1"># args overrides it. It should be one or the other; don't duplicate the</span>
|
|
<span class="c1"># work The reason for the kwargs check is that standard iterator passes</span>
|
|
<span class="c1"># in by args, and instantiation for iteration is 33% faster.</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">)</span> <span class="o">></span> <span class="nb">len</span><span class="p">(</span><span class="n">opts</span><span class="o">.</span><span class="n">concrete_fields</span><span class="p">):</span>
|
|
<span class="c1"># Daft, but matches old exception sans the err msg.</span>
|
|
<span class="k">raise</span> <span class="ne">IndexError</span><span class="p">(</span><span class="s2">"Number of args exceeds number of fields"</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">kwargs</span><span class="p">:</span>
|
|
<span class="n">fields_iter</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">opts</span><span class="o">.</span><span class="n">concrete_fields</span><span class="p">)</span>
|
|
<span class="c1"># The ordering of the zip calls matter - zip throws StopIteration</span>
|
|
<span class="c1"># when an iter throws it. So if the first iter throws it, the</span>
|
|
<span class="c1"># second is *not* consumed. We rely on this, so don't change the</span>
|
|
<span class="c1"># order without changing the logic.</span>
|
|
<span class="k">for</span> <span class="n">val</span><span class="p">,</span> <span class="n">field</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">fields_iter</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">val</span> <span class="ow">is</span> <span class="n">_DEFERRED</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="n">_setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">,</span> <span class="n">val</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># Slower, kwargs-ready version.</span>
|
|
<span class="n">fields_iter</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">opts</span><span class="o">.</span><span class="n">fields</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">val</span><span class="p">,</span> <span class="n">field</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">fields_iter</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">val</span> <span class="ow">is</span> <span class="n">_DEFERRED</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="n">_setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">,</span> <span class="n">val</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">NOT_PROVIDED</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">NOT_PROVIDED</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="bp">cls</span><span class="o">.</span><span class="vm">__qualname__</span><span class="si">}</span><span class="s2">() got both positional and "</span>
|
|
<span class="sa">f</span><span class="s2">"keyword arguments for field '</span><span class="si">{</span><span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">'."</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="c1"># Now we're left with the unprocessed fields that *must* come from</span>
|
|
<span class="c1"># keywords, or default.</span>
|
|
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">fields_iter</span><span class="p">:</span>
|
|
<span class="n">is_related_object</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="c1"># Virtual field</span>
|
|
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">column</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">field</span><span class="o">.</span><span class="n">generated</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="k">if</span> <span class="n">kwargs</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">remote_field</span><span class="p">,</span> <span class="n">ForeignObjectRel</span><span class="p">):</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="c1"># Assume object instance was passed in.</span>
|
|
<span class="n">rel_obj</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
|
|
<span class="n">is_related_object</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="c1"># Object instance wasn't passed in -- must be an</span>
|
|
<span class="c1"># ID.</span>
|
|
<span class="n">val</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
|
<span class="n">val</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">get_default</span><span class="p">()</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">val</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
|
<span class="c1"># This is done with an exception rather than the</span>
|
|
<span class="c1"># default argument on pop because we don't want</span>
|
|
<span class="c1"># get_default() to be evaluated, and then not used.</span>
|
|
<span class="c1"># Refs #12057.</span>
|
|
<span class="n">val</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">get_default</span><span class="p">()</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">val</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">get_default</span><span class="p">()</span>
|
|
|
|
<span class="k">if</span> <span class="n">is_related_object</span><span class="p">:</span>
|
|
<span class="c1"># If we are passed a related instance, set it using the</span>
|
|
<span class="c1"># field.name instead of field.attname (e.g. "user" instead of</span>
|
|
<span class="c1"># "user_id") so that the object gets properly cached (and type</span>
|
|
<span class="c1"># checked) by the RelatedObjectDescriptor.</span>
|
|
<span class="k">if</span> <span class="n">rel_obj</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">_DEFERRED</span><span class="p">:</span>
|
|
<span class="n">_setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">rel_obj</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">val</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">_DEFERRED</span><span class="p">:</span>
|
|
<span class="n">_setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">,</span> <span class="n">val</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">kwargs</span><span class="p">:</span>
|
|
<span class="n">property_names</span> <span class="o">=</span> <span class="n">opts</span><span class="o">.</span><span class="n">_property_names</span>
|
|
<span class="n">unexpected</span> <span class="o">=</span> <span class="p">()</span>
|
|
<span class="k">for</span> <span class="n">prop</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
<span class="c1"># Any remaining kwargs must correspond to properties or virtual</span>
|
|
<span class="c1"># fields.</span>
|
|
<span class="k">if</span> <span class="n">prop</span> <span class="ow">in</span> <span class="n">property_names</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">value</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">_DEFERRED</span><span class="p">:</span>
|
|
<span class="n">_setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">prop</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">opts</span><span class="o">.</span><span class="n">get_field</span><span class="p">(</span><span class="n">prop</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">FieldDoesNotExist</span><span class="p">:</span>
|
|
<span class="n">unexpected</span> <span class="o">+=</span> <span class="p">(</span><span class="n">prop</span><span class="p">,)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">value</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">_DEFERRED</span><span class="p">:</span>
|
|
<span class="n">_setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">prop</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">unexpected</span><span class="p">:</span>
|
|
<span class="n">unexpected_names</span> <span class="o">=</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">unexpected</span><span class="p">)</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="bp">cls</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2">() got unexpected keyword arguments: "</span>
|
|
<span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">unexpected_names</span><span class="si">}</span><span class="s2">"</span>
|
|
<span class="p">)</span>
|
|
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">()</span>
|
|
<span class="n">post_init</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">sender</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span> <span class="n">instance</span><span class="o">=</span><span class="bp">self</span><span class="p">)</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">from_db</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">db</span><span class="p">,</span> <span class="n">field_names</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">values</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">len</span><span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_fields</span><span class="p">):</span>
|
|
<span class="n">values_iter</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="nb">next</span><span class="p">(</span><span class="n">values_iter</span><span class="p">)</span> <span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">attname</span> <span class="ow">in</span> <span class="n">field_names</span> <span class="k">else</span> <span class="n">DEFERRED</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_fields</span>
|
|
<span class="p">]</span>
|
|
<span class="n">new</span> <span class="o">=</span> <span class="bp">cls</span><span class="p">(</span><span class="o">*</span><span class="n">values</span><span class="p">)</span>
|
|
<span class="n">new</span><span class="o">.</span><span class="n">_state</span><span class="o">.</span><span class="n">adding</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">new</span><span class="o">.</span><span class="n">_state</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="n">db</span>
|
|
<span class="k">return</span> <span class="n">new</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="s2">"<</span><span class="si">%s</span><span class="s2">: </span><span class="si">%s</span><span class="s2">>"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="s2">"</span><span class="si">%s</span><span class="s2"> object (</span><span class="si">%s</span><span class="s2">)"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pk</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">Model</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="bp">NotImplemented</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_model</span> <span class="o">!=</span> <span class="n">other</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_model</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="kc">False</span>
|
|
<span class="n">my_pk</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">pk</span>
|
|
<span class="k">if</span> <span class="n">my_pk</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="bp">self</span> <span class="ow">is</span> <span class="n">other</span>
|
|
<span class="k">return</span> <span class="n">my_pk</span> <span class="o">==</span> <span class="n">other</span><span class="o">.</span><span class="n">pk</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__hash__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_pk_set</span><span class="p">():</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">"Model instances without primary key value are unhashable"</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="nb">hash</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pk</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">__reduce__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__getstate__</span><span class="p">()</span>
|
|
<span class="n">data</span><span class="p">[</span><span class="n">DJANGO_VERSION_PICKLE_KEY</span><span class="p">]</span> <span class="o">=</span> <span class="n">django</span><span class="o">.</span><span class="n">__version__</span>
|
|
<span class="n">class_id</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">app_label</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">object_name</span>
|
|
<span class="k">return</span> <span class="n">model_unpickle</span><span class="p">,</span> <span class="p">(</span><span class="n">class_id</span><span class="p">,),</span> <span class="n">data</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">__getstate__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Hook to allow choosing the attributes to pickle."""</span>
|
|
<span class="n">state</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
|
|
<span class="n">state</span><span class="p">[</span><span class="s2">"_state"</span><span class="p">]</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">state</span><span class="p">[</span><span class="s2">"_state"</span><span class="p">])</span>
|
|
<span class="n">state</span><span class="p">[</span><span class="s2">"_state"</span><span class="p">]</span><span class="o">.</span><span class="n">fields_cache</span> <span class="o">=</span> <span class="n">state</span><span class="p">[</span><span class="s2">"_state"</span><span class="p">]</span><span class="o">.</span><span class="n">fields_cache</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
|
|
<span class="c1"># memoryview cannot be pickled, so cast it to bytes and store</span>
|
|
<span class="c1"># separately.</span>
|
|
<span class="n">_memoryview_attrs</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">attr</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">state</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="nb">memoryview</span><span class="p">):</span>
|
|
<span class="n">_memoryview_attrs</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">attr</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">(</span><span class="n">value</span><span class="p">)))</span>
|
|
<span class="k">if</span> <span class="n">_memoryview_attrs</span><span class="p">:</span>
|
|
<span class="n">state</span><span class="p">[</span><span class="s2">"_memoryview_attrs"</span><span class="p">]</span> <span class="o">=</span> <span class="n">_memoryview_attrs</span>
|
|
<span class="k">for</span> <span class="n">attr</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">_memoryview_attrs</span><span class="p">:</span>
|
|
<span class="n">state</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">attr</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">state</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">__setstate__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">state</span><span class="p">):</span>
|
|
<span class="n">pickled_version</span> <span class="o">=</span> <span class="n">state</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">DJANGO_VERSION_PICKLE_KEY</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">pickled_version</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">pickled_version</span> <span class="o">!=</span> <span class="n">django</span><span class="o">.</span><span class="n">__version__</span><span class="p">:</span>
|
|
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span>
|
|
<span class="s2">"Pickled model instance's Django version </span><span class="si">%s</span><span class="s2"> does not "</span>
|
|
<span class="s2">"match the current version </span><span class="si">%s</span><span class="s2">."</span>
|
|
<span class="o">%</span> <span class="p">(</span><span class="n">pickled_version</span><span class="p">,</span> <span class="n">django</span><span class="o">.</span><span class="n">__version__</span><span class="p">),</span>
|
|
<span class="ne">RuntimeWarning</span><span class="p">,</span>
|
|
<span class="n">stacklevel</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span>
|
|
<span class="s2">"Pickled model instance's Django version is not specified."</span><span class="p">,</span>
|
|
<span class="ne">RuntimeWarning</span><span class="p">,</span>
|
|
<span class="n">stacklevel</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="s2">"_memoryview_attrs"</span> <span class="ow">in</span> <span class="n">state</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">attr</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">state</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">"_memoryview_attrs"</span><span class="p">):</span>
|
|
<span class="n">state</span><span class="p">[</span><span class="n">attr</span><span class="p">]</span> <span class="o">=</span> <span class="nb">memoryview</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">state</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_get_pk_val</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">meta</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="n">meta</span> <span class="o">=</span> <span class="n">meta</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span>
|
|
<span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">meta</span><span class="o">.</span><span class="n">pk</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_set_pk_val</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
|
|
<span class="k">for</span> <span class="n">parent_link</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">parents</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="n">parent_link</span> <span class="ow">and</span> <span class="n">parent_link</span> <span class="o">!=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">pk</span><span class="p">:</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">parent_link</span><span class="o">.</span><span class="n">target_field</span><span class="o">.</span><span class="n">attname</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">pk</span><span class="o">.</span><span class="n">attname</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
|
|
|
|
<span class="n">pk</span> <span class="o">=</span> <span class="nb">property</span><span class="p">(</span><span class="n">_get_pk_val</span><span class="p">,</span> <span class="n">_set_pk_val</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_is_pk_set</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">meta</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="n">pk_val</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_pk_val</span><span class="p">(</span><span class="n">meta</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="ow">not</span> <span class="p">(</span>
|
|
<span class="n">pk_val</span> <span class="ow">is</span> <span class="kc">None</span>
|
|
<span class="ow">or</span> <span class="p">(</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">pk_val</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">)</span> <span class="ow">and</span> <span class="nb">any</span><span class="p">(</span><span class="n">f</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">pk_val</span><span class="p">))</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">get_deferred_fields</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Return a set containing names of deferred fields for this instance.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">return</span> <span class="p">{</span>
|
|
<span class="n">f</span><span class="o">.</span><span class="n">attname</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_fields</span>
|
|
<span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">attname</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__dict__</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">refresh_from_db</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">from_queryset</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Reload field values from the database.</span>
|
|
|
|
<span class="sd"> By default, the reloading happens from the database this instance was</span>
|
|
<span class="sd"> loaded from, or by the read router if this instance wasn't loaded from</span>
|
|
<span class="sd"> any database. The using parameter will override the default.</span>
|
|
|
|
<span class="sd"> Fields can be used to specify which fields to reload. The fields</span>
|
|
<span class="sd"> should be an iterable of field attnames. If fields is None, then</span>
|
|
<span class="sd"> all non-deferred fields are reloaded.</span>
|
|
|
|
<span class="sd"> When accessing deferred fields of an instance, the deferred loading</span>
|
|
<span class="sd"> of the field will call this method.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="n">fields</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_prefetched_objects_cache</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">prefetched_objects_cache</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"_prefetched_objects_cache"</span><span class="p">,</span> <span class="p">())</span>
|
|
<span class="n">fields</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">fields</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">fields</span><span class="o">.</span><span class="n">copy</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">prefetched_objects_cache</span><span class="p">:</span>
|
|
<span class="k">del</span> <span class="n">prefetched_objects_cache</span><span class="p">[</span><span class="n">field</span><span class="p">]</span>
|
|
<span class="n">fields</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">field</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">fields</span><span class="p">:</span>
|
|
<span class="k">return</span>
|
|
<span class="k">if</span> <span class="nb">any</span><span class="p">(</span><span class="n">LOOKUP_SEP</span> <span class="ow">in</span> <span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">fields</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
|
<span class="s1">'Found "</span><span class="si">%s</span><span class="s1">" in fields argument. Relations and transforms '</span>
|
|
<span class="s2">"are not allowed in fields."</span> <span class="o">%</span> <span class="n">LOOKUP_SEP</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">from_queryset</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">hints</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"instance"</span><span class="p">:</span> <span class="bp">self</span><span class="p">}</span>
|
|
<span class="n">from_queryset</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="n">_base_manager</span><span class="o">.</span><span class="n">db_manager</span><span class="p">(</span><span class="n">using</span><span class="p">,</span> <span class="n">hints</span><span class="o">=</span><span class="n">hints</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">using</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">from_queryset</span> <span class="o">=</span> <span class="n">from_queryset</span><span class="o">.</span><span class="n">using</span><span class="p">(</span><span class="n">using</span><span class="p">)</span>
|
|
|
|
<span class="n">db_instance_qs</span> <span class="o">=</span> <span class="n">from_queryset</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">pk</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">pk</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Use provided fields, if not set then reload all non-deferred fields.</span>
|
|
<span class="n">deferred_fields</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_deferred_fields</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="n">fields</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">db_instance_qs</span> <span class="o">=</span> <span class="n">db_instance_qs</span><span class="o">.</span><span class="n">only</span><span class="p">(</span><span class="o">*</span><span class="n">fields</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">deferred_fields</span><span class="p">:</span>
|
|
<span class="n">db_instance_qs</span> <span class="o">=</span> <span class="n">db_instance_qs</span><span class="o">.</span><span class="n">only</span><span class="p">(</span>
|
|
<span class="o">*</span><span class="p">{</span>
|
|
<span class="n">f</span><span class="o">.</span><span class="n">attname</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_fields</span>
|
|
<span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">attname</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">deferred_fields</span>
|
|
<span class="p">}</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="n">db_instance</span> <span class="o">=</span> <span class="n">db_instance_qs</span><span class="o">.</span><span class="n">get</span><span class="p">()</span>
|
|
<span class="n">non_loaded_fields</span> <span class="o">=</span> <span class="n">db_instance</span><span class="o">.</span><span class="n">get_deferred_fields</span><span class="p">()</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">fields</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span> <span class="ow">in</span> <span class="n">non_loaded_fields</span><span class="p">:</span>
|
|
<span class="c1"># This field wasn't refreshed - skip ahead.</span>
|
|
<span class="k">continue</span>
|
|
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">concrete</span><span class="p">:</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">,</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">db_instance</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">))</span>
|
|
<span class="c1"># Clear or copy cached foreign keys.</span>
|
|
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">is_relation</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">is_cached</span><span class="p">(</span><span class="n">db_instance</span><span class="p">):</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">set_cached_value</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">get_cached_value</span><span class="p">(</span><span class="n">db_instance</span><span class="p">))</span>
|
|
<span class="k">elif</span> <span class="n">field</span><span class="o">.</span><span class="n">is_cached</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">delete_cached_value</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Clear cached relations.</span>
|
|
<span class="k">for</span> <span class="n">rel</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">related_objects</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">fields</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">rel</span><span class="o">.</span><span class="n">name</span> <span class="ow">in</span> <span class="n">fields</span><span class="p">)</span> <span class="ow">and</span> <span class="n">rel</span><span class="o">.</span><span class="n">is_cached</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="n">rel</span><span class="o">.</span><span class="n">delete_cached_value</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Clear cached private relations.</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">private_fields</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="p">(</span>
|
|
<span class="p">(</span><span class="n">fields</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">field</span><span class="o">.</span><span class="n">name</span> <span class="ow">in</span> <span class="n">fields</span><span class="p">)</span>
|
|
<span class="ow">and</span> <span class="n">field</span><span class="o">.</span><span class="n">is_relation</span>
|
|
<span class="ow">and</span> <span class="n">field</span><span class="o">.</span><span class="n">is_cached</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="p">):</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">delete_cached_value</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_state</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="n">db_instance</span><span class="o">.</span><span class="n">_state</span><span class="o">.</span><span class="n">db</span>
|
|
|
|
<span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">arefresh_from_db</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">from_queryset</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="k">await</span> <span class="n">sync_to_async</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">refresh_from_db</span><span class="p">)(</span>
|
|
<span class="n">using</span><span class="o">=</span><span class="n">using</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="n">fields</span><span class="p">,</span> <span class="n">from_queryset</span><span class="o">=</span><span class="n">from_queryset</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">serializable_value</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field_name</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Return the value of the field name for this instance. If the field is</span>
|
|
<span class="sd"> a foreign key, return the id value instead of the object. If there's</span>
|
|
<span class="sd"> no Field object with this name on the model, return the model</span>
|
|
<span class="sd"> attribute's value.</span>
|
|
|
|
<span class="sd"> Used to serialize a field's value (in the serializer, or form output,</span>
|
|
<span class="sd"> for example). Normally, you would just access the attribute directly</span>
|
|
<span class="sd"> and not use this method.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">field</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">get_field</span><span class="p">(</span><span class="n">field_name</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">FieldDoesNotExist</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field_name</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">save</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="o">*</span><span class="p">,</span>
|
|
<span class="n">force_insert</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">force_update</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">update_fields</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Save the current instance. Override this in a subclass if you want to</span>
|
|
<span class="sd"> control the saving process.</span>
|
|
|
|
<span class="sd"> The 'force_insert' and 'force_update' parameters can be used to insist</span>
|
|
<span class="sd"> that the "save" must be an SQL insert or update (or equivalent for</span>
|
|
<span class="sd"> non-SQL backends), respectively. Normally, they should not be set.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_prepare_related_fields_for_save</span><span class="p">(</span><span class="n">operation_name</span><span class="o">=</span><span class="s2">"save"</span><span class="p">)</span>
|
|
|
|
<span class="n">using</span> <span class="o">=</span> <span class="n">using</span> <span class="ow">or</span> <span class="n">router</span><span class="o">.</span><span class="n">db_for_write</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">,</span> <span class="n">instance</span><span class="o">=</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">force_insert</span> <span class="ow">and</span> <span class="p">(</span><span class="n">force_update</span> <span class="ow">or</span> <span class="n">update_fields</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Cannot force both insert and updating in model saving."</span><span class="p">)</span>
|
|
|
|
<span class="n">deferred_non_generated_fields</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="n">f</span><span class="o">.</span><span class="n">attname</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_fields</span>
|
|
<span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">attname</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__dict__</span> <span class="ow">and</span> <span class="n">f</span><span class="o">.</span><span class="n">generated</span> <span class="ow">is</span> <span class="kc">False</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span> <span class="n">update_fields</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># If update_fields is empty, skip the save. We do also check for</span>
|
|
<span class="c1"># no-op saves later on for inheritance cases. This bailout is</span>
|
|
<span class="c1"># still needed for skipping signal sending.</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">update_fields</span><span class="p">:</span>
|
|
<span class="k">return</span>
|
|
|
|
<span class="n">update_fields</span> <span class="o">=</span> <span class="nb">frozenset</span><span class="p">(</span><span class="n">update_fields</span><span class="p">)</span>
|
|
<span class="n">field_names</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">_non_pk_concrete_field_names</span>
|
|
<span class="n">not_updatable_fields</span> <span class="o">=</span> <span class="n">update_fields</span><span class="o">.</span><span class="n">difference</span><span class="p">(</span><span class="n">field_names</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">not_updatable_fields</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
|
<span class="s2">"The following fields do not exist in this model, are m2m "</span>
|
|
<span class="s2">"fields, primary keys, or are non-concrete fields: </span><span class="si">%s</span><span class="s2">"</span>
|
|
<span class="o">%</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">not_updatable_fields</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="c1"># If saving to the same database, and this model is deferred, then</span>
|
|
<span class="c1"># automatically do an "update_fields" save on the loaded fields.</span>
|
|
<span class="k">elif</span> <span class="p">(</span>
|
|
<span class="ow">not</span> <span class="n">force_insert</span>
|
|
<span class="ow">and</span> <span class="n">deferred_non_generated_fields</span>
|
|
<span class="ow">and</span> <span class="n">using</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">_state</span><span class="o">.</span><span class="n">db</span>
|
|
<span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_pk_set</span><span class="p">()</span>
|
|
<span class="p">):</span>
|
|
<span class="n">field_names</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
|
|
<span class="n">pk_fields</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">pk_fields</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_fields</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">field</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">pk_fields</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">field</span><span class="p">,</span> <span class="s2">"through"</span><span class="p">):</span>
|
|
<span class="n">field_names</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span>
|
|
<span class="n">loaded_fields</span> <span class="o">=</span> <span class="n">field_names</span><span class="o">.</span><span class="n">difference</span><span class="p">(</span><span class="n">deferred_non_generated_fields</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">loaded_fields</span><span class="p">:</span>
|
|
<span class="n">update_fields</span> <span class="o">=</span> <span class="nb">frozenset</span><span class="p">(</span><span class="n">loaded_fields</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">save_base</span><span class="p">(</span>
|
|
<span class="n">using</span><span class="o">=</span><span class="n">using</span><span class="p">,</span>
|
|
<span class="n">force_insert</span><span class="o">=</span><span class="n">force_insert</span><span class="p">,</span>
|
|
<span class="n">force_update</span><span class="o">=</span><span class="n">force_update</span><span class="p">,</span>
|
|
<span class="n">update_fields</span><span class="o">=</span><span class="n">update_fields</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="n">save</span><span class="o">.</span><span class="n">alters_data</span> <span class="o">=</span> <span class="kc">True</span>
|
|
|
|
<span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">asave</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="o">*</span><span class="p">,</span>
|
|
<span class="n">force_insert</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">force_update</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">update_fields</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="p">):</span>
|
|
<span class="k">return</span> <span class="k">await</span> <span class="n">sync_to_async</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">save</span><span class="p">)(</span>
|
|
<span class="n">force_insert</span><span class="o">=</span><span class="n">force_insert</span><span class="p">,</span>
|
|
<span class="n">force_update</span><span class="o">=</span><span class="n">force_update</span><span class="p">,</span>
|
|
<span class="n">using</span><span class="o">=</span><span class="n">using</span><span class="p">,</span>
|
|
<span class="n">update_fields</span><span class="o">=</span><span class="n">update_fields</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="n">asave</span><span class="o">.</span><span class="n">alters_data</span> <span class="o">=</span> <span class="kc">True</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_validate_force_insert</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">force_insert</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">force_insert</span> <span class="ow">is</span> <span class="kc">False</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">()</span>
|
|
<span class="k">if</span> <span class="n">force_insert</span> <span class="ow">is</span> <span class="kc">True</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">(</span><span class="bp">cls</span><span class="p">,)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">force_insert</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">"force_insert must be a bool or tuple."</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">member</span> <span class="ow">in</span> <span class="n">force_insert</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">member</span><span class="p">,</span> <span class="n">ModelBase</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"Invalid force_insert member. </span><span class="si">{</span><span class="n">member</span><span class="si">!r}</span><span class="s2"> must be a model subclass."</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">issubclass</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">member</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"Invalid force_insert member. </span><span class="si">{</span><span class="n">member</span><span class="o">.</span><span class="vm">__qualname__</span><span class="si">}</span><span class="s2"> must be a "</span>
|
|
<span class="sa">f</span><span class="s2">"base of </span><span class="si">{</span><span class="bp">cls</span><span class="o">.</span><span class="vm">__qualname__</span><span class="si">}</span><span class="s2">."</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">force_insert</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">save_base</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">raw</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">force_insert</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">force_update</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">update_fields</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Handle the parts of saving which should be done only once per save,</span>
|
|
<span class="sd"> yet need to be done in raw saves, too. This includes some sanity</span>
|
|
<span class="sd"> checks and signal sending.</span>
|
|
|
|
<span class="sd"> The 'raw' argument is telling save_base not to save any parent</span>
|
|
<span class="sd"> models and not to do any changes to the values before save. This</span>
|
|
<span class="sd"> is used by fixture loading.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">using</span> <span class="o">=</span> <span class="n">using</span> <span class="ow">or</span> <span class="n">router</span><span class="o">.</span><span class="n">db_for_write</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">,</span> <span class="n">instance</span><span class="o">=</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="k">assert</span> <span class="ow">not</span> <span class="p">(</span><span class="n">force_insert</span> <span class="ow">and</span> <span class="p">(</span><span class="n">force_update</span> <span class="ow">or</span> <span class="n">update_fields</span><span class="p">))</span>
|
|
<span class="k">assert</span> <span class="n">update_fields</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">update_fields</span>
|
|
<span class="bp">cls</span> <span class="o">=</span> <span class="n">origin</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span>
|
|
<span class="c1"># Skip proxies, but keep the origin as the proxy model.</span>
|
|
<span class="k">if</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">proxy</span><span class="p">:</span>
|
|
<span class="bp">cls</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_model</span>
|
|
<span class="n">meta</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">meta</span><span class="o">.</span><span class="n">auto_created</span><span class="p">:</span>
|
|
<span class="n">pre_save</span><span class="o">.</span><span class="n">send</span><span class="p">(</span>
|
|
<span class="n">sender</span><span class="o">=</span><span class="n">origin</span><span class="p">,</span>
|
|
<span class="n">instance</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">raw</span><span class="o">=</span><span class="n">raw</span><span class="p">,</span>
|
|
<span class="n">using</span><span class="o">=</span><span class="n">using</span><span class="p">,</span>
|
|
<span class="n">update_fields</span><span class="o">=</span><span class="n">update_fields</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="c1"># A transaction isn't needed if one query is issued.</span>
|
|
<span class="k">if</span> <span class="n">meta</span><span class="o">.</span><span class="n">parents</span><span class="p">:</span>
|
|
<span class="n">context_manager</span> <span class="o">=</span> <span class="n">transaction</span><span class="o">.</span><span class="n">atomic</span><span class="p">(</span><span class="n">using</span><span class="o">=</span><span class="n">using</span><span class="p">,</span> <span class="n">savepoint</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">context_manager</span> <span class="o">=</span> <span class="n">transaction</span><span class="o">.</span><span class="n">mark_for_rollback_on_error</span><span class="p">(</span><span class="n">using</span><span class="o">=</span><span class="n">using</span><span class="p">)</span>
|
|
<span class="k">with</span> <span class="n">context_manager</span><span class="p">:</span>
|
|
<span class="n">parent_inserted</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">raw</span><span class="p">:</span>
|
|
<span class="c1"># Validate force insert only when parents are inserted.</span>
|
|
<span class="n">force_insert</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_validate_force_insert</span><span class="p">(</span><span class="n">force_insert</span><span class="p">)</span>
|
|
<span class="n">parent_inserted</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_save_parents</span><span class="p">(</span>
|
|
<span class="bp">cls</span><span class="p">,</span> <span class="n">using</span><span class="p">,</span> <span class="n">update_fields</span><span class="p">,</span> <span class="n">force_insert</span>
|
|
<span class="p">)</span>
|
|
<span class="n">updated</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_save_table</span><span class="p">(</span>
|
|
<span class="n">raw</span><span class="p">,</span>
|
|
<span class="bp">cls</span><span class="p">,</span>
|
|
<span class="n">force_insert</span> <span class="ow">or</span> <span class="n">parent_inserted</span><span class="p">,</span>
|
|
<span class="n">force_update</span><span class="p">,</span>
|
|
<span class="n">using</span><span class="p">,</span>
|
|
<span class="n">update_fields</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="c1"># Store the database on which the object was saved</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_state</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="n">using</span>
|
|
<span class="c1"># Once saved, this is no longer a to-be-added instance.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_state</span><span class="o">.</span><span class="n">adding</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<span class="c1"># Signal that the save is complete</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">meta</span><span class="o">.</span><span class="n">auto_created</span><span class="p">:</span>
|
|
<span class="n">post_save</span><span class="o">.</span><span class="n">send</span><span class="p">(</span>
|
|
<span class="n">sender</span><span class="o">=</span><span class="n">origin</span><span class="p">,</span>
|
|
<span class="n">instance</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">created</span><span class="o">=</span><span class="p">(</span><span class="ow">not</span> <span class="n">updated</span><span class="p">),</span>
|
|
<span class="n">update_fields</span><span class="o">=</span><span class="n">update_fields</span><span class="p">,</span>
|
|
<span class="n">raw</span><span class="o">=</span><span class="n">raw</span><span class="p">,</span>
|
|
<span class="n">using</span><span class="o">=</span><span class="n">using</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="n">save_base</span><span class="o">.</span><span class="n">alters_data</span> <span class="o">=</span> <span class="kc">True</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_save_parents</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span> <span class="bp">cls</span><span class="p">,</span> <span class="n">using</span><span class="p">,</span> <span class="n">update_fields</span><span class="p">,</span> <span class="n">force_insert</span><span class="p">,</span> <span class="n">updated_parents</span><span class="o">=</span><span class="kc">None</span>
|
|
<span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Save all the parents of cls using values from self."""</span>
|
|
<span class="n">meta</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span>
|
|
<span class="n">inserted</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="k">if</span> <span class="n">updated_parents</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">updated_parents</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="k">for</span> <span class="n">parent</span><span class="p">,</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">meta</span><span class="o">.</span><span class="n">parents</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
<span class="c1"># Make sure the link fields are synced between parent and self.</span>
|
|
<span class="k">if</span> <span class="p">(</span>
|
|
<span class="n">field</span>
|
|
<span class="ow">and</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">parent</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">pk</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span>
|
|
<span class="ow">and</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="p">):</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">parent</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">pk</span><span class="o">.</span><span class="n">attname</span><span class="p">,</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">))</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">parent_updated</span> <span class="o">:=</span> <span class="n">updated_parents</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">parent</span><span class="p">))</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">parent_inserted</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_save_parents</span><span class="p">(</span>
|
|
<span class="bp">cls</span><span class="o">=</span><span class="n">parent</span><span class="p">,</span>
|
|
<span class="n">using</span><span class="o">=</span><span class="n">using</span><span class="p">,</span>
|
|
<span class="n">update_fields</span><span class="o">=</span><span class="n">update_fields</span><span class="p">,</span>
|
|
<span class="n">force_insert</span><span class="o">=</span><span class="n">force_insert</span><span class="p">,</span>
|
|
<span class="n">updated_parents</span><span class="o">=</span><span class="n">updated_parents</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="n">updated</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_save_table</span><span class="p">(</span>
|
|
<span class="bp">cls</span><span class="o">=</span><span class="n">parent</span><span class="p">,</span>
|
|
<span class="n">using</span><span class="o">=</span><span class="n">using</span><span class="p">,</span>
|
|
<span class="n">update_fields</span><span class="o">=</span><span class="n">update_fields</span><span class="p">,</span>
|
|
<span class="n">force_insert</span><span class="o">=</span><span class="n">parent_inserted</span> <span class="ow">or</span> <span class="nb">issubclass</span><span class="p">(</span><span class="n">parent</span><span class="p">,</span> <span class="n">force_insert</span><span class="p">),</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">updated</span><span class="p">:</span>
|
|
<span class="n">inserted</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">updated_parents</span><span class="p">[</span><span class="n">parent</span><span class="p">]</span> <span class="o">=</span> <span class="n">updated</span>
|
|
<span class="k">elif</span> <span class="ow">not</span> <span class="n">parent_updated</span><span class="p">:</span>
|
|
<span class="n">inserted</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="c1"># Set the parent's PK value to self.</span>
|
|
<span class="k">if</span> <span class="n">field</span><span class="p">:</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_pk_val</span><span class="p">(</span><span class="n">parent</span><span class="o">.</span><span class="n">_meta</span><span class="p">))</span>
|
|
<span class="c1"># Since we didn't have an instance of the parent handy set</span>
|
|
<span class="c1"># attname directly, bypassing the descriptor. Invalidate</span>
|
|
<span class="c1"># the related object cache, in case it's been accidentally</span>
|
|
<span class="c1"># populated. A fresh instance will be re-built from the</span>
|
|
<span class="c1"># database if necessary.</span>
|
|
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">is_cached</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">delete_cached_value</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">inserted</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_save_table</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">raw</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
|
<span class="bp">cls</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">force_insert</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">force_update</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">update_fields</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Do the heavy-lifting involved in saving. Update or insert the data</span>
|
|
<span class="sd"> for a single table.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">meta</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span>
|
|
<span class="n">pk_fields</span> <span class="o">=</span> <span class="n">meta</span><span class="o">.</span><span class="n">pk_fields</span>
|
|
<span class="n">non_pks_non_generated</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="n">f</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">meta</span><span class="o">.</span><span class="n">local_concrete_fields</span>
|
|
<span class="k">if</span> <span class="n">f</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">pk_fields</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">f</span><span class="o">.</span><span class="n">generated</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="k">if</span> <span class="n">update_fields</span><span class="p">:</span>
|
|
<span class="n">non_pks_non_generated</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="n">f</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">non_pks_non_generated</span>
|
|
<span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">name</span> <span class="ow">in</span> <span class="n">update_fields</span> <span class="ow">or</span> <span class="n">f</span><span class="o">.</span><span class="n">attname</span> <span class="ow">in</span> <span class="n">update_fields</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_pk_set</span><span class="p">(</span><span class="n">meta</span><span class="p">):</span>
|
|
<span class="n">pk_val</span> <span class="o">=</span> <span class="n">meta</span><span class="o">.</span><span class="n">pk</span><span class="o">.</span><span class="n">get_pk_value_on_save</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">meta</span><span class="o">.</span><span class="n">pk</span><span class="o">.</span><span class="n">attname</span><span class="p">,</span> <span class="n">pk_val</span><span class="p">)</span>
|
|
<span class="n">pk_set</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_pk_set</span><span class="p">(</span><span class="n">meta</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">pk_set</span> <span class="ow">and</span> <span class="p">(</span><span class="n">force_update</span> <span class="ow">or</span> <span class="n">update_fields</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Cannot force an update in save() with no primary key."</span><span class="p">)</span>
|
|
<span class="n">updated</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="c1"># Skip an UPDATE when adding an instance and primary key has a default.</span>
|
|
<span class="k">if</span> <span class="p">(</span>
|
|
<span class="ow">not</span> <span class="n">raw</span>
|
|
<span class="ow">and</span> <span class="ow">not</span> <span class="n">force_insert</span>
|
|
<span class="ow">and</span> <span class="ow">not</span> <span class="n">force_update</span>
|
|
<span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_state</span><span class="o">.</span><span class="n">adding</span>
|
|
<span class="ow">and</span> <span class="nb">all</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">has_default</span><span class="p">()</span> <span class="ow">or</span> <span class="n">f</span><span class="o">.</span><span class="n">has_db_default</span><span class="p">()</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">meta</span><span class="o">.</span><span class="n">pk_fields</span><span class="p">)</span>
|
|
<span class="p">):</span>
|
|
<span class="n">force_insert</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="c1"># If possible, try an UPDATE. If that doesn't update anything, do an</span>
|
|
<span class="c1"># INSERT.</span>
|
|
<span class="k">if</span> <span class="n">pk_set</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">force_insert</span><span class="p">:</span>
|
|
<span class="n">base_qs</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_base_manager</span><span class="o">.</span><span class="n">using</span><span class="p">(</span><span class="n">using</span><span class="p">)</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">(</span>
|
|
<span class="n">f</span><span class="p">,</span>
|
|
<span class="kc">None</span><span class="p">,</span>
|
|
<span class="p">(</span><span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span> <span class="k">if</span> <span class="n">raw</span> <span class="k">else</span> <span class="n">f</span><span class="o">.</span><span class="n">pre_save</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="kc">False</span><span class="p">)),</span>
|
|
<span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">non_pks_non_generated</span>
|
|
<span class="p">]</span>
|
|
<span class="n">forced_update</span> <span class="o">=</span> <span class="n">update_fields</span> <span class="ow">or</span> <span class="n">force_update</span>
|
|
<span class="n">pk_val</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_pk_val</span><span class="p">(</span><span class="n">meta</span><span class="p">)</span>
|
|
<span class="n">returning_fields</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="n">f</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">meta</span><span class="o">.</span><span class="n">local_concrete_fields</span>
|
|
<span class="k">if</span> <span class="p">(</span>
|
|
<span class="n">f</span><span class="o">.</span><span class="n">generated</span>
|
|
<span class="ow">and</span> <span class="n">f</span><span class="o">.</span><span class="n">referenced_fields</span><span class="o">.</span><span class="n">intersection</span><span class="p">(</span><span class="n">non_pks_non_generated</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="p">]</span>
|
|
<span class="k">for</span> <span class="n">field</span><span class="p">,</span> <span class="n">_model</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">update_fields</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">field</span><span class="o">.</span><span class="n">name</span> <span class="ow">in</span> <span class="n">update_fields</span><span class="p">)</span> <span class="ow">and</span> <span class="nb">hasattr</span><span class="p">(</span>
|
|
<span class="n">value</span><span class="p">,</span> <span class="s2">"resolve_expression"</span>
|
|
<span class="p">):</span>
|
|
<span class="n">returning_fields</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">field</span><span class="p">)</span>
|
|
<span class="n">results</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_do_update</span><span class="p">(</span>
|
|
<span class="n">base_qs</span><span class="p">,</span>
|
|
<span class="n">using</span><span class="p">,</span>
|
|
<span class="n">pk_val</span><span class="p">,</span>
|
|
<span class="n">values</span><span class="p">,</span>
|
|
<span class="n">update_fields</span><span class="p">,</span>
|
|
<span class="n">forced_update</span><span class="p">,</span>
|
|
<span class="n">returning_fields</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">updated</span> <span class="o">:=</span> <span class="nb">bool</span><span class="p">(</span><span class="n">results</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_assign_returned_values</span><span class="p">(</span><span class="n">results</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">returning_fields</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">force_update</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">NotUpdated</span><span class="p">(</span><span class="s2">"Forced update did not affect any rows."</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">update_fields</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">NotUpdated</span><span class="p">(</span>
|
|
<span class="s2">"Save with update_fields did not affect any rows."</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">updated</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">meta</span><span class="o">.</span><span class="n">order_with_respect_to</span><span class="p">:</span>
|
|
<span class="c1"># If this is a model with an order_with_respect_to</span>
|
|
<span class="c1"># autopopulate the _order field</span>
|
|
<span class="n">field</span> <span class="o">=</span> <span class="n">meta</span><span class="o">.</span><span class="n">order_with_respect_to</span>
|
|
<span class="n">filter_args</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">get_filter_kwargs_for_object</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_order</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="bp">cls</span><span class="o">.</span><span class="n">_base_manager</span><span class="o">.</span><span class="n">using</span><span class="p">(</span><span class="n">using</span><span class="p">)</span>
|
|
<span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="o">**</span><span class="n">filter_args</span><span class="p">)</span>
|
|
<span class="o">.</span><span class="n">aggregate</span><span class="p">(</span>
|
|
<span class="n">_order__max</span><span class="o">=</span><span class="n">Coalesce</span><span class="p">(</span>
|
|
<span class="n">ExpressionWrapper</span><span class="p">(</span>
|
|
<span class="n">Max</span><span class="p">(</span><span class="s2">"_order"</span><span class="p">)</span> <span class="o">+</span> <span class="n">Value</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="n">output_field</span><span class="o">=</span><span class="n">IntegerField</span><span class="p">()</span>
|
|
<span class="p">),</span>
|
|
<span class="n">Value</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span>
|
|
<span class="p">),</span>
|
|
<span class="p">)[</span><span class="s2">"_order__max"</span><span class="p">]</span>
|
|
<span class="p">)</span>
|
|
<span class="n">insert_fields</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="n">f</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">meta</span><span class="o">.</span><span class="n">local_concrete_fields</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">f</span><span class="o">.</span><span class="n">generated</span> <span class="ow">and</span> <span class="p">(</span><span class="n">pk_set</span> <span class="ow">or</span> <span class="n">f</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">meta</span><span class="o">.</span><span class="n">auto_field</span><span class="p">)</span>
|
|
<span class="p">]</span>
|
|
<span class="n">returning_fields</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">meta</span><span class="o">.</span><span class="n">db_returning_fields</span><span class="p">)</span>
|
|
<span class="n">can_return_columns_from_insert</span> <span class="o">=</span> <span class="n">connections</span><span class="p">[</span>
|
|
<span class="n">using</span>
|
|
<span class="p">]</span><span class="o">.</span><span class="n">features</span><span class="o">.</span><span class="n">can_return_columns_from_insert</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">insert_fields</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">raw</span>
|
|
<span class="k">else</span> <span class="n">field</span><span class="o">.</span><span class="n">pre_save</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">add</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="s2">"resolve_expression"</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">field</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">returning_fields</span><span class="p">:</span>
|
|
<span class="n">returning_fields</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">field</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="p">(</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">db_returning</span>
|
|
<span class="ow">and</span> <span class="ow">not</span> <span class="n">can_return_columns_from_insert</span>
|
|
<span class="ow">and</span> <span class="ow">not</span> <span class="p">(</span><span class="n">pk_set</span> <span class="ow">and</span> <span class="n">field</span> <span class="ow">is</span> <span class="n">meta</span><span class="o">.</span><span class="n">auto_field</span><span class="p">)</span>
|
|
<span class="p">):</span>
|
|
<span class="n">returning_fields</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">field</span><span class="p">)</span>
|
|
<span class="n">results</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_do_insert</span><span class="p">(</span>
|
|
<span class="bp">cls</span><span class="o">.</span><span class="n">_base_manager</span><span class="p">,</span> <span class="n">using</span><span class="p">,</span> <span class="n">insert_fields</span><span class="p">,</span> <span class="n">returning_fields</span><span class="p">,</span> <span class="n">raw</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">results</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_assign_returned_values</span><span class="p">(</span><span class="n">results</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">returning_fields</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">updated</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_do_update</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">base_qs</span><span class="p">,</span>
|
|
<span class="n">using</span><span class="p">,</span>
|
|
<span class="n">pk_val</span><span class="p">,</span>
|
|
<span class="n">values</span><span class="p">,</span>
|
|
<span class="n">update_fields</span><span class="p">,</span>
|
|
<span class="n">forced_update</span><span class="p">,</span>
|
|
<span class="n">returning_fields</span><span class="p">,</span>
|
|
<span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Try to update the model. Return True if the model was updated (if an</span>
|
|
<span class="sd"> update query was done and a matching row was found in the DB).</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">filtered</span> <span class="o">=</span> <span class="n">base_qs</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">pk</span><span class="o">=</span><span class="n">pk_val</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">values</span><span class="p">:</span>
|
|
<span class="c1"># We can end up here when saving a model in inheritance chain where</span>
|
|
<span class="c1"># update_fields doesn't target any field in current model. In that</span>
|
|
<span class="c1"># case we just say the update succeeded. Another case ending up</span>
|
|
<span class="c1"># here is a model with just PK - in that case check that the PK</span>
|
|
<span class="c1"># still exists.</span>
|
|
<span class="k">if</span> <span class="n">update_fields</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">filtered</span><span class="o">.</span><span class="n">exists</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="p">[()]</span>
|
|
<span class="k">return</span> <span class="p">[]</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">select_on_save</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">forced_update</span><span class="p">:</span>
|
|
<span class="c1"># It may happen that the object is deleted from the DB right after</span>
|
|
<span class="c1"># this check, causing the subsequent UPDATE to return zero matching</span>
|
|
<span class="c1"># rows. The same result can occur in some rare cases when the</span>
|
|
<span class="c1"># database returns zero despite the UPDATE being executed</span>
|
|
<span class="c1"># successfully (a row is matched and updated). In order to</span>
|
|
<span class="c1"># distinguish these two cases, the object's existence in the</span>
|
|
<span class="c1"># database is again checked for if the UPDATE query returns 0.</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">filtered</span><span class="o">.</span><span class="n">exists</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="p">[]</span>
|
|
<span class="k">if</span> <span class="n">results</span> <span class="o">:=</span> <span class="n">filtered</span><span class="o">.</span><span class="n">_update</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">returning_fields</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">results</span>
|
|
<span class="k">return</span> <span class="p">[()]</span> <span class="k">if</span> <span class="n">filtered</span><span class="o">.</span><span class="n">exists</span><span class="p">()</span> <span class="k">else</span> <span class="p">[]</span>
|
|
<span class="k">return</span> <span class="n">filtered</span><span class="o">.</span><span class="n">_update</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">returning_fields</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_do_insert</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">manager</span><span class="p">,</span> <span class="n">using</span><span class="p">,</span> <span class="n">fields</span><span class="p">,</span> <span class="n">returning_fields</span><span class="p">,</span> <span class="n">raw</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Do an INSERT. If returning_fields is defined then this method should</span>
|
|
<span class="sd"> return the newly created data for the model.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">return</span> <span class="n">manager</span><span class="o">.</span><span class="n">_insert</span><span class="p">(</span>
|
|
<span class="p">[</span><span class="bp">self</span><span class="p">],</span>
|
|
<span class="n">fields</span><span class="o">=</span><span class="n">fields</span><span class="p">,</span>
|
|
<span class="n">returning_fields</span><span class="o">=</span><span class="n">returning_fields</span><span class="p">,</span>
|
|
<span class="n">using</span><span class="o">=</span><span class="n">using</span><span class="p">,</span>
|
|
<span class="n">raw</span><span class="o">=</span><span class="n">raw</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_assign_returned_values</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">returned_values</span><span class="p">,</span> <span class="n">returning_fields</span><span class="p">):</span>
|
|
<span class="n">returning_fields_iter</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">returning_fields</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">value</span><span class="p">,</span> <span class="n">field</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">returned_values</span><span class="p">,</span> <span class="n">returning_fields_iter</span><span class="p">):</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
|
|
<span class="c1"># Defer all fields that were meant to be updated with their database</span>
|
|
<span class="c1"># resolved values but couldn't as they are effectively stale.</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">returning_fields_iter</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_prepare_related_fields_for_save</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">operation_name</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="c1"># Ensure that a model instance without a PK hasn't been assigned to</span>
|
|
<span class="c1"># a ForeignKey, GenericForeignKey or OneToOneField on this model. If</span>
|
|
<span class="c1"># the field is nullable, allowing the save would result in silent data</span>
|
|
<span class="c1"># loss.</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_fields</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">fields</span> <span class="ow">and</span> <span class="n">field</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">fields</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="c1"># If the related field isn't cached, then an instance hasn't been</span>
|
|
<span class="c1"># assigned and there's no need to worry about this check.</span>
|
|
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">is_relation</span> <span class="ow">and</span> <span class="n">field</span><span class="o">.</span><span class="n">is_cached</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="n">obj</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="c1"># A pk may have been assigned manually to a model instance not</span>
|
|
<span class="c1"># saved to the database (or auto-generated in a case like</span>
|
|
<span class="c1"># UUIDField), but we allow the save to proceed and rely on the</span>
|
|
<span class="c1"># database to raise an IntegrityError if applicable. If</span>
|
|
<span class="c1"># constraints aren't supported by the database, there's the</span>
|
|
<span class="c1"># unavoidable risk of data corruption.</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="o">.</span><span class="n">_is_pk_set</span><span class="p">():</span>
|
|
<span class="c1"># Remove the object from a related instance cache.</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">field</span><span class="o">.</span><span class="n">remote_field</span><span class="o">.</span><span class="n">multiple</span><span class="p">:</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">remote_field</span><span class="o">.</span><span class="n">delete_cached_value</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
|
<span class="s2">"</span><span class="si">%s</span><span class="s2">() prohibited to prevent data loss due to unsaved "</span>
|
|
<span class="s2">"related object '</span><span class="si">%s</span><span class="s2">'."</span> <span class="o">%</span> <span class="p">(</span><span class="n">operation_name</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span> <span class="ow">in</span> <span class="n">field</span><span class="o">.</span><span class="n">empty_values</span><span class="p">:</span>
|
|
<span class="c1"># Set related object if it has been saved after an</span>
|
|
<span class="c1"># assignment.</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">obj</span><span class="p">)</span>
|
|
<span class="c1"># If the relationship's pk/to_field was changed, clear the</span>
|
|
<span class="c1"># cached relationship.</span>
|
|
<span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">target_field</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">getattr</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span>
|
|
<span class="p">):</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">delete_cached_value</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="c1"># GenericForeignKeys are private.</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">private_fields</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">fields</span> <span class="ow">and</span> <span class="n">field</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">fields</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="k">if</span> <span class="p">(</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">is_relation</span>
|
|
<span class="ow">and</span> <span class="n">field</span><span class="o">.</span><span class="n">is_cached</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="ow">and</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">field</span><span class="p">,</span> <span class="s2">"fk_field"</span><span class="p">)</span>
|
|
<span class="p">):</span>
|
|
<span class="n">obj</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">get_cached_value</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">obj</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">obj</span><span class="o">.</span><span class="n">_is_pk_set</span><span class="p">():</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">operation_name</span><span class="si">}</span><span class="s2">() prohibited to prevent data loss due to "</span>
|
|
<span class="sa">f</span><span class="s2">"unsaved related object '</span><span class="si">{</span><span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">'."</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">delete</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">keep_parents</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_pk_set</span><span class="p">():</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
|
<span class="s2">"</span><span class="si">%s</span><span class="s2"> object can't be deleted because its </span><span class="si">%s</span><span class="s2"> attribute is set "</span>
|
|
<span class="s2">"to None."</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">object_name</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">pk</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="n">using</span> <span class="o">=</span> <span class="n">using</span> <span class="ow">or</span> <span class="n">router</span><span class="o">.</span><span class="n">db_for_write</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">,</span> <span class="n">instance</span><span class="o">=</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="n">collector</span> <span class="o">=</span> <span class="n">Collector</span><span class="p">(</span><span class="n">using</span><span class="o">=</span><span class="n">using</span><span class="p">,</span> <span class="n">origin</span><span class="o">=</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="n">collector</span><span class="o">.</span><span class="n">collect</span><span class="p">([</span><span class="bp">self</span><span class="p">],</span> <span class="n">keep_parents</span><span class="o">=</span><span class="n">keep_parents</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">collector</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
|
|
|
|
<span class="n">delete</span><span class="o">.</span><span class="n">alters_data</span> <span class="o">=</span> <span class="kc">True</span>
|
|
|
|
<span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">adelete</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">keep_parents</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="k">await</span> <span class="n">sync_to_async</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">delete</span><span class="p">)(</span>
|
|
<span class="n">using</span><span class="o">=</span><span class="n">using</span><span class="p">,</span>
|
|
<span class="n">keep_parents</span><span class="o">=</span><span class="n">keep_parents</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="n">adelete</span><span class="o">.</span><span class="n">alters_data</span> <span class="o">=</span> <span class="kc">True</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_get_FIELD_display</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">):</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span>
|
|
<span class="n">choices_dict</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">make_hashable</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">flatchoices</span><span class="p">))</span>
|
|
<span class="c1"># force_str() to coerce lazy strings.</span>
|
|
<span class="k">return</span> <span class="n">force_str</span><span class="p">(</span>
|
|
<span class="n">choices_dict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">make_hashable</span><span class="p">(</span><span class="n">value</span><span class="p">),</span> <span class="n">value</span><span class="p">),</span> <span class="n">strings_only</span><span class="o">=</span><span class="kc">True</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_get_next_or_previous_by_FIELD</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">,</span> <span class="n">is_next</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_pk_set</span><span class="p">():</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"get_next/get_previous cannot be used on unsaved objects."</span><span class="p">)</span>
|
|
<span class="n">op</span> <span class="o">=</span> <span class="s2">"gt"</span> <span class="k">if</span> <span class="n">is_next</span> <span class="k">else</span> <span class="s2">"lt"</span>
|
|
<span class="n">order</span> <span class="o">=</span> <span class="s2">""</span> <span class="k">if</span> <span class="n">is_next</span> <span class="k">else</span> <span class="s2">"-"</span>
|
|
<span class="n">param</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span>
|
|
<span class="n">q</span> <span class="o">=</span> <span class="n">Q</span><span class="o">.</span><span class="n">create</span><span class="p">([(</span><span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">param</span><span class="p">),</span> <span class="p">(</span><span class="sa">f</span><span class="s2">"pk__</span><span class="si">{</span><span class="n">op</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pk</span><span class="p">)],</span> <span class="n">connector</span><span class="o">=</span><span class="n">Q</span><span class="o">.</span><span class="n">AND</span><span class="p">)</span>
|
|
<span class="n">q</span> <span class="o">=</span> <span class="n">Q</span><span class="o">.</span><span class="n">create</span><span class="p">([</span><span class="n">q</span><span class="p">,</span> <span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">__</span><span class="si">{</span><span class="n">op</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="n">param</span><span class="p">)],</span> <span class="n">connector</span><span class="o">=</span><span class="n">Q</span><span class="o">.</span><span class="n">OR</span><span class="p">)</span>
|
|
<span class="n">qs</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="n">_default_manager</span><span class="o">.</span><span class="n">using</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_state</span><span class="o">.</span><span class="n">db</span><span class="p">)</span>
|
|
<span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">q</span><span class="p">)</span>
|
|
<span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s2">"</span><span class="si">%s%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">order</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="p">),</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">pk"</span> <span class="o">%</span> <span class="n">order</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">qs</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="k">except</span> <span class="ne">IndexError</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">DoesNotExist</span><span class="p">(</span>
|
|
<span class="s2">"</span><span class="si">%s</span><span class="s2"> matching query does not exist."</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">object_name</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_get_next_or_previous_in_order</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">is_next</span><span class="p">):</span>
|
|
<span class="n">cachename</span> <span class="o">=</span> <span class="s2">"__</span><span class="si">%s</span><span class="s2">_order_cache"</span> <span class="o">%</span> <span class="n">is_next</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cachename</span><span class="p">):</span>
|
|
<span class="n">op</span> <span class="o">=</span> <span class="s2">"gt"</span> <span class="k">if</span> <span class="n">is_next</span> <span class="k">else</span> <span class="s2">"lt"</span>
|
|
<span class="n">order</span> <span class="o">=</span> <span class="s2">"_order"</span> <span class="k">if</span> <span class="n">is_next</span> <span class="k">else</span> <span class="s2">"-_order"</span>
|
|
<span class="n">order_field</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">order_with_respect_to</span>
|
|
<span class="n">filter_args</span> <span class="o">=</span> <span class="n">order_field</span><span class="o">.</span><span class="n">get_filter_kwargs_for_object</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="n">obj</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="n">_default_manager</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="o">**</span><span class="n">filter_args</span><span class="p">)</span>
|
|
<span class="o">.</span><span class="n">filter</span><span class="p">(</span>
|
|
<span class="o">**</span><span class="p">{</span>
|
|
<span class="s2">"_order__</span><span class="si">%s</span><span class="s2">"</span>
|
|
<span class="o">%</span> <span class="n">op</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="n">_default_manager</span><span class="o">.</span><span class="n">values</span><span class="p">(</span><span class="s2">"_order"</span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span>
|
|
<span class="o">**</span><span class="p">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">pk</span><span class="o">.</span><span class="n">name</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">pk</span><span class="p">}</span>
|
|
<span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">)</span>
|
|
<span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="n">order</span><span class="p">)[:</span><span class="mi">1</span><span class="p">]</span>
|
|
<span class="o">.</span><span class="n">get</span><span class="p">()</span>
|
|
<span class="p">)</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cachename</span><span class="p">,</span> <span class="n">obj</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cachename</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_get_field_expression_map</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">meta</span><span class="p">,</span> <span class="n">exclude</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">exclude</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">exclude</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
|
|
<span class="n">meta</span> <span class="o">=</span> <span class="n">meta</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span>
|
|
<span class="n">field_map</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="n">generated_fields</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">meta</span><span class="o">.</span><span class="n">local_fields</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">name</span> <span class="ow">in</span> <span class="n">exclude</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">generated</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="nb">any</span><span class="p">(</span>
|
|
<span class="n">ref</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="n">exclude</span>
|
|
<span class="k">for</span> <span class="n">ref</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_expr_references</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">expression</span><span class="p">)</span>
|
|
<span class="p">):</span>
|
|
<span class="k">continue</span>
|
|
<span class="n">generated_fields</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">field</span><span class="p">)</span>
|
|
<span class="k">continue</span>
|
|
<span class="k">if</span> <span class="p">(</span>
|
|
<span class="nb">isinstance</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">remote_field</span><span class="p">,</span> <span class="n">ForeignObjectRel</span><span class="p">)</span>
|
|
<span class="ow">and</span> <span class="n">field</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">meta</span><span class="o">.</span><span class="n">local_concrete_fields</span>
|
|
<span class="p">):</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span>
|
|
<span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">from_field</span><span class="p">)</span> <span class="k">for</span> <span class="n">from_field</span> <span class="ow">in</span> <span class="n">field</span><span class="o">.</span><span class="n">from_fields</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">field</span><span class="o">.</span><span class="n">concrete</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">value</span> <span class="ow">or</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="s2">"resolve_expression"</span><span class="p">):</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">Value</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span>
|
|
<span class="n">field_map</span><span class="p">[</span><span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
|
|
<span class="n">field_map</span><span class="p">[</span><span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
|
|
<span class="k">if</span> <span class="s2">"pk"</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">exclude</span><span class="p">:</span>
|
|
<span class="n">field_map</span><span class="p">[</span><span class="s2">"pk"</span><span class="p">]</span> <span class="o">=</span> <span class="n">Value</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pk</span><span class="p">,</span> <span class="n">meta</span><span class="o">.</span><span class="n">pk</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">generated_fields</span><span class="p">:</span>
|
|
<span class="n">replacements</span> <span class="o">=</span> <span class="p">{</span><span class="n">F</span><span class="p">(</span><span class="n">name</span><span class="p">):</span> <span class="n">value</span> <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">field_map</span><span class="o">.</span><span class="n">items</span><span class="p">()}</span>
|
|
<span class="k">for</span> <span class="n">generated_field</span> <span class="ow">in</span> <span class="n">generated_fields</span><span class="p">:</span>
|
|
<span class="n">field_map</span><span class="p">[</span><span class="n">generated_field</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">ExpressionWrapper</span><span class="p">(</span>
|
|
<span class="n">generated_field</span><span class="o">.</span><span class="n">expression</span><span class="o">.</span><span class="n">replace_expressions</span><span class="p">(</span><span class="n">replacements</span><span class="p">),</span>
|
|
<span class="n">generated_field</span><span class="o">.</span><span class="n">output_field</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="n">field_map</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">prepare_database_save</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_pk_set</span><span class="p">():</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
|
<span class="s2">"Unsaved model instance </span><span class="si">%r</span><span class="s2"> cannot be used in an ORM query."</span> <span class="o">%</span> <span class="bp">self</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">.</span><span class="n">remote_field</span><span class="o">.</span><span class="n">get_related_field</span><span class="p">()</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">clean</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Hook for doing any extra model-wide validation after clean() has been</span>
|
|
<span class="sd"> called on every field by self.clean_fields. Any ValidationError raised</span>
|
|
<span class="sd"> by this method will not be associated with a particular field; it will</span>
|
|
<span class="sd"> have a special-case association with the field defined by</span>
|
|
<span class="sd"> NON_FIELD_ERRORS.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">pass</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">validate_unique</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exclude</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Check unique constraints on the model and raise ValidationError if any</span>
|
|
<span class="sd"> failed.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">unique_checks</span><span class="p">,</span> <span class="n">date_checks</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_unique_checks</span><span class="p">(</span><span class="n">exclude</span><span class="o">=</span><span class="n">exclude</span><span class="p">)</span>
|
|
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_perform_unique_checks</span><span class="p">(</span><span class="n">unique_checks</span><span class="p">)</span>
|
|
<span class="n">date_errors</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_perform_date_checks</span><span class="p">(</span><span class="n">date_checks</span><span class="p">)</span>
|
|
|
|
<span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">date_errors</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="p">[])</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">errors</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">ValidationError</span><span class="p">(</span><span class="n">errors</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_get_unique_checks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exclude</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">include_meta_constraints</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Return a list of checks to perform. Since validate_unique() could be</span>
|
|
<span class="sd"> called from a ModelForm, some fields may have been excluded; we can't</span>
|
|
<span class="sd"> perform a unique check on a model that is missing fields involved</span>
|
|
<span class="sd"> in that check. Fields that did not validate should also be excluded,</span>
|
|
<span class="sd"> but they need to be passed in via the exclude argument.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="n">exclude</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">exclude</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
|
|
<span class="n">unique_checks</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
<span class="n">unique_togethers</span> <span class="o">=</span> <span class="p">[(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">unique_together</span><span class="p">)]</span>
|
|
<span class="n">constraints</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">if</span> <span class="n">include_meta_constraints</span><span class="p">:</span>
|
|
<span class="n">constraints</span> <span class="o">=</span> <span class="p">[(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">total_unique_constraints</span><span class="p">)]</span>
|
|
<span class="k">for</span> <span class="n">parent_class</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">all_parents</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">parent_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">unique_together</span><span class="p">:</span>
|
|
<span class="n">unique_togethers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="p">(</span><span class="n">parent_class</span><span class="p">,</span> <span class="n">parent_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">unique_together</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">include_meta_constraints</span> <span class="ow">and</span> <span class="n">parent_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">total_unique_constraints</span><span class="p">:</span>
|
|
<span class="n">constraints</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="p">(</span><span class="n">parent_class</span><span class="p">,</span> <span class="n">parent_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">total_unique_constraints</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">for</span> <span class="n">model_class</span><span class="p">,</span> <span class="n">unique_together</span> <span class="ow">in</span> <span class="n">unique_togethers</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">check</span> <span class="ow">in</span> <span class="n">unique_together</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">any</span><span class="p">(</span><span class="n">name</span> <span class="ow">in</span> <span class="n">exclude</span> <span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">check</span><span class="p">):</span>
|
|
<span class="c1"># Add the check if the field isn't excluded.</span>
|
|
<span class="n">unique_checks</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">model_class</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">check</span><span class="p">)))</span>
|
|
|
|
<span class="k">if</span> <span class="n">include_meta_constraints</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">model_class</span><span class="p">,</span> <span class="n">model_constraints</span> <span class="ow">in</span> <span class="n">constraints</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">constraint</span> <span class="ow">in</span> <span class="n">model_constraints</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">any</span><span class="p">(</span><span class="n">name</span> <span class="ow">in</span> <span class="n">exclude</span> <span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">constraint</span><span class="o">.</span><span class="n">fields</span><span class="p">):</span>
|
|
<span class="n">unique_checks</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">model_class</span><span class="p">,</span> <span class="n">constraint</span><span class="o">.</span><span class="n">fields</span><span class="p">))</span>
|
|
|
|
<span class="c1"># These are checks for the unique_for_<date/year/month>.</span>
|
|
<span class="n">date_checks</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
<span class="c1"># Gather a list of checks for fields declared as unique and add them to</span>
|
|
<span class="c1"># the list of checks.</span>
|
|
|
|
<span class="n">fields_with_class</span> <span class="o">=</span> <span class="p">[(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_fields</span><span class="p">)]</span>
|
|
<span class="k">for</span> <span class="n">parent_class</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">all_parents</span><span class="p">:</span>
|
|
<span class="n">fields_with_class</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">parent_class</span><span class="p">,</span> <span class="n">parent_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_fields</span><span class="p">))</span>
|
|
|
|
<span class="k">for</span> <span class="n">model_class</span><span class="p">,</span> <span class="n">fields</span> <span class="ow">in</span> <span class="n">fields_with_class</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">fields</span><span class="p">:</span>
|
|
<span class="n">name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">name</span>
|
|
<span class="k">if</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">exclude</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">CompositePrimaryKey</span><span class="p">):</span>
|
|
<span class="n">names</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">name</span> <span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">fields</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">exclude</span><span class="o">.</span><span class="n">isdisjoint</span><span class="p">(</span><span class="n">names</span><span class="p">):</span>
|
|
<span class="n">unique_checks</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">model_class</span><span class="p">,</span> <span class="n">names</span><span class="p">))</span>
|
|
<span class="k">continue</span>
|
|
<span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">unique</span><span class="p">:</span>
|
|
<span class="n">unique_checks</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">model_class</span><span class="p">,</span> <span class="p">(</span><span class="n">name</span><span class="p">,)))</span>
|
|
<span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">unique_for_date</span> <span class="ow">and</span> <span class="n">f</span><span class="o">.</span><span class="n">unique_for_date</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">exclude</span><span class="p">:</span>
|
|
<span class="n">date_checks</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">model_class</span><span class="p">,</span> <span class="s2">"date"</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">unique_for_date</span><span class="p">))</span>
|
|
<span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">unique_for_year</span> <span class="ow">and</span> <span class="n">f</span><span class="o">.</span><span class="n">unique_for_year</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">exclude</span><span class="p">:</span>
|
|
<span class="n">date_checks</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">model_class</span><span class="p">,</span> <span class="s2">"year"</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">unique_for_year</span><span class="p">))</span>
|
|
<span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">unique_for_month</span> <span class="ow">and</span> <span class="n">f</span><span class="o">.</span><span class="n">unique_for_month</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">exclude</span><span class="p">:</span>
|
|
<span class="n">date_checks</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">model_class</span><span class="p">,</span> <span class="s2">"month"</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">unique_for_month</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="n">unique_checks</span><span class="p">,</span> <span class="n">date_checks</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_perform_unique_checks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">unique_checks</span><span class="p">):</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">{}</span>
|
|
|
|
<span class="k">for</span> <span class="n">model_class</span><span class="p">,</span> <span class="n">unique_check</span> <span class="ow">in</span> <span class="n">unique_checks</span><span class="p">:</span>
|
|
<span class="c1"># Try to look up an existing object with the same values as this</span>
|
|
<span class="c1"># object's values for all the unique field.</span>
|
|
|
|
<span class="n">lookup_kwargs</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="k">for</span> <span class="n">field_name</span> <span class="ow">in</span> <span class="n">unique_check</span><span class="p">:</span>
|
|
<span class="n">f</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">get_field</span><span class="p">(</span><span class="n">field_name</span><span class="p">)</span>
|
|
<span class="n">lookup_value</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span>
|
|
<span class="c1"># TODO: Handle multiple backends with different feature flags.</span>
|
|
<span class="k">if</span> <span class="n">lookup_value</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="p">(</span>
|
|
<span class="n">lookup_value</span> <span class="o">==</span> <span class="s2">""</span>
|
|
<span class="ow">and</span> <span class="n">connection</span><span class="o">.</span><span class="n">features</span><span class="o">.</span><span class="n">interprets_empty_strings_as_nulls</span>
|
|
<span class="p">):</span>
|
|
<span class="c1"># no value, skip the lookup</span>
|
|
<span class="k">continue</span>
|
|
<span class="k">if</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">model_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">pk_fields</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_state</span><span class="o">.</span><span class="n">adding</span><span class="p">:</span>
|
|
<span class="c1"># no need to check for unique primary key when editing</span>
|
|
<span class="k">continue</span>
|
|
<span class="n">lookup_kwargs</span><span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">field_name</span><span class="p">)]</span> <span class="o">=</span> <span class="n">lookup_value</span>
|
|
|
|
<span class="c1"># some fields were skipped, no reason to do the check</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">unique_check</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">len</span><span class="p">(</span><span class="n">lookup_kwargs</span><span class="p">):</span>
|
|
<span class="k">continue</span>
|
|
|
|
<span class="n">qs</span> <span class="o">=</span> <span class="n">model_class</span><span class="o">.</span><span class="n">_default_manager</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="o">**</span><span class="n">lookup_kwargs</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Exclude the current object from the query if we are editing an</span>
|
|
<span class="c1"># instance (as opposed to creating a new one)</span>
|
|
<span class="c1"># Note that we need to use the pk as defined by model_class, not</span>
|
|
<span class="c1"># self.pk. These can be different fields because model inheritance</span>
|
|
<span class="c1"># allows single model to have effectively multiple primary keys.</span>
|
|
<span class="c1"># Refs #17615.</span>
|
|
<span class="n">model_class_pk</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_pk_val</span><span class="p">(</span><span class="n">model_class</span><span class="o">.</span><span class="n">_meta</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_state</span><span class="o">.</span><span class="n">adding</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_pk_set</span><span class="p">(</span><span class="n">model_class</span><span class="o">.</span><span class="n">_meta</span><span class="p">):</span>
|
|
<span class="n">qs</span> <span class="o">=</span> <span class="n">qs</span><span class="o">.</span><span class="n">exclude</span><span class="p">(</span><span class="n">pk</span><span class="o">=</span><span class="n">model_class_pk</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">qs</span><span class="o">.</span><span class="n">exists</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">unique_check</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">key</span> <span class="o">=</span> <span class="n">unique_check</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">key</span> <span class="o">=</span> <span class="n">NON_FIELD_ERRORS</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">unique_error_message</span><span class="p">(</span><span class="n">model_class</span><span class="p">,</span> <span class="n">unique_check</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_perform_date_checks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">date_checks</span><span class="p">):</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="k">for</span> <span class="n">model_class</span><span class="p">,</span> <span class="n">lookup_type</span><span class="p">,</span> <span class="n">field</span><span class="p">,</span> <span class="n">unique_for</span> <span class="ow">in</span> <span class="n">date_checks</span><span class="p">:</span>
|
|
<span class="n">lookup_kwargs</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="c1"># there's a ticket to add a date lookup, we can remove this special</span>
|
|
<span class="c1"># case if that makes it's way in</span>
|
|
<span class="n">date</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">unique_for</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">date</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="k">if</span> <span class="n">lookup_type</span> <span class="o">==</span> <span class="s2">"date"</span><span class="p">:</span>
|
|
<span class="n">lookup_kwargs</span><span class="p">[</span><span class="s2">"</span><span class="si">%s</span><span class="s2">__day"</span> <span class="o">%</span> <span class="n">unique_for</span><span class="p">]</span> <span class="o">=</span> <span class="n">date</span><span class="o">.</span><span class="n">day</span>
|
|
<span class="n">lookup_kwargs</span><span class="p">[</span><span class="s2">"</span><span class="si">%s</span><span class="s2">__month"</span> <span class="o">%</span> <span class="n">unique_for</span><span class="p">]</span> <span class="o">=</span> <span class="n">date</span><span class="o">.</span><span class="n">month</span>
|
|
<span class="n">lookup_kwargs</span><span class="p">[</span><span class="s2">"</span><span class="si">%s</span><span class="s2">__year"</span> <span class="o">%</span> <span class="n">unique_for</span><span class="p">]</span> <span class="o">=</span> <span class="n">date</span><span class="o">.</span><span class="n">year</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">lookup_kwargs</span><span class="p">[</span><span class="s2">"</span><span class="si">%s</span><span class="s2">__</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">unique_for</span><span class="p">,</span> <span class="n">lookup_type</span><span class="p">)]</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span>
|
|
<span class="n">date</span><span class="p">,</span> <span class="n">lookup_type</span>
|
|
<span class="p">)</span>
|
|
<span class="n">lookup_kwargs</span><span class="p">[</span><span class="n">field</span><span class="p">]</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span>
|
|
|
|
<span class="n">qs</span> <span class="o">=</span> <span class="n">model_class</span><span class="o">.</span><span class="n">_default_manager</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="o">**</span><span class="n">lookup_kwargs</span><span class="p">)</span>
|
|
<span class="c1"># Exclude the current object from the query if we are editing an</span>
|
|
<span class="c1"># instance (as opposed to creating a new one)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_state</span><span class="o">.</span><span class="n">adding</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_pk_set</span><span class="p">():</span>
|
|
<span class="n">qs</span> <span class="o">=</span> <span class="n">qs</span><span class="o">.</span><span class="n">exclude</span><span class="p">(</span><span class="n">pk</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">pk</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">qs</span><span class="o">.</span><span class="n">exists</span><span class="p">():</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">field</span><span class="p">,</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">date_error_message</span><span class="p">(</span><span class="n">lookup_type</span><span class="p">,</span> <span class="n">field</span><span class="p">,</span> <span class="n">unique_for</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">date_error_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">lookup_type</span><span class="p">,</span> <span class="n">field_name</span><span class="p">,</span> <span class="n">unique_for</span><span class="p">):</span>
|
|
<span class="n">opts</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span>
|
|
<span class="n">field</span> <span class="o">=</span> <span class="n">opts</span><span class="o">.</span><span class="n">get_field</span><span class="p">(</span><span class="n">field_name</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">ValidationError</span><span class="p">(</span>
|
|
<span class="n">message</span><span class="o">=</span><span class="n">field</span><span class="o">.</span><span class="n">error_messages</span><span class="p">[</span><span class="s2">"unique_for_date"</span><span class="p">],</span>
|
|
<span class="n">code</span><span class="o">=</span><span class="s2">"unique_for_date"</span><span class="p">,</span>
|
|
<span class="n">params</span><span class="o">=</span><span class="p">{</span>
|
|
<span class="s2">"model"</span><span class="p">:</span> <span class="bp">self</span><span class="p">,</span>
|
|
<span class="s2">"model_name"</span><span class="p">:</span> <span class="n">capfirst</span><span class="p">(</span><span class="n">opts</span><span class="o">.</span><span class="n">verbose_name</span><span class="p">),</span>
|
|
<span class="s2">"lookup_type"</span><span class="p">:</span> <span class="n">lookup_type</span><span class="p">,</span>
|
|
<span class="s2">"field"</span><span class="p">:</span> <span class="n">field_name</span><span class="p">,</span>
|
|
<span class="s2">"field_label"</span><span class="p">:</span> <span class="n">capfirst</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">verbose_name</span><span class="p">),</span>
|
|
<span class="s2">"date_field"</span><span class="p">:</span> <span class="n">unique_for</span><span class="p">,</span>
|
|
<span class="s2">"date_field_label"</span><span class="p">:</span> <span class="n">capfirst</span><span class="p">(</span><span class="n">opts</span><span class="o">.</span><span class="n">get_field</span><span class="p">(</span><span class="n">unique_for</span><span class="p">)</span><span class="o">.</span><span class="n">verbose_name</span><span class="p">),</span>
|
|
<span class="p">},</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">unique_error_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">model_class</span><span class="p">,</span> <span class="n">unique_check</span><span class="p">):</span>
|
|
<span class="n">opts</span> <span class="o">=</span> <span class="n">model_class</span><span class="o">.</span><span class="n">_meta</span>
|
|
|
|
<span class="n">params</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="s2">"model"</span><span class="p">:</span> <span class="bp">self</span><span class="p">,</span>
|
|
<span class="s2">"model_class"</span><span class="p">:</span> <span class="n">model_class</span><span class="p">,</span>
|
|
<span class="s2">"model_name"</span><span class="p">:</span> <span class="n">capfirst</span><span class="p">(</span><span class="n">opts</span><span class="o">.</span><span class="n">verbose_name</span><span class="p">),</span>
|
|
<span class="s2">"unique_check"</span><span class="p">:</span> <span class="n">unique_check</span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="c1"># A unique field</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">unique_check</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">field</span> <span class="o">=</span> <span class="n">opts</span><span class="o">.</span><span class="n">get_field</span><span class="p">(</span><span class="n">unique_check</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
|
<span class="n">params</span><span class="p">[</span><span class="s2">"field_label"</span><span class="p">]</span> <span class="o">=</span> <span class="n">capfirst</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">verbose_name</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">ValidationError</span><span class="p">(</span>
|
|
<span class="n">message</span><span class="o">=</span><span class="n">field</span><span class="o">.</span><span class="n">error_messages</span><span class="p">[</span><span class="s2">"unique"</span><span class="p">],</span>
|
|
<span class="n">code</span><span class="o">=</span><span class="s2">"unique"</span><span class="p">,</span>
|
|
<span class="n">params</span><span class="o">=</span><span class="n">params</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="c1"># unique_together</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">field_labels</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="n">capfirst</span><span class="p">(</span><span class="n">opts</span><span class="o">.</span><span class="n">get_field</span><span class="p">(</span><span class="n">f</span><span class="p">)</span><span class="o">.</span><span class="n">verbose_name</span><span class="p">)</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">unique_check</span>
|
|
<span class="p">]</span>
|
|
<span class="n">params</span><span class="p">[</span><span class="s2">"field_labels"</span><span class="p">]</span> <span class="o">=</span> <span class="n">get_text_list</span><span class="p">(</span><span class="n">field_labels</span><span class="p">,</span> <span class="n">_</span><span class="p">(</span><span class="s2">"and"</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="n">ValidationError</span><span class="p">(</span>
|
|
<span class="n">message</span><span class="o">=</span><span class="n">_</span><span class="p">(</span><span class="s2">"</span><span class="si">%(model_name)s</span><span class="s2"> with this </span><span class="si">%(field_labels)s</span><span class="s2"> already exists."</span><span class="p">),</span>
|
|
<span class="n">code</span><span class="o">=</span><span class="s2">"unique_together"</span><span class="p">,</span>
|
|
<span class="n">params</span><span class="o">=</span><span class="n">params</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">get_constraints</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="n">constraints</span> <span class="o">=</span> <span class="p">[(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">constraints</span><span class="p">)]</span>
|
|
<span class="k">for</span> <span class="n">parent_class</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">all_parents</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">parent_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">constraints</span><span class="p">:</span>
|
|
<span class="n">constraints</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">parent_class</span><span class="p">,</span> <span class="n">parent_class</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">constraints</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="n">constraints</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">validate_constraints</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exclude</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="n">constraints</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_constraints</span><span class="p">()</span>
|
|
<span class="n">using</span> <span class="o">=</span> <span class="n">router</span><span class="o">.</span><span class="n">db_for_write</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">,</span> <span class="n">instance</span><span class="o">=</span><span class="bp">self</span><span class="p">)</span>
|
|
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="k">for</span> <span class="n">model_class</span><span class="p">,</span> <span class="n">model_constraints</span> <span class="ow">in</span> <span class="n">constraints</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">constraint</span> <span class="ow">in</span> <span class="n">model_constraints</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">constraint</span><span class="o">.</span><span class="n">validate</span><span class="p">(</span><span class="n">model_class</span><span class="p">,</span> <span class="bp">self</span><span class="p">,</span> <span class="n">exclude</span><span class="o">=</span><span class="n">exclude</span><span class="p">,</span> <span class="n">using</span><span class="o">=</span><span class="n">using</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">ValidationError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="p">(</span>
|
|
<span class="nb">getattr</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="s2">"code"</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> <span class="o">==</span> <span class="s2">"unique"</span>
|
|
<span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">constraint</span><span class="o">.</span><span class="n">fields</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span>
|
|
<span class="p">):</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">constraint</span><span class="o">.</span><span class="n">fields</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="n">update_error_dict</span><span class="p">(</span><span class="n">errors</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">errors</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">ValidationError</span><span class="p">(</span><span class="n">errors</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">full_clean</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exclude</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">validate_unique</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">validate_constraints</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Call clean_fields(), clean(), validate_unique(), and</span>
|
|
<span class="sd"> validate_constraints() on the model. Raise a ValidationError for any</span>
|
|
<span class="sd"> errors that occur.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="k">if</span> <span class="n">exclude</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">exclude</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">exclude</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">exclude</span><span class="p">)</span>
|
|
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">clean_fields</span><span class="p">(</span><span class="n">exclude</span><span class="o">=</span><span class="n">exclude</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">ValidationError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="n">update_error_dict</span><span class="p">(</span><span class="n">errors</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Form.clean() is run even if other validation fails, so do the</span>
|
|
<span class="c1"># same with Model.clean() for consistency.</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">clean</span><span class="p">()</span>
|
|
<span class="k">except</span> <span class="n">ValidationError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="n">update_error_dict</span><span class="p">(</span><span class="n">errors</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Run unique checks, but only for fields that passed validation.</span>
|
|
<span class="k">if</span> <span class="n">validate_unique</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">errors</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">name</span> <span class="o">!=</span> <span class="n">NON_FIELD_ERRORS</span> <span class="ow">and</span> <span class="n">name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">exclude</span><span class="p">:</span>
|
|
<span class="n">exclude</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">validate_unique</span><span class="p">(</span><span class="n">exclude</span><span class="o">=</span><span class="n">exclude</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">ValidationError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="n">update_error_dict</span><span class="p">(</span><span class="n">errors</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Run constraints checks, but only for fields that passed validation.</span>
|
|
<span class="k">if</span> <span class="n">validate_constraints</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">errors</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">name</span> <span class="o">!=</span> <span class="n">NON_FIELD_ERRORS</span> <span class="ow">and</span> <span class="n">name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">exclude</span><span class="p">:</span>
|
|
<span class="n">exclude</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">validate_constraints</span><span class="p">(</span><span class="n">exclude</span><span class="o">=</span><span class="n">exclude</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">ValidationError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="n">update_error_dict</span><span class="p">(</span><span class="n">errors</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">errors</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">ValidationError</span><span class="p">(</span><span class="n">errors</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">clean_fields</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exclude</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Clean all fields and raise a ValidationError containing a dict</span>
|
|
<span class="sd"> of all validation errors if any occur.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="n">exclude</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">exclude</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
|
|
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">fields</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">name</span> <span class="ow">in</span> <span class="n">exclude</span> <span class="ow">or</span> <span class="n">f</span><span class="o">.</span><span class="n">generated</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="c1"># Skip validation for empty fields with blank=True. The developer</span>
|
|
<span class="c1"># is responsible for making sure they have a valid value.</span>
|
|
<span class="n">raw_value</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">blank</span> <span class="ow">and</span> <span class="n">raw_value</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">empty_values</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="c1"># Skip validation for empty fields when db_default is used.</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">raw_value</span><span class="p">,</span> <span class="n">DatabaseDefault</span><span class="p">):</span>
|
|
<span class="k">continue</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">attname</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">clean</span><span class="p">(</span><span class="n">raw_value</span><span class="p">,</span> <span class="bp">self</span><span class="p">))</span>
|
|
<span class="k">except</span> <span class="n">ValidationError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="p">[</span><span class="n">f</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="n">error_list</span>
|
|
|
|
<span class="k">if</span> <span class="n">errors</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">ValidationError</span><span class="p">(</span><span class="n">errors</span><span class="p">)</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">check</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_swappable</span><span class="p">(),</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_model</span><span class="p">(),</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_managers</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">),</span>
|
|
<span class="p">]</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">swapped</span><span class="p">:</span>
|
|
<span class="n">databases</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"databases"</span><span class="p">)</span> <span class="ow">or</span> <span class="p">[]</span>
|
|
<span class="n">errors</span> <span class="o">+=</span> <span class="p">[</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_fields</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">),</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_m2m_through_same_relationship</span><span class="p">(),</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_long_column_names</span><span class="p">(</span><span class="n">databases</span><span class="p">),</span>
|
|
<span class="p">]</span>
|
|
<span class="n">clash_errors</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_id_field</span><span class="p">(),</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_field_name_clashes</span><span class="p">(),</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_model_name_db_lookup_clashes</span><span class="p">(),</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_property_name_related_field_accessor_clashes</span><span class="p">(),</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_single_primary_key</span><span class="p">(),</span>
|
|
<span class="p">)</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">clash_errors</span><span class="p">)</span>
|
|
<span class="c1"># If there are field name clashes, hide consequent column name</span>
|
|
<span class="c1"># clashes.</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">clash_errors</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_column_name_clashes</span><span class="p">())</span>
|
|
<span class="n">errors</span> <span class="o">+=</span> <span class="p">[</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_unique_together</span><span class="p">(),</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_indexes</span><span class="p">(</span><span class="n">databases</span><span class="p">),</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_ordering</span><span class="p">(),</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_constraints</span><span class="p">(</span><span class="n">databases</span><span class="p">),</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_db_table_comment</span><span class="p">(</span><span class="n">databases</span><span class="p">),</span>
|
|
<span class="o">*</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_composite_pk</span><span class="p">(),</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_composite_pk</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">meta</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span>
|
|
<span class="n">pk</span> <span class="o">=</span> <span class="n">meta</span><span class="o">.</span><span class="n">pk</span>
|
|
|
|
<span class="k">if</span> <span class="n">meta</span><span class="o">.</span><span class="n">proxy</span> <span class="ow">or</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">pk</span><span class="p">,</span> <span class="n">CompositePrimaryKey</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="n">seen_columns</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">list</span><span class="p">)</span>
|
|
|
|
<span class="k">for</span> <span class="n">field_name</span> <span class="ow">in</span> <span class="n">pk</span><span class="o">.</span><span class="n">field_names</span><span class="p">:</span>
|
|
<span class="n">hint</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">field</span> <span class="o">=</span> <span class="n">meta</span><span class="o">.</span><span class="n">get_field</span><span class="p">(</span><span class="n">field_name</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">FieldDoesNotExist</span><span class="p">:</span>
|
|
<span class="n">field</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">field</span><span class="p">:</span>
|
|
<span class="n">hint</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">field_name</span><span class="si">!r}</span><span class="s2"> is not a valid field."</span>
|
|
<span class="k">elif</span> <span class="ow">not</span> <span class="n">field</span><span class="o">.</span><span class="n">column</span><span class="p">:</span>
|
|
<span class="n">hint</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">field_name</span><span class="si">!r}</span><span class="s2"> field has no column."</span>
|
|
<span class="k">elif</span> <span class="n">field</span><span class="o">.</span><span class="n">null</span><span class="p">:</span>
|
|
<span class="n">hint</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">field_name</span><span class="si">!r}</span><span class="s2"> field may not set 'null=True'."</span>
|
|
<span class="k">elif</span> <span class="n">field</span><span class="o">.</span><span class="n">generated</span><span class="p">:</span>
|
|
<span class="n">hint</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">field_name</span><span class="si">!r}</span><span class="s2"> field is a generated field."</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">meta</span><span class="o">.</span><span class="n">local_fields</span><span class="p">:</span>
|
|
<span class="n">hint</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">field_name</span><span class="si">!r}</span><span class="s2"> field is not a local field."</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">seen_columns</span><span class="p">[</span><span class="n">field</span><span class="o">.</span><span class="n">column</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">field_name</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">hint</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">field_name</span><span class="si">!r}</span><span class="s2"> cannot be included in the composite primary "</span>
|
|
<span class="s2">"key."</span><span class="p">,</span>
|
|
<span class="n">hint</span><span class="o">=</span><span class="n">hint</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E042"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">for</span> <span class="n">column</span><span class="p">,</span> <span class="n">field_names</span> <span class="ow">in</span> <span class="n">seen_columns</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">field_names</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">field_name</span><span class="p">,</span> <span class="o">*</span><span class="n">rest</span> <span class="o">=</span> <span class="n">field_names</span>
|
|
<span class="n">duplicates</span> <span class="o">=</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">field</span><span class="p">)</span> <span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">rest</span><span class="p">)</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">duplicates</span><span class="si">}</span><span class="s2"> cannot be included in the composite primary "</span>
|
|
<span class="s2">"key."</span><span class="p">,</span>
|
|
<span class="n">hint</span><span class="o">=</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">duplicates</span><span class="si">}</span><span class="s2"> and </span><span class="si">{</span><span class="n">field_name</span><span class="si">!r}</span><span class="s2"> are the same fields."</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E042"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_db_table_comment</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">databases</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">db_table_comment</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">[]</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">db</span> <span class="ow">in</span> <span class="n">databases</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">router</span><span class="o">.</span><span class="n">allow_migrate_model</span><span class="p">(</span><span class="n">db</span><span class="p">,</span> <span class="bp">cls</span><span class="p">):</span>
|
|
<span class="k">continue</span>
|
|
<span class="n">connection</span> <span class="o">=</span> <span class="n">connections</span><span class="p">[</span><span class="n">db</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="p">(</span>
|
|
<span class="n">connection</span><span class="o">.</span><span class="n">features</span><span class="o">.</span><span class="n">supports_comments</span>
|
|
<span class="ow">or</span> <span class="s2">"supports_comments"</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">required_db_features</span>
|
|
<span class="p">):</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Warning</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">connection</span><span class="o">.</span><span class="n">display_name</span><span class="si">}</span><span class="s2"> does not support comments on "</span>
|
|
<span class="sa">f</span><span class="s2">"tables (db_table_comment)."</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.W046"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_swappable</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Check if the swapped model exists."""</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">if</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">swapped</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">apps</span><span class="o">.</span><span class="n">get_model</span><span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">swapped</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"'</span><span class="si">%s</span><span class="s2">' is not of the form 'app_label.app_name'."</span>
|
|
<span class="o">%</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">swappable</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E001"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">LookupError</span><span class="p">:</span>
|
|
<span class="n">app_label</span><span class="p">,</span> <span class="n">model_name</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">swapped</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"."</span><span class="p">)</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"'</span><span class="si">%s</span><span class="s2">' references '</span><span class="si">%s</span><span class="s2">.</span><span class="si">%s</span><span class="s2">', which has not been "</span>
|
|
<span class="s2">"installed, or is abstract."</span>
|
|
<span class="o">%</span> <span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">swappable</span><span class="p">,</span> <span class="n">app_label</span><span class="p">,</span> <span class="n">model_name</span><span class="p">),</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E002"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_model</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">if</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">proxy</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_fields</span> <span class="ow">or</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_many_to_many</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"Proxy model '</span><span class="si">%s</span><span class="s2">' contains model fields."</span> <span class="o">%</span> <span class="bp">cls</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E017"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_managers</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Perform all manager checks."""</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">manager</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">managers</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">manager</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_fields</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Perform all field checks."""</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_fields</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">))</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_many_to_many</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="n">from_model</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_m2m_through_same_relationship</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Check if no relationship model is used by more than one m2m field.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">seen_intermediary_signatures</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
<span class="n">fields</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_many_to_many</span>
|
|
|
|
<span class="c1"># Skip when the target model wasn't found.</span>
|
|
<span class="n">fields</span> <span class="o">=</span> <span class="p">(</span><span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">fields</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">remote_field</span><span class="o">.</span><span class="n">model</span><span class="p">,</span> <span class="n">ModelBase</span><span class="p">))</span>
|
|
|
|
<span class="c1"># Skip when the relationship model wasn't found.</span>
|
|
<span class="n">fields</span> <span class="o">=</span> <span class="p">(</span><span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">fields</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">remote_field</span><span class="o">.</span><span class="n">through</span><span class="p">,</span> <span class="n">ModelBase</span><span class="p">))</span>
|
|
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">fields</span><span class="p">:</span>
|
|
<span class="n">signature</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="n">f</span><span class="o">.</span><span class="n">remote_field</span><span class="o">.</span><span class="n">model</span><span class="p">,</span>
|
|
<span class="bp">cls</span><span class="p">,</span>
|
|
<span class="n">f</span><span class="o">.</span><span class="n">remote_field</span><span class="o">.</span><span class="n">through</span><span class="p">,</span>
|
|
<span class="n">f</span><span class="o">.</span><span class="n">remote_field</span><span class="o">.</span><span class="n">through_fields</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">signature</span> <span class="ow">in</span> <span class="n">seen_intermediary_signatures</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"The model has two identical many-to-many relations "</span>
|
|
<span class="s2">"through the intermediate model '</span><span class="si">%s</span><span class="s2">'."</span>
|
|
<span class="o">%</span> <span class="n">f</span><span class="o">.</span><span class="n">remote_field</span><span class="o">.</span><span class="n">through</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">label</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E003"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">seen_intermediary_signatures</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">signature</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_id_field</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Check if `id` field is a primary key."""</span>
|
|
<span class="n">fields</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_fields</span> <span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s2">"id"</span> <span class="ow">and</span> <span class="n">f</span> <span class="o">!=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">pk</span>
|
|
<span class="p">]</span>
|
|
<span class="c1"># fields is empty or consists of the invalid "id" field</span>
|
|
<span class="k">if</span> <span class="n">fields</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">fields</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">primary_key</span> <span class="ow">and</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">pk</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s2">"id"</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">[</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"'id' can only be used as a field name if the field also "</span>
|
|
<span class="s2">"sets 'primary_key=True'."</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E004"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">[]</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_field_name_clashes</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Forbid field shadowing in multi-table inheritance."""</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">used_fields</span> <span class="o">=</span> <span class="p">{}</span> <span class="c1"># name or attname -> field</span>
|
|
|
|
<span class="c1"># Check that multi-inheritance doesn't cause field name shadowing.</span>
|
|
<span class="k">for</span> <span class="n">parent</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">all_parents</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">parent</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_fields</span><span class="p">:</span>
|
|
<span class="n">clash</span> <span class="o">=</span> <span class="n">used_fields</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> <span class="ow">or</span> <span class="n">used_fields</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span> <span class="ow">or</span> <span class="kc">None</span>
|
|
<span class="k">if</span> <span class="n">clash</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"The field '</span><span class="si">%s</span><span class="s2">' from parent model "</span>
|
|
<span class="s2">"'</span><span class="si">%s</span><span class="s2">' clashes with the field '</span><span class="si">%s</span><span class="s2">' "</span>
|
|
<span class="s2">"from parent model '</span><span class="si">%s</span><span class="s2">'."</span>
|
|
<span class="o">%</span> <span class="p">(</span><span class="n">clash</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">clash</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">_meta</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">_meta</span><span class="p">),</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E005"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="n">used_fields</span><span class="p">[</span><span class="n">f</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">f</span>
|
|
<span class="n">used_fields</span><span class="p">[</span><span class="n">f</span><span class="o">.</span><span class="n">attname</span><span class="p">]</span> <span class="o">=</span> <span class="n">f</span>
|
|
|
|
<span class="c1"># Check that fields defined in the model don't clash with fields from</span>
|
|
<span class="c1"># parents, including auto-generated fields like multi-table inheritance</span>
|
|
<span class="c1"># child accessors.</span>
|
|
<span class="k">for</span> <span class="n">parent</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">all_parents</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">parent</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">get_fields</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="n">f</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">used_fields</span><span class="p">:</span>
|
|
<span class="n">used_fields</span><span class="p">[</span><span class="n">f</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">f</span>
|
|
|
|
<span class="c1"># Check that parent links in diamond-shaped MTI models don't clash.</span>
|
|
<span class="k">for</span> <span class="n">parent_link</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">parents</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">parent_link</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="n">clash</span> <span class="o">=</span> <span class="n">used_fields</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">parent_link</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> <span class="ow">or</span> <span class="kc">None</span>
|
|
<span class="k">if</span> <span class="n">clash</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"The field '</span><span class="si">{</span><span class="n">parent_link</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">' clashes with the field "</span>
|
|
<span class="sa">f</span><span class="s2">"'</span><span class="si">{</span><span class="n">clash</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">' from model '</span><span class="si">{</span><span class="n">clash</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">_meta</span><span class="si">}</span><span class="s2">'."</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E006"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_fields</span><span class="p">:</span>
|
|
<span class="n">clash</span> <span class="o">=</span> <span class="n">used_fields</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> <span class="ow">or</span> <span class="n">used_fields</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span> <span class="ow">or</span> <span class="kc">None</span>
|
|
<span class="c1"># Note that we may detect clash between user-defined non-unique</span>
|
|
<span class="c1"># field "id" and automatically added unique field "id", both</span>
|
|
<span class="c1"># defined at the same model. This special case is considered in</span>
|
|
<span class="c1"># _check_id_field and here we ignore it.</span>
|
|
<span class="n">id_conflict</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="n">f</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s2">"id"</span> <span class="ow">and</span> <span class="n">clash</span> <span class="ow">and</span> <span class="n">clash</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s2">"id"</span> <span class="ow">and</span> <span class="n">clash</span><span class="o">.</span><span class="n">model</span> <span class="o">==</span> <span class="bp">cls</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">clash</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">id_conflict</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"The field '</span><span class="si">%s</span><span class="s2">' clashes with the field '</span><span class="si">%s</span><span class="s2">' "</span>
|
|
<span class="s2">"from model '</span><span class="si">%s</span><span class="s2">'."</span> <span class="o">%</span> <span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">clash</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">clash</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">_meta</span><span class="p">),</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="n">f</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E006"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="n">used_fields</span><span class="p">[</span><span class="n">f</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">f</span>
|
|
<span class="n">used_fields</span><span class="p">[</span><span class="n">f</span><span class="o">.</span><span class="n">attname</span><span class="p">]</span> <span class="o">=</span> <span class="n">f</span>
|
|
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_column_name_clashes</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
|
<span class="c1"># Store a list of column names which have already been used by other</span>
|
|
<span class="c1"># fields.</span>
|
|
<span class="n">used_column_names</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_fields</span><span class="p">:</span>
|
|
<span class="n">column_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">column</span>
|
|
|
|
<span class="c1"># Ensure the column name is not already in use.</span>
|
|
<span class="k">if</span> <span class="n">column_name</span> <span class="ow">and</span> <span class="n">column_name</span> <span class="ow">in</span> <span class="n">used_column_names</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"Field '</span><span class="si">%s</span><span class="s2">' has column name '</span><span class="si">%s</span><span class="s2">' that is used by "</span>
|
|
<span class="s2">"another field."</span> <span class="o">%</span> <span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">column_name</span><span class="p">),</span>
|
|
<span class="n">hint</span><span class="o">=</span><span class="s2">"Specify a 'db_column' for the field."</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E007"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">used_column_names</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">column_name</span><span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_model_name_db_lookup_clashes</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">model_name</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="vm">__name__</span>
|
|
<span class="k">if</span> <span class="n">model_name</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"_"</span><span class="p">)</span> <span class="ow">or</span> <span class="n">model_name</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s2">"_"</span><span class="p">):</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"The model name '</span><span class="si">%s</span><span class="s2">' cannot start or end with an underscore "</span>
|
|
<span class="s2">"as it collides with the query lookup syntax."</span> <span class="o">%</span> <span class="n">model_name</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E023"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">LOOKUP_SEP</span> <span class="ow">in</span> <span class="n">model_name</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"The model name '</span><span class="si">%s</span><span class="s2">' cannot contain double underscores as "</span>
|
|
<span class="s2">"it collides with the query lookup syntax."</span> <span class="o">%</span> <span class="n">model_name</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E024"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_property_name_related_field_accessor_clashes</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">property_names</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">_property_names</span>
|
|
<span class="n">related_field_accessors</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="n">f</span><span class="o">.</span><span class="n">attname</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">_get_fields</span><span class="p">(</span><span class="n">reverse</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">is_relation</span> <span class="ow">and</span> <span class="n">f</span><span class="o">.</span><span class="n">related_model</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">accessor</span> <span class="ow">in</span> <span class="n">related_field_accessors</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">accessor</span> <span class="ow">in</span> <span class="n">property_names</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"The property '</span><span class="si">%s</span><span class="s2">' clashes with a related field "</span>
|
|
<span class="s2">"accessor."</span> <span class="o">%</span> <span class="n">accessor</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E025"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_single_primary_key</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">if</span> <span class="nb">sum</span><span class="p">(</span><span class="mi">1</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_fields</span> <span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">primary_key</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"The model cannot have more than one field with "</span>
|
|
<span class="s2">"'primary_key=True'."</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E026"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_unique_together</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Check the value of "unique_together" option."""</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">unique_together</span><span class="p">,</span> <span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">list</span><span class="p">)):</span>
|
|
<span class="k">return</span> <span class="p">[</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"'unique_together' must be a list or tuple."</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E010"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="k">elif</span> <span class="nb">any</span><span class="p">(</span>
|
|
<span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">fields</span><span class="p">,</span> <span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">list</span><span class="p">))</span>
|
|
<span class="k">for</span> <span class="n">fields</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">unique_together</span>
|
|
<span class="p">):</span>
|
|
<span class="k">return</span> <span class="p">[</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"All 'unique_together' elements must be lists or tuples."</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E011"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">fields</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">unique_together</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="n">_check_local_fields</span><span class="p">(</span><span class="n">fields</span><span class="p">,</span> <span class="s2">"unique_together"</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_indexes</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">databases</span><span class="p">):</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">db</span> <span class="ow">in</span> <span class="n">databases</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">router</span><span class="o">.</span><span class="n">allow_migrate_model</span><span class="p">(</span><span class="n">db</span><span class="p">,</span> <span class="bp">cls</span><span class="p">):</span>
|
|
<span class="k">continue</span>
|
|
<span class="n">connection</span> <span class="o">=</span> <span class="n">connections</span><span class="p">[</span><span class="n">db</span><span class="p">]</span>
|
|
<span class="k">for</span> <span class="n">index</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">indexes</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">index</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">connection</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_local_fields</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">fields</span><span class="p">,</span> <span class="n">option</span><span class="p">):</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">django.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">models</span>
|
|
|
|
<span class="c1"># In order to avoid hitting the relation tree prematurely, we use our</span>
|
|
<span class="c1"># own fields_map instead of using get_field()</span>
|
|
<span class="n">forward_fields_map</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">_get_fields</span><span class="p">(</span><span class="n">reverse</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
|
|
<span class="n">forward_fields_map</span><span class="p">[</span><span class="n">field</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">field</span>
|
|
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">field</span><span class="p">,</span> <span class="s2">"attname"</span><span class="p">):</span>
|
|
<span class="n">forward_fields_map</span><span class="p">[</span><span class="n">field</span><span class="o">.</span><span class="n">attname</span><span class="p">]</span> <span class="o">=</span> <span class="n">field</span>
|
|
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">field_name</span> <span class="ow">in</span> <span class="n">fields</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">field</span> <span class="o">=</span> <span class="n">forward_fields_map</span><span class="p">[</span><span class="n">field_name</span><span class="p">]</span>
|
|
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"'</span><span class="si">%s</span><span class="s2">' refers to the nonexistent field '</span><span class="si">%s</span><span class="s2">'."</span>
|
|
<span class="o">%</span> <span class="p">(</span>
|
|
<span class="n">option</span><span class="p">,</span>
|
|
<span class="n">field_name</span><span class="p">,</span>
|
|
<span class="p">),</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E012"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">remote_field</span><span class="p">,</span> <span class="n">models</span><span class="o">.</span><span class="n">ManyToManyRel</span><span class="p">):</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"'</span><span class="si">%s</span><span class="s2">' refers to a ManyToManyField '</span><span class="si">%s</span><span class="s2">', but "</span>
|
|
<span class="s2">"ManyToManyFields are not permitted in '</span><span class="si">%s</span><span class="s2">'."</span>
|
|
<span class="o">%</span> <span class="p">(</span>
|
|
<span class="n">option</span><span class="p">,</span>
|
|
<span class="n">field_name</span><span class="p">,</span>
|
|
<span class="n">option</span><span class="p">,</span>
|
|
<span class="p">),</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E013"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">field</span><span class="p">,</span> <span class="n">models</span><span class="o">.</span><span class="n">CompositePrimaryKey</span><span class="p">):</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">option</span><span class="si">!r}</span><span class="s2"> refers to a CompositePrimaryKey "</span>
|
|
<span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">field_name</span><span class="si">!r}</span><span class="s2">, but CompositePrimaryKeys are not "</span>
|
|
<span class="sa">f</span><span class="s2">"permitted in </span><span class="si">{</span><span class="n">option</span><span class="si">!r}</span><span class="s2">."</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E048"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="p">(</span>
|
|
<span class="nb">isinstance</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">remote_field</span><span class="p">,</span> <span class="n">ForeignObjectRel</span><span class="p">)</span>
|
|
<span class="ow">and</span> <span class="n">field</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_concrete_fields</span>
|
|
<span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">from_fields</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span>
|
|
<span class="p">):</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">option</span><span class="si">!r}</span><span class="s2"> refers to a ForeignObject </span><span class="si">{</span><span class="n">field_name</span><span class="si">!r}</span><span class="s2"> with "</span>
|
|
<span class="s2">"multiple 'from_fields', which is not supported for that "</span>
|
|
<span class="s2">"option."</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E049"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_fields</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"'</span><span class="si">%s</span><span class="s2">' refers to field '</span><span class="si">%s</span><span class="s2">' which is not local to model "</span>
|
|
<span class="s2">"'</span><span class="si">%s</span><span class="s2">'."</span> <span class="o">%</span> <span class="p">(</span><span class="n">option</span><span class="p">,</span> <span class="n">field_name</span><span class="p">,</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">object_name</span><span class="p">),</span>
|
|
<span class="n">hint</span><span class="o">=</span><span class="s2">"This issue may be caused by multi-table inheritance."</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E016"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_ordering</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Check "ordering" option -- is it a list of strings and do all fields</span>
|
|
<span class="sd"> exist?</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">_ordering_clash</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">[</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"'ordering' and 'order_with_respect_to' cannot be used together."</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E021"</span><span class="p">,</span>
|
|
<span class="p">),</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="k">if</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">order_with_respect_to</span> <span class="ow">or</span> <span class="ow">not</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">ordering</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">[]</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">ordering</span><span class="p">,</span> <span class="p">(</span><span class="nb">list</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">)):</span>
|
|
<span class="k">return</span> <span class="p">[</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"'ordering' must be a tuple or list (even if you want to order by "</span>
|
|
<span class="s2">"only one field)."</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E014"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">fields</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">ordering</span>
|
|
|
|
<span class="c1"># Skip expressions and '?' fields.</span>
|
|
<span class="n">fields</span> <span class="o">=</span> <span class="p">(</span><span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">fields</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="ow">and</span> <span class="n">f</span> <span class="o">!=</span> <span class="s2">"?"</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Convert "-field" to "field".</span>
|
|
<span class="n">fields</span> <span class="o">=</span> <span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">removeprefix</span><span class="p">(</span><span class="s2">"-"</span><span class="p">)</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">fields</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Separate related fields and non-related fields.</span>
|
|
<span class="n">_fields</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">related_fields</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">fields</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">LOOKUP_SEP</span> <span class="ow">in</span> <span class="n">f</span><span class="p">:</span>
|
|
<span class="n">related_fields</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">_fields</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
|
|
<span class="n">fields</span> <span class="o">=</span> <span class="n">_fields</span>
|
|
|
|
<span class="c1"># Check related fields.</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">related_fields</span><span class="p">:</span>
|
|
<span class="n">_cls</span> <span class="o">=</span> <span class="bp">cls</span>
|
|
<span class="n">fld</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">for</span> <span class="n">part</span> <span class="ow">in</span> <span class="n">field</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">LOOKUP_SEP</span><span class="p">):</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="c1"># pk is an alias that won't be found by opts.get_field.</span>
|
|
<span class="k">if</span> <span class="n">part</span> <span class="o">==</span> <span class="s2">"pk"</span><span class="p">:</span>
|
|
<span class="n">fld</span> <span class="o">=</span> <span class="n">_cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">pk</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">fld</span> <span class="o">=</span> <span class="n">_cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">get_field</span><span class="p">(</span><span class="n">part</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">fld</span><span class="o">.</span><span class="n">is_relation</span><span class="p">:</span>
|
|
<span class="n">_cls</span> <span class="o">=</span> <span class="n">fld</span><span class="o">.</span><span class="n">path_infos</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">to_opts</span><span class="o">.</span><span class="n">model</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">_cls</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">except</span> <span class="p">(</span><span class="n">FieldDoesNotExist</span><span class="p">,</span> <span class="ne">AttributeError</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">fld</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="p">(</span>
|
|
<span class="n">fld</span><span class="o">.</span><span class="n">get_transform</span><span class="p">(</span><span class="n">part</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">fld</span><span class="o">.</span><span class="n">get_lookup</span><span class="p">(</span><span class="n">part</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span>
|
|
<span class="p">):</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"'ordering' refers to the nonexistent field, "</span>
|
|
<span class="s2">"related field, or lookup '</span><span class="si">%s</span><span class="s2">'."</span> <span class="o">%</span> <span class="n">field</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E015"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="c1"># Skip ordering on pk. This is always a valid order_by field</span>
|
|
<span class="c1"># but is an alias and therefore won't be found by opts.get_field.</span>
|
|
<span class="n">fields</span> <span class="o">=</span> <span class="p">{</span><span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">fields</span> <span class="k">if</span> <span class="n">f</span> <span class="o">!=</span> <span class="s2">"pk"</span><span class="p">}</span>
|
|
|
|
<span class="c1"># Check for invalid or nonexistent fields in ordering.</span>
|
|
<span class="n">invalid_fields</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
<span class="c1"># Any field name that is not present in field_names does not exist.</span>
|
|
<span class="c1"># Also, ordering by m2m fields is not allowed.</span>
|
|
<span class="n">opts</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span>
|
|
<span class="n">valid_fields</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span>
|
|
<span class="n">chain</span><span class="o">.</span><span class="n">from_iterable</span><span class="p">(</span>
|
|
<span class="p">(</span>
|
|
<span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">attname</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">auto_created</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">f</span><span class="o">.</span><span class="n">concrete</span><span class="p">)</span>
|
|
<span class="k">else</span> <span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">field</span><span class="o">.</span><span class="n">related_query_name</span><span class="p">(),)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">chain</span><span class="p">(</span><span class="n">opts</span><span class="o">.</span><span class="n">fields</span><span class="p">,</span> <span class="n">opts</span><span class="o">.</span><span class="n">related_objects</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="n">invalid_fields</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">fields</span> <span class="o">-</span> <span class="n">valid_fields</span><span class="p">)</span>
|
|
|
|
<span class="k">for</span> <span class="n">invalid_field</span> <span class="ow">in</span> <span class="n">invalid_fields</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"'ordering' refers to the nonexistent field, related "</span>
|
|
<span class="s2">"field, or lookup '</span><span class="si">%s</span><span class="s2">'."</span> <span class="o">%</span> <span class="n">invalid_field</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E015"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_long_column_names</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">databases</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Check that any auto-generated column names are shorter than the limits</span>
|
|
<span class="sd"> for each database in which the model will be created.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">databases</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">[]</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">allowed_len</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">db_alias</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="c1"># Find the minimum max allowed length among all specified db_aliases.</span>
|
|
<span class="k">for</span> <span class="n">db</span> <span class="ow">in</span> <span class="n">databases</span><span class="p">:</span>
|
|
<span class="c1"># skip databases where the model won't be created</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">router</span><span class="o">.</span><span class="n">allow_migrate_model</span><span class="p">(</span><span class="n">db</span><span class="p">,</span> <span class="bp">cls</span><span class="p">):</span>
|
|
<span class="k">continue</span>
|
|
<span class="n">connection</span> <span class="o">=</span> <span class="n">connections</span><span class="p">[</span><span class="n">db</span><span class="p">]</span>
|
|
<span class="n">max_name_length</span> <span class="o">=</span> <span class="n">connection</span><span class="o">.</span><span class="n">ops</span><span class="o">.</span><span class="n">max_name_length</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="n">max_name_length</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">connection</span><span class="o">.</span><span class="n">features</span><span class="o">.</span><span class="n">truncates_names</span><span class="p">:</span>
|
|
<span class="k">continue</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">allowed_len</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">allowed_len</span> <span class="o">=</span> <span class="n">max_name_length</span>
|
|
<span class="n">db_alias</span> <span class="o">=</span> <span class="n">db</span>
|
|
<span class="k">elif</span> <span class="n">max_name_length</span> <span class="o"><</span> <span class="n">allowed_len</span><span class="p">:</span>
|
|
<span class="n">allowed_len</span> <span class="o">=</span> <span class="n">max_name_length</span>
|
|
<span class="n">db_alias</span> <span class="o">=</span> <span class="n">db</span>
|
|
|
|
<span class="k">if</span> <span class="n">allowed_len</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_fields</span><span class="p">:</span>
|
|
<span class="c1"># Check if auto-generated name for the field is too long</span>
|
|
<span class="c1"># for the database.</span>
|
|
<span class="k">if</span> <span class="p">(</span>
|
|
<span class="n">f</span><span class="o">.</span><span class="n">db_column</span> <span class="ow">is</span> <span class="kc">None</span>
|
|
<span class="ow">and</span> <span class="p">(</span><span class="n">column_name</span> <span class="o">:=</span> <span class="n">f</span><span class="o">.</span><span class="n">column</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">column_name</span><span class="p">)</span> <span class="o">></span> <span class="n">allowed_len</span>
|
|
<span class="p">):</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s1">'Autogenerated column name too long for field "</span><span class="si">%s</span><span class="s1">". '</span>
|
|
<span class="s1">'Maximum length is "</span><span class="si">%s</span><span class="s1">" for database "</span><span class="si">%s</span><span class="s1">".'</span>
|
|
<span class="o">%</span> <span class="p">(</span><span class="n">column_name</span><span class="p">,</span> <span class="n">allowed_len</span><span class="p">,</span> <span class="n">db_alias</span><span class="p">),</span>
|
|
<span class="n">hint</span><span class="o">=</span><span class="s2">"Set the column name manually using 'db_column'."</span><span class="p">,</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E018"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_many_to_many</span><span class="p">:</span>
|
|
<span class="c1"># Skip nonexistent models.</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">remote_field</span><span class="o">.</span><span class="n">through</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
|
|
<span class="k">continue</span>
|
|
|
|
<span class="c1"># Check if auto-generated name for the M2M field is too long</span>
|
|
<span class="c1"># for the database.</span>
|
|
<span class="k">for</span> <span class="n">m2m</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">remote_field</span><span class="o">.</span><span class="n">through</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">local_fields</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="p">(</span>
|
|
<span class="n">m2m</span><span class="o">.</span><span class="n">db_column</span> <span class="ow">is</span> <span class="kc">None</span>
|
|
<span class="ow">and</span> <span class="p">(</span><span class="n">rel_name</span> <span class="o">:=</span> <span class="n">m2m</span><span class="o">.</span><span class="n">column</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">rel_name</span><span class="p">)</span> <span class="o">></span> <span class="n">allowed_len</span>
|
|
<span class="p">):</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">checks</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span>
|
|
<span class="s2">"Autogenerated column name too long for M2M field "</span>
|
|
<span class="s1">'"</span><span class="si">%s</span><span class="s1">". Maximum length is "</span><span class="si">%s</span><span class="s1">" for database "</span><span class="si">%s</span><span class="s1">".'</span>
|
|
<span class="o">%</span> <span class="p">(</span><span class="n">rel_name</span><span class="p">,</span> <span class="n">allowed_len</span><span class="p">,</span> <span class="n">db_alias</span><span class="p">),</span>
|
|
<span class="n">hint</span><span class="o">=</span><span class="p">(</span>
|
|
<span class="s2">"Use 'through' to create a separate model for "</span>
|
|
<span class="s2">"M2M and then set column_name using 'db_column'."</span>
|
|
<span class="p">),</span>
|
|
<span class="n">obj</span><span class="o">=</span><span class="bp">cls</span><span class="p">,</span>
|
|
<span class="nb">id</span><span class="o">=</span><span class="s2">"models.E019"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_get_expr_references</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">expr</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">expr</span><span class="p">,</span> <span class="n">Q</span><span class="p">):</span>
|
|
<span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">expr</span><span class="o">.</span><span class="n">children</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
|
|
<span class="n">lookup</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="n">child</span>
|
|
<span class="k">yield</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">lookup</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">LOOKUP_SEP</span><span class="p">))</span>
|
|
<span class="k">yield from</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_get_expr_references</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">yield from</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_get_expr_references</span><span class="p">(</span><span class="n">child</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">expr</span><span class="p">,</span> <span class="n">F</span><span class="p">):</span>
|
|
<span class="k">yield</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">expr</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">LOOKUP_SEP</span><span class="p">))</span>
|
|
<span class="k">elif</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">expr</span><span class="p">,</span> <span class="s2">"get_source_expressions"</span><span class="p">):</span>
|
|
<span class="k">for</span> <span class="n">src_expr</span> <span class="ow">in</span> <span class="n">expr</span><span class="o">.</span><span class="n">get_source_expressions</span><span class="p">():</span>
|
|
<span class="k">yield from</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_get_expr_references</span><span class="p">(</span><span class="n">src_expr</span><span class="p">)</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_constraints</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">databases</span><span class="p">):</span>
|
|
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">db</span> <span class="ow">in</span> <span class="n">databases</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">router</span><span class="o">.</span><span class="n">allow_migrate_model</span><span class="p">(</span><span class="n">db</span><span class="p">,</span> <span class="bp">cls</span><span class="p">):</span>
|
|
<span class="k">continue</span>
|
|
<span class="n">connection</span> <span class="o">=</span> <span class="n">connections</span><span class="p">[</span><span class="n">db</span><span class="p">]</span>
|
|
<span class="k">for</span> <span class="n">constraint</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">constraints</span><span class="p">:</span>
|
|
<span class="n">errors</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">constraint</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">connection</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="n">errors</span>
|
|
|
|
|
|
<span class="c1">############################################</span>
|
|
<span class="c1"># HELPER FUNCTIONS (CURRIED MODEL METHODS) #</span>
|
|
<span class="c1">############################################</span>
|
|
|
|
<span class="c1"># ORDERING METHODS #########################</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">method_set_order</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ordered_obj</span><span class="p">,</span> <span class="n">id_list</span><span class="p">,</span> <span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="n">order_wrt</span> <span class="o">=</span> <span class="n">ordered_obj</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">order_with_respect_to</span>
|
|
<span class="n">filter_args</span> <span class="o">=</span> <span class="n">order_wrt</span><span class="o">.</span><span class="n">get_forward_related_filter</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="n">ordered_obj</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">db_manager</span><span class="p">(</span><span class="n">using</span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="o">**</span><span class="n">filter_args</span><span class="p">)</span><span class="o">.</span><span class="n">bulk_update</span><span class="p">(</span>
|
|
<span class="p">[</span><span class="n">ordered_obj</span><span class="p">(</span><span class="n">pk</span><span class="o">=</span><span class="n">pk</span><span class="p">,</span> <span class="n">_order</span><span class="o">=</span><span class="n">order</span><span class="p">)</span> <span class="k">for</span> <span class="n">order</span><span class="p">,</span> <span class="n">pk</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">id_list</span><span class="p">)],</span>
|
|
<span class="p">[</span><span class="s2">"_order"</span><span class="p">],</span>
|
|
<span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">method_get_order</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ordered_obj</span><span class="p">):</span>
|
|
<span class="n">order_wrt</span> <span class="o">=</span> <span class="n">ordered_obj</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">order_with_respect_to</span>
|
|
<span class="n">filter_args</span> <span class="o">=</span> <span class="n">order_wrt</span><span class="o">.</span><span class="n">get_forward_related_filter</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="n">pk_name</span> <span class="o">=</span> <span class="n">ordered_obj</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">pk</span><span class="o">.</span><span class="n">name</span>
|
|
<span class="k">return</span> <span class="n">ordered_obj</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="o">**</span><span class="n">filter_args</span><span class="p">)</span><span class="o">.</span><span class="n">values_list</span><span class="p">(</span><span class="n">pk_name</span><span class="p">,</span> <span class="n">flat</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">make_foreign_order_accessors</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">related_model</span><span class="p">):</span>
|
|
<span class="nb">setattr</span><span class="p">(</span>
|
|
<span class="n">related_model</span><span class="p">,</span>
|
|
<span class="s2">"get_</span><span class="si">%s</span><span class="s2">_order"</span> <span class="o">%</span> <span class="n">model</span><span class="o">.</span><span class="vm">__name__</span><span class="o">.</span><span class="n">lower</span><span class="p">(),</span>
|
|
<span class="n">partialmethod</span><span class="p">(</span><span class="n">method_get_order</span><span class="p">,</span> <span class="n">model</span><span class="p">),</span>
|
|
<span class="p">)</span>
|
|
<span class="nb">setattr</span><span class="p">(</span>
|
|
<span class="n">related_model</span><span class="p">,</span>
|
|
<span class="s2">"set_</span><span class="si">%s</span><span class="s2">_order"</span> <span class="o">%</span> <span class="n">model</span><span class="o">.</span><span class="vm">__name__</span><span class="o">.</span><span class="n">lower</span><span class="p">(),</span>
|
|
<span class="n">partialmethod</span><span class="p">(</span><span class="n">method_set_order</span><span class="p">,</span> <span class="n">model</span><span class="p">),</span>
|
|
<span class="p">)</span>
|
|
|
|
|
|
<span class="c1">########</span>
|
|
<span class="c1"># MISC #</span>
|
|
<span class="c1">########</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">model_unpickle</span><span class="p">(</span><span class="n">model_id</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Used to unpickle Model subclasses with deferred fields."""</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">model_id</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
|
|
<span class="n">model</span> <span class="o">=</span> <span class="n">apps</span><span class="o">.</span><span class="n">get_model</span><span class="p">(</span><span class="o">*</span><span class="n">model_id</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># Backwards compat - the model was cached directly in earlier versions.</span>
|
|
<span class="n">model</span> <span class="o">=</span> <span class="n">model_id</span>
|
|
<span class="k">return</span> <span class="n">model</span><span class="o">.</span><span class="fm">__new__</span><span class="p">(</span><span class="n">model</span><span class="p">)</span>
|
|
|
|
|
|
<span class="n">model_unpickle</span><span class="o">.</span><span class="n">__safe_for_unpickle__</span> <span class="o">=</span> <span class="kc">True</span>
|
|
</pre></div>
|
|
|
|
<div class="clearer"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sphinxsidebar" role="navigation" aria-label="Main">
|
|
<div class="sphinxsidebarwrapper">
|
|
<p class="logo"><a href="../../../../index.html">
|
|
<img class="logo" src="../../../../_static/evennia_logo.png" alt="Logo of Evennia"/>
|
|
</a></p>
|
|
<search id="searchbox" style="display: none" role="search">
|
|
<h3 id="searchlabel">Quick search</h3>
|
|
<div class="searchformwrapper">
|
|
<form class="search" action="../../../../search.html" method="get">
|
|
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
|
<input type="submit" value="Go" />
|
|
</form>
|
|
</div>
|
|
</search>
|
|
<script>document.getElementById('searchbox').style.display = "block"</script><h3>Links</h3>
|
|
<ul>
|
|
<li><a href="https://www.evennia.com/docs/latest/index.html">Documentation Top</a> </li>
|
|
<li><a href="https://www.evennia.com">Evennia Home</a> </li>
|
|
<li><a href="https://github.com/evennia/evennia">Github</a> </li>
|
|
<li><a href="http://games.evennia.com">Game Index</a> </li>
|
|
<li>
|
|
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
|
|
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
|
|
<a href="https://evennia.blogspot.com/">Blog</a>
|
|
</li>
|
|
</ul>
|
|
<h3>Doc Versions</h3>
|
|
<ul>
|
|
|
|
<li>
|
|
<a href="https://www.evennia.com/docs/latest/index.html">latest (main branch)</a>
|
|
</li>
|
|
|
|
|
|
<li>
|
|
<a href="https://www.evennia.com/docs/5.x/index.html">v5.0.0 branch (outdated)</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="https://www.evennia.com/docs/4.x/index.html">v4.0.0 branch (outdated)</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="https://www.evennia.com/docs/3.x/index.html">v3.0.0 branch (outdated)</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="https://www.evennia.com/docs/2.x/index.html">v2.0.0 branch (outdated)</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="https://www.evennia.com/docs/1.x/index.html">v1.0.0 branch (outdated)</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="https://www.evennia.com/docs/0.x/index.html">v0.9.5 branch (outdated)</a>
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
</div>
|
|
<div class="clearer"></div>
|
|
</div>
|
|
<div class="related" role="navigation" aria-label="Related">
|
|
<h3>Navigation</h3>
|
|
<ul>
|
|
<li class="right" style="margin-right: 10px">
|
|
<a href="../../../../genindex.html" title="General Index"
|
|
>index</a></li>
|
|
<li class="right" >
|
|
<a href="../../../../py-modindex.html" title="Python Module Index"
|
|
>modules</a> |</li>
|
|
<li class="nav-item nav-item-0"><a href="../../../../index.html">Evennia</a> »</li>
|
|
<li class="nav-item nav-item-1"><a href="../../../index.html" >Module code</a> »</li>
|
|
<li class="nav-item nav-item-this"><a href="">django.db.models.base</a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="footer" role="contentinfo">
|
|
© Copyright 2024, The Evennia developer community.
|
|
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
|
|
</div>
|
|
</body>
|
|
</html> |