Source code for django.db.models.base

importcopyimportinspectimportwarningsfromfunctoolsimportpartialmethodfromitertoolsimportchainfromdjango.appsimportappsfromdjango.confimportsettingsfromdjango.coreimportchecksfromdjango.core.exceptionsimport(NON_FIELD_ERRORS,FieldDoesNotExist,FieldError,MultipleObjectsReturned,ObjectDoesNotExist,ValidationError,)fromdjango.dbimport(DEFAULT_DB_ALIAS,DJANGO_VERSION_PICKLE_KEY,DatabaseError,connection,connections,router,transaction,)fromdjango.db.models.constantsimportLOOKUP_SEPfromdjango.db.models.constraintsimportCheckConstraint,UniqueConstraintfromdjango.db.models.deletionimportCASCADE,Collectorfromdjango.db.models.fields.relatedimport(ForeignObjectRel,OneToOneField,lazy_related_operation,resolve_relation,)fromdjango.db.models.managerimportManagerfromdjango.db.models.optionsimportOptionsfromdjango.db.models.queryimportQfromdjango.db.models.signalsimport(class_prepared,post_init,post_save,pre_init,pre_save,)fromdjango.db.models.utilsimportmake_model_tuplefromdjango.utils.encodingimportforce_strfromdjango.utils.textimportcapfirst,get_text_listfromdjango.utils.translationimportgettext_lazyas_fromdjango.utils.versionimportget_versionclassDeferred:def__repr__(self):return'<Deferred field>'def__str__(self):return'<Deferred field>'DEFERRED=Deferred()defsubclass_exception(name,bases,module,attached_to):""" Create exception subclass. Used by ModelBase below. The exception is created in a way that allows it to be pickled, assuming that the returned exception class will be added as an attribute to the 'attached_to' class. """returntype(name,bases,{'__module__':module,'__qualname__':'%s.%s'%(attached_to.__qualname__,name),})def_has_contribute_to_class(value):# Only call contribute_to_class() if it's bound.returnnotinspect.isclass(value)andhasattr(value,'contribute_to_class')classModelBase(type):"""Metaclass for all models."""def__new__(cls,name,bases,attrs,**kwargs):super_new=super().__new__# Also ensure initialization is only performed for subclasses of Model# (excluding Model class itself).parents=[bforbinbasesifisinstance(b,ModelBase)]ifnotparents:returnsuper_new(cls,name,bases,attrs)# Create the class.module=attrs.pop('__module__')new_attrs={'__module__':module}classcell=attrs.pop('__classcell__',None)ifclasscellisnotNone:new_attrs['__classcell__']=classcellattr_meta=attrs.pop('Meta',None)# Pass all attrs without a (Django-specific) contribute_to_class()# method to type.__new__() so that they're properly initialized# (i.e. __set_name__()).contributable_attrs={}forobj_name,objinlist(attrs.items()):if_has_contribute_to_class(obj):contributable_attrs[obj_name]=objelse:new_attrs[obj_name]=objnew_class=super_new(cls,name,bases,new_attrs,**kwargs)abstract=getattr(attr_meta,'abstract',False)meta=attr_metaorgetattr(new_class,'Meta',None)base_meta=getattr(new_class,'_meta',None)app_label=None# Look for an application configuration to attach the model to.app_config=apps.get_containing_app_config(module)ifgetattr(meta,'app_label',None)isNone:ifapp_configisNone:ifnotabstract:raiseRuntimeError("Model class %s.%s doesn't declare an explicit ""app_label and isn't in an application in ""INSTALLED_APPS."%(module,name))else:app_label=app_config.labelnew_class.add_to_class('_meta',Options(meta,app_label))ifnotabstract:new_class.add_to_class('DoesNotExist',subclass_exception('DoesNotExist',tuple(x.DoesNotExistforxinparentsifhasattr(x,'_meta')andnotx._meta.abstract)or(ObjectDoesNotExist,),module,attached_to=new_class))new_class.add_to_class('MultipleObjectsReturned',subclass_exception('MultipleObjectsReturned',tuple(x.MultipleObjectsReturnedforxinparentsifhasattr(x,'_meta')andnotx._meta.abstract)or(MultipleObjectsReturned,),module,attached_to=new_class))ifbase_metaandnotbase_meta.abstract:# Non-abstract child classes inherit some attributes from their# non-abstract parent (unless an ABC comes before it in the# method resolution order).ifnothasattr(meta,'ordering'):new_class._meta.ordering=base_meta.orderingifnothasattr(meta,'get_latest_by'):new_class._meta.get_latest_by=base_meta.get_latest_byis_proxy=new_class._meta.proxy# If the model is a proxy, ensure that the base class# hasn't been swapped out.ifis_proxyandbase_metaandbase_meta.swapped:raiseTypeError("%s cannot proxy the swapped model '%s'."%(name,base_meta.swapped))# Add remaining attributes (those with a contribute_to_class() method)# to the class.forobj_name,objincontributable_attrs.items():new_class.add_to_class(obj_name,obj)# All the fields of any type declared on this modelnew_fields=chain(new_class._meta.local_fields,new_class._meta.local_many_to_many,new_class._meta.private_fields)field_names={f.nameforfinnew_fields}# Basic setup for proxy models.ifis_proxy:base=Noneforparentin[klsforklsinparentsifhasattr(kls,'_meta')]:ifparent._meta.abstract:ifparent._meta.fields:raiseTypeError("Abstract base class containing model fields not ""permitted for proxy model '%s'."%name)else:continueifbaseisNone:base=parentelifparent._meta.concrete_modelisnotbase._meta.concrete_model:raiseTypeError("Proxy model '%s' has more than one non-abstract model base class."%name)ifbaseisNone:raiseTypeError("Proxy model '%s' has no non-abstract model base class."%name)new_class._meta.setup_proxy(base)new_class._meta.concrete_model=base._meta.concrete_modelelse:new_class._meta.concrete_model=new_class# Collect the parent links for multi-table inheritance.parent_links={}forbaseinreversed([new_class]+parents):# Conceptually equivalent to `if base is Model`.ifnothasattr(base,'_meta'):continue# Skip concrete parent classes.ifbase!=new_classandnotbase._meta.abstract:continue# Locate OneToOneField instances.forfieldinbase._meta.local_fields:ifisinstance(field,OneToOneField):related=resolve_relation(new_class,field.remote_field.model)parent_links[make_model_tuple(related)]=field# Track fields inherited from base models.inherited_attributes=set()# Do the appropriate setup for any model parents.forbaseinnew_class.mro():ifbasenotinparentsornothasattr(base,'_meta'):# Things without _meta aren't functional models, so they're# uninteresting parents.inherited_attributes.update(base.__dict__)continueparent_fields=base._meta.local_fields+base._meta.local_many_to_manyifnotbase._meta.abstract:# Check for clashes between locally declared fields and those# on the base classes.forfieldinparent_fields:iffield.nameinfield_names:raiseFieldError('Local field %r in class %r clashes with field of ''the same name from base class %r.'%(field.name,name,base.__name__,))else:inherited_attributes.add(field.name)# Concrete classes...base=base._meta.concrete_modelbase_key=make_model_tuple(base)ifbase_keyinparent_links:field=parent_links[base_key]elifnotis_proxy:attr_name='%s_ptr'%base._meta.model_namefield=OneToOneField(base,on_delete=CASCADE,name=attr_name,auto_created=True,parent_link=True,)ifattr_nameinfield_names:raiseFieldError("Auto-generated field '%s' in class %r for ""parent_link to base class %r clashes with ""declared field of the same name."%(attr_name,name,base.__name__,))# Only add the ptr field if it's not already present;# e.g. migrations will already have it specifiedifnothasattr(new_class,attr_name):new_class.add_to_class(attr_name,field)else:field=Nonenew_class._meta.parents[base]=fieldelse:base_parents=base._meta.parents.copy()# Add fields from abstract base class if it wasn't overridden.forfieldinparent_fields:if(field.namenotinfield_namesandfield.namenotinnew_class.__dict__andfield.namenotininherited_attributes):new_field=copy.deepcopy(field)new_class.add_to_class(field.name,new_field)# Replace parent links defined on this base by the new# field. It will be appropriately resolved if required.iffield.one_to_one:forparent,parent_linkinbase_parents.items():iffield==parent_link:base_parents[parent]=new_field# Pass any non-abstract parent classes onto child.new_class._meta.parents.update(base_parents)# Inherit private fields (like GenericForeignKey) from the parent# classforfieldinbase._meta.private_fields:iffield.nameinfield_names:ifnotbase._meta.abstract:raiseFieldError('Local field %r in class %r clashes with field of ''the same name from base class %r.'%(field.name,name,base.__name__,))else:field=copy.deepcopy(field)ifnotbase._meta.abstract:field.mti_inherited=Truenew_class.add_to_class(field.name,field)# Copy indexes so that index names are unique when models extend an# abstract model.new_class._meta.indexes=[copy.deepcopy(idx)foridxinnew_class._meta.indexes]ifabstract:# Abstract base models can't be instantiated and don't appear in# the list of models for an app. We do the final setup for them a# little differently from normal models.attr_meta.abstract=Falsenew_class.Meta=attr_metareturnnew_classnew_class._prepare()new_class._meta.apps.register_model(new_class._meta.app_label,new_class)returnnew_classdefadd_to_class(cls,name,value):if_has_contribute_to_class(value):value.contribute_to_class(cls,name)else:setattr(cls,name,value)def_prepare(cls):"""Create some methods once self._meta has been populated."""opts=cls._metaopts._prepare(cls)ifopts.order_with_respect_to:cls.get_next_in_order=partialmethod(cls._get_next_or_previous_in_order,is_next=True)cls.get_previous_in_order=partialmethod(cls._get_next_or_previous_in_order,is_next=False)# Defer creating accessors on the foreign class until it has been# created and registered. If remote_field is None, we're ordering# with respect to a GenericForeignKey and don't know what the# foreign class is - we'll add those accessors later in# contribute_to_class().ifopts.order_with_respect_to.remote_field:wrt=opts.order_with_respect_toremote=wrt.remote_field.modellazy_related_operation(make_foreign_order_accessors,cls,remote)# Give the class a docstring -- its definition.ifcls.__doc__isNone:cls.__doc__="%s(%s)"%(cls.__name__,", ".join(f.nameforfinopts.fields))get_absolute_url_override=settings.ABSOLUTE_URL_OVERRIDES.get(opts.label_lower)ifget_absolute_url_override:setattr(cls,'get_absolute_url',get_absolute_url_override)ifnotopts.managers:ifany(f.name=='objects'forfinopts.fields):raiseValueError("Model %s must specify a custom Manager, because it has a ""field named 'objects'."%cls.__name__)manager=Manager()manager.auto_created=Truecls.add_to_class('objects',manager)# Set the name of _meta.indexes. This can't be done in# Options.contribute_to_class() because fields haven't been added to# the model at that point.forindexincls._meta.indexes:ifnotindex.name:index.set_name_with_model(cls)class_prepared.send(sender=cls)@propertydef_base_manager(cls):returncls._meta.base_manager@propertydef_default_manager(cls):returncls._meta.default_managerclassModelStateFieldsCacheDescriptor:def__get__(self,instance,cls=None):ifinstanceisNone:returnselfres=instance.fields_cache={}returnresclassModelState:"""Store model instance state."""db=None# If true, uniqueness validation checks will consider this a new, unsaved# object. Necessary for correct validation of new instances of objects with# explicit (non-auto) PKs. This impacts validation only; it has no effect# on the actual save.adding=Truefields_cache=ModelStateFieldsCacheDescriptor()

[docs]classModel(metaclass=ModelBase):def__init__(self,*args,**kwargs):# Alias some things as locals to avoid repeat global lookupscls=self.__class__opts=self._meta_setattr=setattr_DEFERRED=DEFERREDpre_init.send(sender=cls,args=args,kwargs=kwargs)# Set up the storage for instance stateself._state=ModelState()# There is a rather weird disparity here; if kwargs, it's set, then args# overrides it. It should be one or the other; don't duplicate the work# The reason for the kwargs check is that standard iterator passes in by# args, and instantiation for iteration is 33% faster.iflen(args)>len(opts.concrete_fields):# Daft, but matches old exception sans the err msg.raiseIndexError("Number of args exceeds number of fields")ifnotkwargs:fields_iter=iter(opts.concrete_fields)# The ordering of the zip calls matter - zip throws StopIteration# when an iter throws it. So if the first iter throws it, the second# is *not* consumed. We rely on this, so don't change the order# without changing the logic.forval,fieldinzip(args,fields_iter):ifvalis_DEFERRED:continue_setattr(self,field.attname,val)else:# Slower, kwargs-ready version.fields_iter=iter(opts.fields)forval,fieldinzip(args,fields_iter):ifvalis_DEFERRED:continue_setattr(self,field.attname,val)kwargs.pop(field.name,None)# Now we're left with the unprocessed fields that *must* come from# keywords, or default.forfieldinfields_iter:is_related_object=False# Virtual fieldiffield.attnamenotinkwargsandfield.columnisNone:continueifkwargs:ifisinstance(field.remote_field,ForeignObjectRel):try:# Assume object instance was passed in.rel_obj=kwargs.pop(field.name)is_related_object=TrueexceptKeyError:try:# Object instance wasn't passed in -- must be an ID.val=kwargs.pop(field.attname)exceptKeyError:val=field.get_default()else:# Object instance was passed in. Special case: You can# pass in "None" for related objects if it's allowed.ifrel_objisNoneandfield.null:val=Noneelse:try:val=kwargs.pop(field.attname)exceptKeyError:# This is done with an exception rather than the# default argument on pop because we don't want# get_default() to be evaluated, and then not used.# Refs #12057.val=field.get_default()else:val=field.get_default()ifis_related_object:# If we are passed a related instance, set it using the# field.name instead of field.attname (e.g. "user" instead of# "user_id") so that the object gets properly cached (and type# checked) by the RelatedObjectDescriptor.ifrel_objisnot_DEFERRED:_setattr(self,field.name,rel_obj)else:ifvalisnot_DEFERRED:_setattr(self,field.attname,val)ifkwargs:property_names=opts._property_namesforpropintuple(kwargs):try:# Any remaining kwargs must correspond to properties or# virtual fields.ifpropinproperty_namesoropts.get_field(prop):ifkwargs[prop]isnot_DEFERRED:_setattr(self,prop,kwargs[prop])delkwargs[prop]except(AttributeError,FieldDoesNotExist):passforkwarginkwargs:raiseTypeError("%s() got an unexpected keyword argument '%s'"%(cls.__name__,kwarg))super().__init__()post_init.send(sender=cls,instance=self)

def__reduce__(self):data=self.__getstate__()data[DJANGO_VERSION_PICKLE_KEY]=get_version()class_id=self._meta.app_label,self._meta.object_namereturnmodel_unpickle,(class_id,),datadef__getstate__(self):"""Hook to allow choosing the attributes to pickle."""returnself.__dict__def__setstate__(self,state):msg=Nonepickled_version=state.get(DJANGO_VERSION_PICKLE_KEY)ifpickled_version:current_version=get_version()ifcurrent_version!=pickled_version:msg=("Pickled model instance's Django version %s does not match ""the current version %s."%(pickled_version,current_version))else:msg="Pickled model instance's Django version is not specified."ifmsg:warnings.warn(msg,RuntimeWarning,stacklevel=2)self.__dict__.update(state)def_get_pk_val(self,meta=None):meta=metaorself._metareturngetattr(self,meta.pk.attname)def_set_pk_val(self,value):returnsetattr(self,self._meta.pk.attname,value)pk=property(_get_pk_val,_set_pk_val)

[docs]defget_deferred_fields(self):""" Return a set containing names of deferred fields for this instance. """return{f.attnameforfinself._meta.concrete_fieldsiff.attnamenotinself.__dict__}

[docs]defrefresh_from_db(self,using=None,fields=None):""" Reload field values from the database. By default, the reloading happens from the database this instance was loaded from, or by the read router if this instance wasn't loaded from any database. The using parameter will override the default. Fields can be used to specify which fields to reload. The fields should be an iterable of field attnames. If fields is None, then all non-deferred fields are reloaded. When accessing deferred fields of an instance, the deferred loading of the field will call this method. """iffieldsisNone:self._prefetched_objects_cache={}else:prefetched_objects_cache=getattr(self,'_prefetched_objects_cache',())forfieldinfields:iffieldinprefetched_objects_cache:delprefetched_objects_cache[field]fields.remove(field)ifnotfields:returnifany(LOOKUP_SEPinfforfinfields):raiseValueError('Found "%s" in fields argument. Relations and transforms ''are not allowed in fields.'%LOOKUP_SEP)hints={'instance':self}db_instance_qs=self.__class__._base_manager.db_manager(using,hints=hints).filter(pk=self.pk)# Use provided fields, if not set then reload all non-deferred fields.deferred_fields=self.get_deferred_fields()iffieldsisnotNone:fields=list(fields)db_instance_qs=db_instance_qs.only(*fields)elifdeferred_fields:fields=[f.attnameforfinself._meta.concrete_fieldsiff.attnamenotindeferred_fields]db_instance_qs=db_instance_qs.only(*fields)db_instance=db_instance_qs.get()non_loaded_fields=db_instance.get_deferred_fields()forfieldinself._meta.concrete_fields:iffield.attnameinnon_loaded_fields:# This field wasn't refreshed - skip ahead.continuesetattr(self,field.attname,getattr(db_instance,field.attname))# Clear cached foreign keys.iffield.is_relationandfield.is_cached(self):field.delete_cached_value(self)# Clear cached relations.forfieldinself._meta.related_objects:iffield.is_cached(self):field.delete_cached_value(self)self._state.db=db_instance._state.db

defserializable_value(self,field_name):""" Return the value of the field name for this instance. If the field is a foreign key, return the id value instead of the object. If there's no Field object with this name on the model, return the model attribute's value. Used to serialize a field's value (in the serializer, or form output, for example). Normally, you would just access the attribute directly and not use this method. """try:field=self._meta.get_field(field_name)exceptFieldDoesNotExist:returngetattr(self,field_name)returngetattr(self,field.attname)

[docs]defsave(self,force_insert=False,force_update=False,using=None,update_fields=None):""" Save the current instance. Override this in a subclass if you want to control the saving process. The 'force_insert' and 'force_update' parameters can be used to insist that the "save" must be an SQL insert or update (or equivalent for non-SQL backends), respectively. Normally, they should not be set. """# Ensure that a model instance without a PK hasn't been assigned to# a ForeignKey or OneToOneField on this model. If the field is# nullable, allowing the save() would result in silent data loss.forfieldinself._meta.concrete_fields:# If the related field isn't cached, then an instance hasn't# been assigned and there's no need to worry about this check.iffield.is_relationandfield.is_cached(self):obj=getattr(self,field.name,None)# A pk may have been assigned manually to a model instance not# saved to the database (or auto-generated in a case like# UUIDField), but we allow the save to proceed and rely on the# database to raise an IntegrityError if applicable. If# constraints aren't supported by the database, there's the# unavoidable risk of data corruption.ifobjandobj.pkisNone:# Remove the object from a related instance cache.ifnotfield.remote_field.multiple:field.remote_field.delete_cached_value(obj)raiseValueError("save() prohibited to prevent data loss due to ""unsaved related object '%s'."%field.name)# If the relationship's pk/to_field was changed, clear the# cached relationship.ifobjandgetattr(obj,field.target_field.attname)!=getattr(self,field.attname):field.delete_cached_value(self)using=usingorrouter.db_for_write(self.__class__,instance=self)ifforce_insertand(force_updateorupdate_fields):raiseValueError("Cannot force both insert and updating in model saving.")deferred_fields=self.get_deferred_fields()ifupdate_fieldsisnotNone:# If update_fields is empty, skip the save. We do also check for# no-op saves later on for inheritance cases. This bailout is# still needed for skipping signal sending.ifnotupdate_fields:returnupdate_fields=frozenset(update_fields)field_names=set()forfieldinself._meta.fields:ifnotfield.primary_key:field_names.add(field.name)iffield.name!=field.attname:field_names.add(field.attname)non_model_fields=update_fields.difference(field_names)ifnon_model_fields:raiseValueError("The following fields do not exist in this ""model or are m2m fields: %s"%', '.join(non_model_fields))# If saving to the same database, and this model is deferred, then# automatically do a "update_fields" save on the loaded fields.elifnotforce_insertanddeferred_fieldsandusing==self._state.db:field_names=set()forfieldinself._meta.concrete_fields:ifnotfield.primary_keyandnothasattr(field,'through'):field_names.add(field.attname)loaded_fields=field_names.difference(deferred_fields)ifloaded_fields:update_fields=frozenset(loaded_fields)self.save_base(using=using,force_insert=force_insert,force_update=force_update,update_fields=update_fields)

save.alters_data=Truedefsave_base(self,raw=False,force_insert=False,force_update=False,using=None,update_fields=None):""" Handle the parts of saving which should be done only once per save, yet need to be done in raw saves, too. This includes some sanity checks and signal sending. The 'raw' argument is telling save_base not to save any parent models and not to do any changes to the values before save. This is used by fixture loading. """using=usingorrouter.db_for_write(self.__class__,instance=self)assertnot(force_insertand(force_updateorupdate_fields))assertupdate_fieldsisNoneorupdate_fieldscls=origin=self.__class__# Skip proxies, but keep the origin as the proxy model.ifcls._meta.proxy:cls=cls._meta.concrete_modelmeta=cls._metaifnotmeta.auto_created:pre_save.send(sender=origin,instance=self,raw=raw,using=using,update_fields=update_fields,)# A transaction isn't needed if one query is issued.ifmeta.parents:context_manager=transaction.atomic(using=using,savepoint=False)else:context_manager=transaction.mark_for_rollback_on_error(using=using)withcontext_manager:parent_inserted=Falseifnotraw:parent_inserted=self._save_parents(cls,using,update_fields)updated=self._save_table(raw,cls,force_insertorparent_inserted,force_update,using,update_fields,)# Store the database on which the object was savedself._state.db=using# Once saved, this is no longer a to-be-added instance.self._state.adding=False# Signal that the save is completeifnotmeta.auto_created:post_save.send(sender=origin,instance=self,created=(notupdated),update_fields=update_fields,raw=raw,using=using,)save_base.alters_data=Truedef_save_parents(self,cls,using,update_fields):"""Save all the parents of cls using values from self."""meta=cls._metainserted=Falseforparent,fieldinmeta.parents.items():# Make sure the link fields are synced between parent and self.if(fieldandgetattr(self,parent._meta.pk.attname)isNoneandgetattr(self,field.attname)isnotNone):setattr(self,parent._meta.pk.attname,getattr(self,field.attname))parent_inserted=self._save_parents(cls=parent,using=using,update_fields=update_fields)updated=self._save_table(cls=parent,using=using,update_fields=update_fields,force_insert=parent_inserted,)ifnotupdated:inserted=True# Set the parent's PK value to self.iffield:setattr(self,field.attname,self._get_pk_val(parent._meta))# Since we didn't have an instance of the parent handy set# attname directly, bypassing the descriptor. Invalidate# the related object cache, in case it's been accidentally# populated. A fresh instance will be re-built from the# database if necessary.iffield.is_cached(self):field.delete_cached_value(self)returninserteddef_save_table(self,raw=False,cls=None,force_insert=False,force_update=False,using=None,update_fields=None):""" Do the heavy-lifting involved in saving. Update or insert the data for a single table. """meta=cls._metanon_pks=[fforfinmeta.local_concrete_fieldsifnotf.primary_key]ifupdate_fields:non_pks=[fforfinnon_pksiff.nameinupdate_fieldsorf.attnameinupdate_fields]pk_val=self._get_pk_val(meta)ifpk_valisNone:pk_val=meta.pk.get_pk_value_on_save(self)setattr(self,meta.pk.attname,pk_val)pk_set=pk_valisnotNoneifnotpk_setand(force_updateorupdate_fields):raiseValueError("Cannot force an update in save() with no primary key.")updated=False# If possible, try an UPDATE. If that doesn't update anything, do an INSERT.ifpk_setandnotforce_insert:base_qs=cls._base_manager.using(using)values=[(f,None,(getattr(self,f.attname)ifrawelsef.pre_save(self,False)))forfinnon_pks]forced_update=update_fieldsorforce_updateupdated=self._do_update(base_qs,using,pk_val,values,update_fields,forced_update)ifforce_updateandnotupdated:raiseDatabaseError("Forced update did not affect any rows.")ifupdate_fieldsandnotupdated:raiseDatabaseError("Save with update_fields did not affect any rows.")ifnotupdated:ifmeta.order_with_respect_to:# If this is a model with an order_with_respect_to# autopopulate the _order fieldfield=meta.order_with_respect_tofilter_args=field.get_filter_kwargs_for_object(self)order_value=cls._base_manager.using(using).filter(**filter_args).count()self._order=order_valuefields=meta.local_concrete_fieldsifnotpk_set:fields=[fforfinfieldsiffisnotmeta.auto_field]update_pk=meta.auto_fieldandnotpk_setresult=self._do_insert(cls._base_manager,using,fields,update_pk,raw)ifupdate_pk:setattr(self,meta.pk.attname,result)returnupdateddef_do_update(self,base_qs,using,pk_val,values,update_fields,forced_update):""" Try to update the model. Return True if the model was updated (if an update query was done and a matching row was found in the DB). """filtered=base_qs.filter(pk=pk_val)ifnotvalues:# We can end up here when saving a model in inheritance chain where# update_fields doesn't target any field in current model. In that# case we just say the update succeeded. Another case ending up here# is a model with just PK - in that case check that the PK still# exists.returnupdate_fieldsisnotNoneorfiltered.exists()ifself._meta.select_on_saveandnotforced_update:return(filtered.exists()and# It may happen that the object is deleted from the DB right after# this check, causing the subsequent UPDATE to return zero matching# rows. The same result can occur in some rare cases when the# database returns zero despite the UPDATE being executed# successfully (a row is matched and updated). In order to# distinguish these two cases, the object's existence in the# database is again checked for if the UPDATE query returns 0.(filtered._update(values)>0orfiltered.exists()))returnfiltered._update(values)>0def_do_insert(self,manager,using,fields,update_pk,raw):""" Do an INSERT. If update_pk is defined then this method should return the new pk for the model. """returnmanager._insert([self],fields=fields,return_id=update_pk,using=using,raw=raw)

[docs]defdelete(self,using=None,keep_parents=False):using=usingorrouter.db_for_write(self.__class__,instance=self)assertself.pkisnotNone,("%s object can't be deleted because its %s attribute is set to None."%(self._meta.object_name,self._meta.pk.attname))collector=Collector(using=using)collector.collect([self],keep_parents=keep_parents)returncollector.delete()

delete.alters_data=Truedef_get_FIELD_display(self,field):value=getattr(self,field.attname)# force_str() to coerce lazy strings.returnforce_str(dict(field.flatchoices).get(value,value),strings_only=True)def_get_next_or_previous_by_FIELD(self,field,is_next,**kwargs):ifnotself.pk:raiseValueError("get_next/get_previous cannot be used on unsaved objects.")op='gt'ifis_nextelse'lt'order=''ifis_nextelse'-'param=getattr(self,field.attname)q=Q(**{'%s__%s'%(field.name,op):param})q=q|Q(**{field.name:param,'pk__%s'%op:self.pk})qs=self.__class__._default_manager.using(self._state.db).filter(**kwargs).filter(q).order_by('%s%s'%(order,field.name),'%spk'%order)try:returnqs[0]exceptIndexError:raiseself.DoesNotExist("%s matching query does not exist."%self.__class__._meta.object_name)def_get_next_or_previous_in_order(self,is_next):cachename="__%s_order_cache"%is_nextifnothasattr(self,cachename):op='gt'ifis_nextelse'lt'order='_order'ifis_nextelse'-_order'order_field=self._meta.order_with_respect_tofilter_args=order_field.get_filter_kwargs_for_object(self)obj=self.__class__._default_manager.filter(**filter_args).filter(**{'_order__%s'%op:self.__class__._default_manager.values('_order').filter(**{self._meta.pk.name:self.pk})}).order_by(order)[:1].get()setattr(self,cachename,obj)returngetattr(self,cachename)defprepare_database_save(self,field):ifself.pkisNone:raiseValueError("Unsaved model instance %r cannot be used in an ORM query."%self)returngetattr(self,field.remote_field.get_related_field().attname)

[docs]defclean(self):""" Hook for doing any extra model-wide validation after clean() has been called on every field by self.clean_fields. Any ValidationError raised by this method will not be associated with a particular field; it will have a special-case association with the field defined by NON_FIELD_ERRORS. """pass

[docs]defvalidate_unique(self,exclude=None):""" Check unique constraints on the model and raise ValidationError if any failed. """unique_checks,date_checks=self._get_unique_checks(exclude=exclude)errors=self._perform_unique_checks(unique_checks)date_errors=self._perform_date_checks(date_checks)fork,vindate_errors.items():errors.setdefault(k,[]).extend(v)iferrors:raiseValidationError(errors)

def_get_unique_checks(self,exclude=None):""" Return a list of checks to perform. Since validate_unique() could be called from a ModelForm, some fields may have been excluded; we can't perform a unique check on a model that is missing fields involved in that check. Fields that did not validate should also be excluded, but they need to be passed in via the exclude argument. """ifexcludeisNone:exclude=[]unique_checks=[]unique_togethers=[(self.__class__,self._meta.unique_together)]constraints=[(self.__class__,self._meta.constraints)]forparent_classinself._meta.get_parent_list():ifparent_class._meta.unique_together:unique_togethers.append((parent_class,parent_class._meta.unique_together))ifparent_class._meta.constraints:constraints.append((parent_class,parent_class._meta.constraints))formodel_class,unique_togetherinunique_togethers:forcheckinunique_together:ifnotany(nameinexcludefornameincheck):# Add the check if the field isn't excluded.unique_checks.append((model_class,tuple(check)))formodel_class,model_constraintsinconstraints:forconstraintinmodel_constraints:if(isinstance(constraint,UniqueConstraint)and# Partial unique constraints can't be validated.constraint.conditionisNoneandnotany(nameinexcludefornameinconstraint.fields)):unique_checks.append((model_class,constraint.fields))# These are checks for the unique_for_<date/year/month>.date_checks=[]# Gather a list of checks for fields declared as unique and add them to# the list of checks.fields_with_class=[(self.__class__,self._meta.local_fields)]forparent_classinself._meta.get_parent_list():fields_with_class.append((parent_class,parent_class._meta.local_fields))formodel_class,fieldsinfields_with_class:forfinfields:name=f.nameifnameinexclude:continueiff.unique:unique_checks.append((model_class,(name,)))iff.unique_for_dateandf.unique_for_datenotinexclude:date_checks.append((model_class,'date',name,f.unique_for_date))iff.unique_for_yearandf.unique_for_yearnotinexclude:date_checks.append((model_class,'year',name,f.unique_for_year))iff.unique_for_monthandf.unique_for_monthnotinexclude:date_checks.append((model_class,'month',name,f.unique_for_month))returnunique_checks,date_checksdef_perform_unique_checks(self,unique_checks):errors={}formodel_class,unique_checkinunique_checks:# Try to look up an existing object with the same values as this# object's values for all the unique field.lookup_kwargs={}forfield_nameinunique_check:f=self._meta.get_field(field_name)lookup_value=getattr(self,f.attname)# TODO: Handle multiple backends with different feature flags.if(lookup_valueisNoneor(lookup_value==''andconnection.features.interprets_empty_strings_as_nulls)):# no value, skip the lookupcontinueiff.primary_keyandnotself._state.adding:# no need to check for unique primary key when editingcontinuelookup_kwargs[str(field_name)]=lookup_value# some fields were skipped, no reason to do the checkiflen(unique_check)!=len(lookup_kwargs):continueqs=model_class._default_manager.filter(**lookup_kwargs)# Exclude the current object from the query if we are editing an# instance (as opposed to creating a new one)# Note that we need to use the pk as defined by model_class, not# self.pk. These can be different fields because model inheritance# allows single model to have effectively multiple primary keys.# Refs #17615.model_class_pk=self._get_pk_val(model_class._meta)ifnotself._state.addingandmodel_class_pkisnotNone:qs=qs.exclude(pk=model_class_pk)ifqs.exists():iflen(unique_check)==1:key=unique_check[0]else:key=NON_FIELD_ERRORSerrors.setdefault(key,[]).append(self.unique_error_message(model_class,unique_check))returnerrorsdef_perform_date_checks(self,date_checks):errors={}formodel_class,lookup_type,field,unique_forindate_checks:lookup_kwargs={}# there's a ticket to add a date lookup, we can remove this special# case if that makes it's way indate=getattr(self,unique_for)ifdateisNone:continueiflookup_type=='date':lookup_kwargs['%s__day'%unique_for]=date.daylookup_kwargs['%s__month'%unique_for]=date.monthlookup_kwargs['%s__year'%unique_for]=date.yearelse:lookup_kwargs['%s__%s'%(unique_for,lookup_type)]=getattr(date,lookup_type)lookup_kwargs[field]=getattr(self,field)qs=model_class._default_manager.filter(**lookup_kwargs)# Exclude the current object from the query if we are editing an# instance (as opposed to creating a new one)ifnotself._state.addingandself.pkisnotNone:qs=qs.exclude(pk=self.pk)ifqs.exists():errors.setdefault(field,[]).append(self.date_error_message(lookup_type,field,unique_for))returnerrorsdefdate_error_message(self,lookup_type,field_name,unique_for):opts=self._metafield=opts.get_field(field_name)returnValidationError(message=field.error_messages['unique_for_date'],code='unique_for_date',params={'model':self,'model_name':capfirst(opts.verbose_name),'lookup_type':lookup_type,'field':field_name,'field_label':capfirst(field.verbose_name),'date_field':unique_for,'date_field_label':capfirst(opts.get_field(unique_for).verbose_name),})defunique_error_message(self,model_class,unique_check):opts=model_class._metaparams={'model':self,'model_class':model_class,'model_name':capfirst(opts.verbose_name),'unique_check':unique_check,}# A unique fieldiflen(unique_check)==1:field=opts.get_field(unique_check[0])params['field_label']=capfirst(field.verbose_name)returnValidationError(message=field.error_messages['unique'],code='unique',params=params,)# unique_togetherelse:field_labels=[capfirst(opts.get_field(f).verbose_name)forfinunique_check]params['field_labels']=get_text_list(field_labels,_('and'))returnValidationError(message=_("%(model_name)s with this %(field_labels)s already exists."),code='unique_together',params=params,)

[docs]deffull_clean(self,exclude=None,validate_unique=True):""" Call clean_fields(), clean(), and validate_unique() on the model. Raise a ValidationError for any errors that occur. """errors={}ifexcludeisNone:exclude=[]else:exclude=list(exclude)try:self.clean_fields(exclude=exclude)exceptValidationErrorase:errors=e.update_error_dict(errors)# Form.clean() is run even if other validation fails, so do the# same with Model.clean() for consistency.try:self.clean()exceptValidationErrorase:errors=e.update_error_dict(errors)# Run unique checks, but only for fields that passed validation.ifvalidate_unique:fornameinerrors:ifname!=NON_FIELD_ERRORSandnamenotinexclude:exclude.append(name)try:self.validate_unique(exclude=exclude)exceptValidationErrorase:errors=e.update_error_dict(errors)iferrors:raiseValidationError(errors)

[docs]defclean_fields(self,exclude=None):""" Clean all fields and raise a ValidationError containing a dict of all validation errors if any occur. """ifexcludeisNone:exclude=[]errors={}forfinself._meta.fields:iff.nameinexclude:continue# Skip validation for empty fields with blank=True. The developer# is responsible for making sure they have a valid value.raw_value=getattr(self,f.attname)iff.blankandraw_valueinf.empty_values:continuetry:setattr(self,f.attname,f.clean(raw_value,self))exceptValidationErrorase:errors[f.name]=e.error_listiferrors:raiseValidationError(errors)

@classmethoddefcheck(cls,**kwargs):errors=[*cls._check_swappable(),*cls._check_model(),*cls._check_managers(**kwargs)]ifnotcls._meta.swapped:errors+=[*cls._check_fields(**kwargs),*cls._check_m2m_through_same_relationship(),*cls._check_long_column_names(),]clash_errors=(*cls._check_id_field(),*cls._check_field_name_clashes(),*cls._check_model_name_db_lookup_clashes(),*cls._check_property_name_related_field_accessor_clashes(),*cls._check_single_primary_key(),)errors.extend(clash_errors)# If there are field name clashes, hide consequent column name# clashes.ifnotclash_errors:errors.extend(cls._check_column_name_clashes())errors+=[*cls._check_index_together(),*cls._check_unique_together(),*cls._check_indexes(),*cls._check_ordering(),*cls._check_constraints(),]returnerrors@classmethoddef_check_swappable(cls):"""Check if the swapped model exists."""errors=[]ifcls._meta.swapped:try:apps.get_model(cls._meta.swapped)exceptValueError:errors.append(checks.Error("'%s' is not of the form 'app_label.app_name'."%cls._meta.swappable,id='models.E001',))exceptLookupError:app_label,model_name=cls._meta.swapped.split('.')errors.append(checks.Error("'%s' references '%s.%s', which has not been ""installed, or is abstract."%(cls._meta.swappable,app_label,model_name),id='models.E002',))returnerrors@classmethoddef_check_model(cls):errors=[]ifcls._meta.proxy:ifcls._meta.local_fieldsorcls._meta.local_many_to_many:errors.append(checks.Error("Proxy model '%s' contains model fields."%cls.__name__,id='models.E017',))returnerrors@classmethoddef_check_managers(cls,**kwargs):"""Perform all manager checks."""errors=[]formanagerincls._meta.managers:errors.extend(manager.check(**kwargs))returnerrors@classmethoddef_check_fields(cls,**kwargs):"""Perform all field checks."""errors=[]forfieldincls._meta.local_fields:errors.extend(field.check(**kwargs))forfieldincls._meta.local_many_to_many:errors.extend(field.check(from_model=cls,**kwargs))returnerrors@classmethoddef_check_m2m_through_same_relationship(cls):""" Check if no relationship model is used by more than one m2m field. """errors=[]seen_intermediary_signatures=[]fields=cls._meta.local_many_to_many# Skip when the target model wasn't found.fields=(fforfinfieldsifisinstance(f.remote_field.model,ModelBase))# Skip when the relationship model wasn't found.fields=(fforfinfieldsifisinstance(f.remote_field.through,ModelBase))forfinfields:signature=(f.remote_field.model,cls,f.remote_field.through,f.remote_field.through_fields)ifsignatureinseen_intermediary_signatures:errors.append(checks.Error("The model has two identical many-to-many relations ""through the intermediate model '%s'."%f.remote_field.through._meta.label,obj=cls,id='models.E003',))else:seen_intermediary_signatures.append(signature)returnerrors@classmethoddef_check_id_field(cls):"""Check if `id` field is a primary key."""fields=[fforfincls._meta.local_fieldsiff.name=='id'andf!=cls._meta.pk]# fields is empty or consists of the invalid "id" fieldiffieldsandnotfields[0].primary_keyandcls._meta.pk.name=='id':return[checks.Error("'id' can only be used as a field name if the field also ""sets 'primary_key=True'.",obj=cls,id='models.E004',)]else:return[]@classmethoddef_check_field_name_clashes(cls):"""Forbid field shadowing in multi-table inheritance."""errors=[]used_fields={}# name or attname -> field# Check that multi-inheritance doesn't cause field name shadowing.forparentincls._meta.get_parent_list():forfinparent._meta.local_fields:clash=used_fields.get(f.name)orused_fields.get(f.attname)orNoneifclash:errors.append(checks.Error("The field '%s' from parent model ""'%s' clashes with the field '%s' ""from parent model '%s'."%(clash.name,clash.model._meta,f.name,f.model._meta),obj=cls,id='models.E005',))used_fields[f.name]=fused_fields[f.attname]=f# Check that fields defined in the model don't clash with fields from# parents, including auto-generated fields like multi-table inheritance# child accessors.forparentincls._meta.get_parent_list():forfinparent._meta.get_fields():iffnotinused_fields:used_fields[f.name]=fforfincls._meta.local_fields:clash=used_fields.get(f.name)orused_fields.get(f.attname)orNone# Note that we may detect clash between user-defined non-unique# field "id" and automatically added unique field "id", both# defined at the same model. This special case is considered in# _check_id_field and here we ignore it.id_conflict=f.name=="id"andclashandclash.name=="id"andclash.model==clsifclashandnotid_conflict:errors.append(checks.Error("The field '%s' clashes with the field '%s' ""from model '%s'."%(f.name,clash.name,clash.model._meta),obj=f,id='models.E006',))used_fields[f.name]=fused_fields[f.attname]=freturnerrors@classmethoddef_check_column_name_clashes(cls):# Store a list of column names which have already been used by other fields.used_column_names=[]errors=[]forfincls._meta.local_fields:_,column_name=f.get_attname_column()# Ensure the column name is not already in use.ifcolumn_nameandcolumn_nameinused_column_names:errors.append(checks.Error("Field '%s' has column name '%s' that is used by ""another field."%(f.name,column_name),hint="Specify a 'db_column' for the field.",obj=cls,id='models.E007'))else:used_column_names.append(column_name)returnerrors@classmethoddef_check_model_name_db_lookup_clashes(cls):errors=[]model_name=cls.__name__ifmodel_name.startswith('_')ormodel_name.endswith('_'):errors.append(checks.Error("The model name '%s' cannot start or end with an underscore ""as it collides with the query lookup syntax."%model_name,obj=cls,id='models.E023'))elifLOOKUP_SEPinmodel_name:errors.append(checks.Error("The model name '%s' cannot contain double underscores as ""it collides with the query lookup syntax."%model_name,obj=cls,id='models.E024'))returnerrors@classmethoddef_check_property_name_related_field_accessor_clashes(cls):errors=[]property_names=cls._meta._property_namesrelated_field_accessors=(f.get_attname()forfincls._meta._get_fields(reverse=False)iff.is_relationandf.related_modelisnotNone)foraccessorinrelated_field_accessors:ifaccessorinproperty_names:errors.append(checks.Error("The property '%s' clashes with a related field ""accessor."%accessor,obj=cls,id='models.E025',))returnerrors@classmethoddef_check_single_primary_key(cls):errors=[]ifsum(1forfincls._meta.local_fieldsiff.primary_key)>1:errors.append(checks.Error("The model cannot have more than one field with ""'primary_key=True'.",obj=cls,id='models.E026',))returnerrors@classmethoddef_check_index_together(cls):"""Check the value of "index_together" option."""ifnotisinstance(cls._meta.index_together,(tuple,list)):return[checks.Error("'index_together' must be a list or tuple.",obj=cls,id='models.E008',)]elifany(notisinstance(fields,(tuple,list))forfieldsincls._meta.index_together):return[checks.Error("All 'index_together' elements must be lists or tuples.",obj=cls,id='models.E009',)]else:errors=[]forfieldsincls._meta.index_together:errors.extend(cls._check_local_fields(fields,"index_together"))returnerrors@classmethoddef_check_unique_together(cls):"""Check the value of "unique_together" option."""ifnotisinstance(cls._meta.unique_together,(tuple,list)):return[checks.Error("'unique_together' must be a list or tuple.",obj=cls,id='models.E010',)]elifany(notisinstance(fields,(tuple,list))forfieldsincls._meta.unique_together):return[checks.Error("All 'unique_together' elements must be lists or tuples.",obj=cls,id='models.E011',)]else:errors=[]forfieldsincls._meta.unique_together:errors.extend(cls._check_local_fields(fields,"unique_together"))returnerrors@classmethoddef_check_indexes(cls):"""Check the fields of indexes."""fields=[fieldforindexincls._meta.indexesforfield,_inindex.fields_orders]returncls._check_local_fields(fields,'indexes')@classmethoddef_check_local_fields(cls,fields,option):fromdjango.dbimportmodels# In order to avoid hitting the relation tree prematurely, we use our# own fields_map instead of using get_field()forward_fields_map={field.name:fieldforfieldincls._meta._get_fields(reverse=False)}errors=[]forfield_nameinfields:try:field=forward_fields_map[field_name]exceptKeyError:errors.append(checks.Error("'%s' refers to the nonexistent field '%s'."%(option,field_name,),obj=cls,id='models.E012',))else:ifisinstance(field.remote_field,models.ManyToManyRel):errors.append(checks.Error("'%s' refers to a ManyToManyField '%s', but ""ManyToManyFields are not permitted in '%s'."%(option,field_name,option,),obj=cls,id='models.E013',))eliffieldnotincls._meta.local_fields:errors.append(checks.Error("'%s' refers to field '%s' which is not local to model '%s'."%(option,field_name,cls._meta.object_name),hint="This issue may be caused by multi-table inheritance.",obj=cls,id='models.E016',))returnerrors@classmethoddef_check_ordering(cls):""" Check "ordering" option -- is it a list of strings and do all fields exist? """ifcls._meta._ordering_clash:return[checks.Error("'ordering' and 'order_with_respect_to' cannot be used together.",obj=cls,id='models.E021',),]ifcls._meta.order_with_respect_toornotcls._meta.ordering:return[]ifnotisinstance(cls._meta.ordering,(list,tuple)):return[checks.Error("'ordering' must be a tuple or list (even if you want to order by only one field).",obj=cls,id='models.E014',)]errors=[]fields=cls._meta.ordering# Skip expressions and '?' fields.fields=(fforfinfieldsifisinstance(f,str)andf!='?')# Convert "-field" to "field".fields=((f[1:]iff.startswith('-')elsef)forfinfields)# Skip ordering in the format field1__field2 (FIXME: checking# this format would be nice, but it's a little fiddly).fields=(fforfinfieldsifLOOKUP_SEPnotinf)# Skip ordering on pk. This is always a valid order_by field# but is an alias and therefore won't be found by opts.get_field.fields={fforfinfieldsiff!='pk'}# Check for invalid or nonexistent fields in ordering.invalid_fields=[]# Any field name that is not present in field_names does not exist.# Also, ordering by m2m fields is not allowed.opts=cls._metavalid_fields=set(chain.from_iterable((f.name,f.attname)ifnot(f.auto_createdandnotf.concrete)else(f.field.related_query_name(),)forfinchain(opts.fields,opts.related_objects)))invalid_fields.extend(fields-valid_fields)forinvalid_fieldininvalid_fields:errors.append(checks.Error("'ordering' refers to the nonexistent field '%s'."%invalid_field,obj=cls,id='models.E015',))returnerrors@classmethoddef_check_long_column_names(cls):""" Check that any auto-generated column names are shorter than the limits for each database in which the model will be created. """errors=[]allowed_len=Nonedb_alias=None# Find the minimum max allowed length among all specified db_aliases.fordbinsettings.DATABASES:# skip databases where the model won't be createdifnotrouter.allow_migrate_model(db,cls):continueconnection=connections[db]max_name_length=connection.ops.max_name_length()ifmax_name_lengthisNoneorconnection.features.truncates_names:continueelse:ifallowed_lenisNone:allowed_len=max_name_lengthdb_alias=dbelifmax_name_length<allowed_len:allowed_len=max_name_lengthdb_alias=dbifallowed_lenisNone:returnerrorsforfincls._meta.local_fields:_,column_name=f.get_attname_column()# Check if auto-generated name for the field is too long# for the database.iff.db_columnisNoneandcolumn_nameisnotNoneandlen(column_name)>allowed_len:errors.append(checks.Error('Autogenerated column name too long for field "%s". ''Maximum length is "%s" for database "%s".'%(column_name,allowed_len,db_alias),hint="Set the column name manually using 'db_column'.",obj=cls,id='models.E018',))forfincls._meta.local_many_to_many:# Skip nonexistent models.ifisinstance(f.remote_field.through,str):continue# Check if auto-generated name for the M2M field is too long# for the database.form2minf.remote_field.through._meta.local_fields:_,rel_name=m2m.get_attname_column()ifm2m.db_columnisNoneandrel_nameisnotNoneandlen(rel_name)>allowed_len:errors.append(checks.Error('Autogenerated column name too long for M2M field ''"%s". Maximum length is "%s" for database "%s".'%(rel_name,allowed_len,db_alias),hint=("Use 'through' to create a separate model for ""M2M and then set column_name using 'db_column'."),obj=cls,id='models.E019',))returnerrors@classmethoddef_check_constraints(cls):errors=[]fordbinsettings.DATABASES:ifnotrouter.allow_migrate_model(db,cls):continueconnection=connections[db]ifconnection.features.supports_table_check_constraints:continueifany(isinstance(constraint,CheckConstraint)forconstraintincls._meta.constraints):errors.append(checks.Warning('%s does not support check constraints.'%connection.display_name,hint=("A constraint won't be created. Silence this ""warning if you don't care about it."),obj=cls,id='models.W027',))returnerrors

############################################# HELPER FUNCTIONS (CURRIED MODEL METHODS) ############################################## ORDERING METHODS #########################defmethod_set_order(self,ordered_obj,id_list,using=None):ifusingisNone:using=DEFAULT_DB_ALIASorder_wrt=ordered_obj._meta.order_with_respect_tofilter_args=order_wrt.get_forward_related_filter(self)# FIXME: It would be nice if there was an "update many" version of update# for situations like this.withtransaction.atomic(using=using,savepoint=False):fori,jinenumerate(id_list):ordered_obj.objects.filter(pk=j,**filter_args).update(_order=i)defmethod_get_order(self,ordered_obj):order_wrt=ordered_obj._meta.order_with_respect_tofilter_args=order_wrt.get_forward_related_filter(self)pk_name=ordered_obj._meta.pk.namereturnordered_obj.objects.filter(**filter_args).values_list(pk_name,flat=True)defmake_foreign_order_accessors(model,related_model):setattr(related_model,'get_%s_order'%model.__name__.lower(),partialmethod(method_get_order,model))setattr(related_model,'set_%s_order'%model.__name__.lower(),partialmethod(method_set_order,model))######### MISC #########defmodel_unpickle(model_id):"""Used to unpickle Model subclasses with deferred fields."""ifisinstance(model_id,tuple):model=apps.get_model(*model_id)else:# Backwards compat - the model was cached directly in earlier versions.model=model_idreturnmodel.__new__(model)model_unpickle.__safe_for_unpickle__=True