o 3a2@sddlZddlZddlmZddlmZddlmZddlmZm Z ddl m Z m Z ddl mZmZddlmZdd lmZdd lmZdd lmZmZmZdd lmZdd lmZddlmZddl m!Z"ddl#m$Z$ddl%m&Z&ddl'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-ddl.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5ddl6m7Z7m8Z8m9Z9m:Z:dZ;ddZGddde>Z?e?@e2e?@e/e?@e4e?@e0e?@e1e?@e5e?@e3Gdd d e?ZAGd!d"d"eAZBd#d$ZCGd%d&d&e>ZDdS)'N)partial)forms)apps)SettingsReferencesettings)checks exceptions) connectionrouter)utils)Q) LOOKUP_SEP)CASCADE SET_DEFAULTSET_NULL)PathInfomake_model_tuple)cached_property) gettext_lazy)Field)FieldCacheMixin)ForeignKeyDeferredAttributeForwardManyToOneDescriptorForwardOneToOneDescriptorManyToManyDescriptorReverseManyToOneDescriptorReverseOneToOneDescriptor) RelatedExactRelatedGreaterThanRelatedGreaterThanOrEqual RelatedIn RelatedIsNullRelatedLessThanRelatedLessThanOrEqual)ForeignObjectRel ManyToManyRel ManyToOneRel OneToOneRelselfcCs2|tkr|}t|trd|vrd|jj|f}|S)a Transform relation into a model or fully-qualified model string of the form "app_label.ModelName", relative to scope_model. The relation argument can be: * RECURSIVE_RELATIONSHIP_CONSTANT, i.e. the string "self", in which case the model argument will be returned. * A bare model name without an app_label, in which case scope_model's app_label will be prepended. * An "app_label.ModelName" string. * A model class, which will be returned unchanged. .%s.%s)RECURSIVE_RELATIONSHIP_CONSTANT isinstancestr_meta app_label) scope_modelrelationr4A/usr/lib/python3/dist-packages/django/db/models/fields/related.pyresolve_relation%s  r6csLgfdd|D}dd|D}jj}|jt|fi|g|RS)a Schedule `function` to be called once `model` and all `related_models` have been imported and registered with the app registry. `function` will be called with the newly-loaded model classes as its positional arguments, plus any optional keyword arguments. The `model` argument must be a model class. Each subsequent positional argument is another model, or a reference to another model - see `resolve_relation()` for the various forms these may take. Any relative references will be resolved relative to `model`. This is a convenience wrapper for `Apps.lazy_model_operation` - the app registry model used is the one found in `model._meta.apps`. csg|]}t|qSr4)r6).0relmodelr4r5 Msz*lazy_related_operation..css|]}t|VqdSNr)r7mr4r4r5 Nz)lazy_related_operation..)r0rlazy_model_operationr)functionr:related_modelskwargsmodels model_keysrr4r9r5lazy_related_operation>srFcseZdZdZdZdZdZdZeddZ fddZ ddZ d d Z d d Z d dZddZddZd+fdd ZfddZddZddZeddZddZdd Zd!d"Zfd#d$Zd%d&Zed'd(Zd)d*ZZS), RelatedFieldz3Base class that all relational fields inherit from.FcCst|jjSr<)rcheck_models_ready remote_fieldr:r*r4r4r5 related_model\szRelatedField.related_modelc s>gtjdi||||||SNr4)supercheck_check_related_name_is_valid"_check_related_query_name_is_valid_check_relation_model_exists#_check_referencing_to_swapped_model_check_clashesr*rC __class__r4r5rNbszRelatedField.checkcCslddl}|jj}|durgS|| o|}|s4|ds4tjd|jj|jj j |j fd|ddgSgS)Nr+z5The name '%s' is invalid related_name for field %s.%sz@Related name must be a valid Python identifier or end with a '+'z fields.E306hintobjid) keywordrI related_name iskeyword isidentifierendswithrErrorr:r0 object_namename)r*r\r] is_valid_idr4r4r5rOls$ z)RelatedField._check_related_name_is_validcCsl|jrgS|}g}|dr |tjd|d|ddt|vr4|tjd|tfd|dd|S)N_z8Reverse query name '%s' must not end with an underscore.zKAdd or change a related_name or related_query_name argument for this field.z fields.E308rXz.Reverse query name '%s' must not contain '%s'.z fields.E309)rI is_hiddenrelated_query_namer`appendrrar )r*rel_query_nameerrorsr4r4r5rPs6    z/RelatedField._check_related_query_name_is_validcCsh|jj|jjv}t|jjt}|r|jjn|jjjj}|r2|s'|jjjj s2t j d||ddgSgS)NzXField defines a relation with model '%s', which is either not installed, or is abstract.z fields.E300rZr[) rIr:optsr get_modelsr.r/r0rbswappedrra)r*rel_is_missing rel_is_string model_namer4r4r5rQsz)RelatedField._check_relation_model_existscCs^|jj|jjvr-t|jjts-|jjjjr-t j d|jjjj d|jjjj |ddgSgS)NzIField defines a relation with the model '%s', which has been swapped out.z.Update the relation to point at 'settings.%s'.z fields.E301rX) rIr:rlrrmr.r/r0rnrralabel swappablerJr4r4r5rRs    z0RelatedField._check_referencing_to_swapped_modelc sddlm}g}jj}tjj|sgSjjj}j}j}}d|j j f}|j |j } | D]>} d|j | j f} |s]| j |kr]| tjd|| fd| |fdd| j |krv| tjd|| fd| |fd dq8fd d |jD} | D]C} d| jjj | jj f} |s| |kr| tjd || fd || fdd| |kr| tjd|| fd || fddq|S)z.Check accessor and reverse query name clashes.r) ModelBaser,z7Reverse accessor for '%s' clashes with field name '%s'.zZRename field '%s', or add/change a related_name argument to the definition for field '%s'.z fields.E302rXz9Reverse query name for '%s' clashes with field name '%s'.z fields.E303c3s|] }|jur|VqdSr<field)r7rrJr4r5r>sz.RelatedField._check_clashes..zAReverse accessor for '%s' clashes with reverse accessor for '%s'.zIAdd or change a related_name argument to the definition for '%s' or '%s'.z fields.E304zEReverse query name for '%s' clashes with reverse query name for '%s'.z fields.E305)django.db.models.basertr:r0r.rIrfget_accessor_namergrrrcfields many_to_manyrhrrarelated_objectsrKrv) r*rtrjrlrel_opts rel_is_hiddenrel_nameri field_namepotential_clashes clash_field clash_namer4rJr5rSs            zRelatedField._check_clashescCdSr<r4r*r r4r4r5db_typezRelatedField.db_typec stj||fd|i||j|_|jjsc|jjr|jj}n|jj}|r;||j |jj |jj d}||j_|jj rS|jj |j |jj d}||j_ dd}t |||jj|ddSdS)N private_only)classrqr1)rr1cSs||j_|||dSr<)rIr:do_related_class)r:relatedrvr4r4r5resolve_related_class;sz?RelatedField.contribute_to_class..resolve_related_classru)rMcontribute_to_classr0rlabstractrIr]default_related_name__name__lowerrqr1rgrFr:)r*clsrcrrCr]rgrrUr4r5r!s,    z RelatedField.contribute_to_classcsbt\}}}}|jjr|jj|d<|jjdur|jj|d<|jjdur+|jj|d<||||fS)Nlimit_choices_tor]rg)rM deconstructrIrr]rgr*rcpathargsrCrUr4r5r@s      zRelatedField.deconstructcsfddjDS)a> Return the keyword arguments that when supplied to self.model.object.filter(), would select all instances related through this field to the remote obj. This is used to build the querysets returned by related descriptors. obj is an instance of self.related_field.model. cs*i|]\}}dj|jft|jqS)z%s__%s)rcgetattrattname)r7rerh_fieldrZr*r4r5 Rsz;RelatedField.get_forward_related_filter..related_fieldsr*rZr4rr5get_forward_related_filterJs z'RelatedField.get_forward_related_filtercsXfdd|jD}|}tdi|}t|tr$|tdi|@S|r*||@S|S)a% Complement to get_forward_related_filter(). Return the keyword arguments that when passed to self.related_field.model.object.filter() select all instances of self.related_field.model related through this field to obj. obj is an instance of self.model. cs i|] \}}|jt|jqSr4)rr)r7lh_fieldrrZr4r5r^sz;RelatedField.get_reverse_related_filter..Nr4)rget_extra_descriptor_filterr r.dict)r*rZ base_filterdescriptor_filterbase_qr4rr5get_reverse_related_filterWs   z'RelatedField.get_reverse_related_filtercCs8|jrt|jjtr|jj}n|jjjj}t|SdS)z Get the setting that this is powered from for swapping, or None if it's not swapped in / marked with swappable=False. N) rsr.rIr:r/r0rrrget_swappable_settings_name)r* to_stringr4r4r5swappable_settingjs    zRelatedField.swappable_settingcCsL|jp|jjjjd|jjjjj|_|jdur|jjjj|_|jdS)Nre)rcrIr:r0rqpk verbose_nameset_field_namerJr4r4r5set_attributes_from_relys  z$RelatedField.set_attributes_from_relcCs||||jdSr<)rcontribute_to_related_classrI)r*otherrr4r4r5rszRelatedField.do_related_classcCst|jjr |jS|jjS)z Return ``limit_choices_to`` for this model field. If it is a callable, it will be invoked and the result will be returned. )callablerIrrJr4r4r5get_limit_choices_tos  z!RelatedField.get_limit_choices_toc sBi}t|jdr|jj}|d|i||tjdi|S)z Pass ``limit_choices_to`` to the field being constructed. Only passes it if there is a type that supports related fields. This is a similar strategy used to pass the ``queryset`` to the field being constructed. get_related_fieldrNr4)hasattrrIrupdaterM formfield)r*rCdefaultsrrUr4r5rs  zRelatedField.formfieldcCs|jjp |jjp |jjS)zu Define the name that can be used to identify this related object in a table-spanning query. )rIrgr]rlrqrJr4r4r5rgszRelatedField.related_query_namecCs,|dj}t|dkrtd|dS)z When filtering against this relation, return the field on the remote model against which the filtering should happen. rzSThe relation has multiple target fields, but only single target field was asked forr) get_path_info target_fieldslenr FieldError)r*rr4r4r5 target_fields  zRelatedField.target_fieldcCs|jSr<rcrJr4r4r5get_cache_nameszRelatedField.get_cache_nameF)r __module__ __qualname____doc__ one_to_many one_to_oner{ many_to_onerrKrNrOrPrQrRrSrrrrrpropertyrrrrrrgrr __classcell__r4r4rUr5rGSs:   b        rGcs4eZdZdZdZdZdZdZdZe Z e Z e Z   d4fdd ZfddZd d Zd d Zfd dZddZeddZeddZeddZeddZddZddZeddZfdd Zd5d!d"Zd#d$Z d%d&Z!d'd(Z"d6d)d*Z#d6d+d,Z$e%e&j'dd-d.d/Z(d5fd0d1 Z)d2d3Z*Z+S)7 ForeignObjectzS Abstraction of the ForeignKey relation to support multi-column relations. FTNc sL|dur|j|||||| |d}tjdd|i| ||_||_| |_dS)Nr]rgr parent_link on_deleter8r4) rel_classrM__init__ from_fields to_fieldsrs) r*torrrr8r]rgrrrsrCrUr4r5rs  zForeignObject.__init__c &gtjdi|||SrL)rMrN_check_to_fields_exist_check_unique_targetrTrUr4r5rNzForeignObject.checkc Cszt|jjtr gSg}|jD],}|r:z |jjj|Wqtjy9| t j d||jjjj f|ddYqwq|S)Nz:The to_field '%s' doesn't exist on the related model '%s'.z fields.E312rk) r.rIr:r/rr0 get_fieldrFieldDoesNotExistrhrrarr)r*rjto_fieldr4r4r5rs(  z$ForeignObject._check_to_fields_existcsHt|jjt}|s |jsgSz|jWn tjygYSw|js%gSdd|jjj D}| dd|jjjj D| dd|jjjj Ddd|jDt fdd|D}|st|jdkrd d d|jD}|jjj}tjd ||fd |d dgS|s|jdj}|jjj}tjd||fd|ddgSgS)NcSs$h|]}t|ddrt|jgqS)uniqueF)r frozensetrcr7fr4r4r5 s   z5ForeignObject._check_unique_target..cSsh|]}t|qSr4)r)r7utr4r4r5rscSsh|]}t|jqSr4)rrz)r7ucr4r4r5rscSsh|]}|jqSr4rrr4r4r5rc3s|]}|kVqdSr<r4)r7uforeign_fieldsr4r5r>r?z5ForeignObject._check_unique_target..r, css|]}d|jVqdS)z'%s'Nr)r7 rel_fieldr4r4r5r>s  z3No subset of the fields %s on model '%s' is unique.zMark a single field as unique=True or add a set of fields to a unique constraint (via unique_together or a UniqueConstraint (without condition) in the model Meta.constraints).z fields.E310rXrzA'%s.%s' must be unique because it is referenced by a foreign key.zjAdd unique=True to this field or add a UniqueConstraint (without condition) in the model Meta.constraints.z fields.E311)r.rIr:r/requires_unique_targetforeign_related_fieldsrrr0 get_fieldsrunique_togethertotal_unique_constraintsanyrjoinrrrarc)r*rpunique_foreign_fieldshas_unique_constraintfield_combinationrqrr4rr5rs`           z"ForeignObject._check_unique_targetcst\}}}}|jj|d<|j|d<|j|d<|jjr#|jj|d<t|jjt rMd|jjvrD|jj d\}}d|| f|d<n|jj |d<n|jjj j |d<|j}|dur~t|ddru|dj|krutd |dj|ft|d||d<||||fS) Nrrrrr+r,r setting_namezoCannot deconstruct a ForeignKey pointing to a model that is swapped in place of more than one model (%s and %s))rMrrIrrrrr.r:r/splitrr0 label_lowerrrr ValueErrorr)r*rcrrrCr1rqrrUr4r5r@s4       zForeignObject.deconstructcCs|jr t|jt|jkrtdt|jjtr td|jjg}tt|jD]1}|j|}|j|}|t kr;|n|j |}|durK|jjj j n|jjj |}|||fq)|S)NzBForeign Object from and to fields must be the same non-zero lengthz#Related model %r cannot be resolved)rrrrr.rIr:r/ranger-rlrr0rrh)r*rindexfrom_field_name to_field_name from_fieldrr4r4r5resolve_related_fieldscs"   z$ForeignObject.resolve_related_fieldscCs|Sr<)rrJr4r4r5rvszForeignObject.related_fieldscCsdd|jDS)NcSsg|]\}}||fqSr4r4r7 lhs_field rhs_fieldr4r4r5r;|sz8ForeignObject.reverse_related_fields..rrJr4r4r5reverse_related_fieldszsz$ForeignObject.reverse_related_fieldscCtdd|jDS)Ncss|]\}}|VqdSr<r4rr4r4r5r>r?z5ForeignObject.local_related_fields..tuplerrJr4r4r5local_related_fields~z"ForeignObject.local_related_fieldscCr)Ncss|] \}}|r|VqdSr<r4rr4r4r5r>sz7ForeignObject.foreign_related_fields..rrJr4r4r5rrz$ForeignObject.foreign_related_fieldscC|||jSr<)get_instance_value_for_fieldsrr*instancer4r4r5get_local_related_valuez%ForeignObject.get_local_related_valuecCrr<)rrrr4r4r5get_foreign_related_valuer z'ForeignObject.get_foreign_related_valuecCsbg}|j}|D]%}|jr#||j}|r|js|jjjr#||jq|t||jqt |Sr<) r0 primary_keyget_ancestor_linkr:rrhrrrr)rrzretrlrvpossible_parent_linkr4r4r5rs  z+ForeignObject.get_instance_value_for_fieldscst\}}|dfSr<)rMget_attname_columnr*rcolumnrUr4r5rsz ForeignObject.get_attname_columncCs"|r|jn|j}tdd|DS)Ncss |] \}}|j|jfVqdSr<)rrr4r4r5r>sz4ForeignObject.get_joining_columns..)rrr)r* reverse_joinsourcer4r4r5get_joining_columnssz!ForeignObject.get_joining_columnscCs |jddS)NT)r)rrJr4r4r5get_reverse_joining_columns z)ForeignObject.get_reverse_joining_columnscCsiS)a Return an extra filter condition for related object fetching when user does 'instance.fieldname', that is the extra filter is used in the descriptor of the field. The filter should be either a dict usable in .filter(**kwargs) call or a Q-object. The condition will be ANDed together with the relation's joining columns. A parallel method is get_extra_restriction() which is used in JOIN and subquery conditions. r4rr4r4r5rs z)ForeignObject.get_extra_descriptor_filtercCsdS)a Return a pair condition used for joining and subquery pushdown. The condition is something that responds to as_sql(compiler, connection) method. Note that currently referring both the 'alias' and 'related_alias' will not work in some conditions, like subquery pushdown. A parallel method is get_extra_descriptor_filter() which is used in instance.fieldname related object fetching. Nr4)r* where_classalias related_aliasr4r4r5get_extra_restrictions z#ForeignObject.get_extra_restrictionc Cs,|jjj}|jj}t|||j|dd|dgS)z.Get path from this field to the related model.FT from_optsto_optsr join_fieldm2mdirectfiltered_relation)rIr:r0rrr*r!rlrr4r4r5rs zForeignObject.get_path_infoc C4|jj}|jjj}t|||jf|j|j d|dgSz6Get path from the related model to this field's model.Frr:r0rIrrrr"r4r4r5get_reverse_path_info z#ForeignObject.get_reverse_path_info)maxsizecCs8t|}|d|td}dd|D}||S)NrcSsg|] }|jdiqS) class_lookups)__dict__get)r7parentr4r4r5r;sz-ForeignObject.get_lookups..)inspectgetmrorr merge_dicts)rbasesr)r4r4r5 get_lookupss  zForeignObject.get_lookupsc s2tj||fd|i|t||j||dS)Nr)rMrsetattrrcforward_related_accessor_class)r*rrcrrCrUr4r5rsz!ForeignObject.contribute_to_classcCsX|js&|jjjs(t|jj||||jj r*|jj |jj dSdSdSdSr<) rIrfrKr0rnr2concrete_modelryrelated_accessor_classrrelated_fkey_lookupsrhr*rrr4r4r5rs z)ForeignObject.contribute_to_related_class)NNNNFTrr<),rrrrr{rrrrrr5rr3r&rrrNrrrrrrrrrrr  staticmethodrrrrrrrr& classmethod functools lru_cacher1rrrr4r4rUr5rsV  C#           rcsDeZdZdZeZdZdZdZdZ e Z dZ de diZe dZ   d9fdd Zfd d Zd d ZddZfddZddZeddZd:ddZfddZfddZddZddZfd d!Zd"d#Zd;d$d%Zd&d'Z fd(d)Z!dd*fd+d, Z"d-d.Z#d/d0Z$d1d2Z%d3d4Z&fd5d6Z'd:fd7d8 Z(Z)S)< ForeignKeyz Provide a many-to-one relation by adding a column to the local model to hold the remote value. By default ForeignKey will target the pk of the remote model but this behavior can be changed by using the ``to_field`` argument. FTinvalidz;%(model)s instance with %(field)s %(value)r does not exist.z.Foreign Key (type determined by related field)Nc sz|jjWntyt|tsJd|jj|tfYn w|p*|jjo*|jjj }t |s3t d|j ||||||||d| d<| ddtj||ftg|gd| ||_dS)Nzg%s(%r) is invalid. First parameter to ForeignKey must be either a model, a model name, or the string %rzon_delete must be callable.rr8db_indexT)rr)r0rqAttributeErrorr.r/rVrr-rrcr TypeErrorr setdefaultrMr db_constraint) r*rrr]rgrrrrBrCrUr4r5rsB      zForeignKey.__init__c rrL)rMrN_check_on_delete _check_uniquerTrUr4r5rNBrzForeignKey.checkcCsXt|jdd}|tkr|jstjdd|ddgS|tkr*|s*tjdd|ddgSgS) Nrz7Field specifies on_delete=SET_NULL, but cannot be null.zBSet null=True argument on the field, or change the on_delete rule.z fields.E320rXz@Field specifies on_delete=SET_DEFAULT, but has no default value.z2Set a default value, or change the on_delete rule.z fields.E321)rrIrnullrrar has_default)r*rr4r4r5rCIs$ zForeignKey._check_on_deletecKs|jr tjdd|ddgSgS)NzQSetting unique=True on a ForeignKey has the same effect as using a OneToOneField.zDForeignKey(unique=True) is usually better served by a OneToOneField.z fields.W342rX)rrWarningrTr4r4r5rD`szForeignKey._check_uniquecst\}}}}|d=|d=|jr|d=nd|d<|jdur$|j|d<t|jjdd}|jjrC|r=|jrC|jj|jj krC|jj|d<||||fS) Nrrr>FTrBr0r) rMrr>rBrrIr:rrrc)r*rcrrrCto_metarUr4r5rjs"    zForeignKey.deconstructcC |j|Sr<)r to_pythonr*valuer4r4r5rJ|rzForeignKey.to_pythoncCs |jdS)Nr)rrJr4r4r5rs zForeignKey.target_fieldc Cr#r$r%r"r4r4r5r&r'z ForeignKey.get_reverse_path_infocs|jjrdSt|||durdStj|jj|d}|jjj|j di|jj |i}| | }| sOtj|jdd|jjjj||jj |dddS)N)rr=)r:rrvrL)codeparamsr4)rIrrMvalidater db_for_readr: _base_managerusingfilterrcomplex_filterrexistsrValidationErrorerror_messagesr0r)r*rLmodel_instancerRqsrUr4r5rOs&  zForeignKey.validatecs^t}|D]%\}}|r,|j|jjjjkr,td|jjj|j |j |jjjjjjfq|S)Nz>'%s.%s' refers to field '%s' which is not local to model '%s'.) rMrr:rIr0r4rrrrrc)r*rrrrUr4r5rs   z!ForeignKey.resolve_related_fieldscCs d|jS)Nz%s_idrrJr4r4r5 get_attname zForeignKey.get_attnamecCs|}|jp|}||fSr<)rZ db_columnrr4r4r5rs zForeignKey.get_attname_columncs*t}t||jjrt||jjS|S)z6Return the to_field if the default value is an object.)rM get_defaultr.rIr:rrr)r* field_defaultrUr4r5r]s zForeignKey.get_defaultcCs4|dus|dkr|jjr|jjrdS|jj||dS)Nr )rempty_strings_allowedfeatures!interprets_empty_strings_as_nullsget_db_prep_save)r*rLr r4r4r5rdszForeignKey.get_db_prep_savecCs|j|||Sr<)rget_db_prep_value)r*rLr preparedr4r4r5reszForeignKey.get_db_prep_valuecCrIr<)rget_prep_valuerKr4r4r5rgrzForeignKey.get_prep_valuecs0t|||jjdur|jjj|j_dSdSr<)rMrrIrr0rrcr7rUr4r5rs z&ForeignKey.contribute_to_related_classrRc s^t|jjtrtd|j|jjftjditj |jjj ||jj d|d|j iS)NzYCannot create form field for %r yet, because its related model %r has not been loaded yet) form_classquerysetrblankr4)r.rIr:r/rrcrMrrModelChoiceField_default_managerrRrrk)r*rRrCrUr4r5rs   zForeignKey.formfieldcCgSr<r4rr4r4r5db_checkzForeignKey.db_checkcCs|jj|dS)Nr`)r rel_db_typerr4r4r5rr zForeignKey.db_typecCs||||dSN)typerN)rrorr4r4r5 db_parameterszForeignKey.db_parameterscCs|s t|tr dS|Sr<)r.r/)r*rL expressionr r4r4r5convert_empty_stringssz ForeignKey.convert_empty_stringscs$t|}|jjr||jg7}|Sr<)rMget_db_convertersrbrcrw)r*r convertersrUr4r5rxs  zForeignKey.get_db_converterscsF|dur|j}t|tr|j}||urtdt|ts t||S)NzCannot resolve output_field.)rr.r<rrMget_col)r*r output_fieldrUr4r5rzs  zForeignKey.get_col)NNNFNTr<r)*rrrrrdescriptor_classr{rrrr(rraredefault_error_messages descriptionrrNrCrDrrJrrr&rOrrZrr]rdrergrrrorrtrwrxrzrr4r4rUr5r<sP (          r<csneZdZdZdZdZdZdZeZ e Z e Z edZdfdd Zfdd Zfd d Zd d ZddZZS) OneToOneFielda A OneToOneField is essentially the same as a ForeignKey, with the exception that it always carries a "unique" constraint with it and the reverse relation always returns the object pointed to (since there will only ever be one), rather than returning a list. FTzOne-to-one relationshipNc s&d|d<tj||fd|i|dS)NTrr)rMr)r*rrrrCrUr4r5rszOneToOneField.__init__cs,t\}}}}d|vr|d=||||fS)Nr)rMrrrUr4r5rs zOneToOneField.deconstructc s|jjrdStjdi|SrL)rIrrMrrTrUr4r5r!szOneToOneField.formfieldcCsLt||jjrt||j|dSt||j||dur$t||j|dSdSr<)r.rIr:r2rcrr*rdatar4r4r5save_form_data&s zOneToOneField.save_form_datacKrnr<r4rTr4r4r5rD0szOneToOneField._check_uniquer<)rrrrr{rrrrr5rr3r)rrer~rrrrrDrr4r4rUr5rs   rc Csddlm}dd}t||jj}d|jj|jf}t||||t |d}|jj }||kr7d|}d|}t d d | |j||jj |jj||ftd ||d td ||d |jjjd}t ||jfd |d|j||j|d||j|jjtd||j|d||j|jjtdiS)Nr)rDcSs|jjp|jj|j_dSr<)r0managed)r:rthroughr4r4r5 set_managed8sz;create_many_to_many_intermediary_model..set_managed%s_%srzto_%szfrom_%sMetar4z%(from)s-%(to)s relationship)fromrz%(from)s-%(to)s relationships)db_table auto_createdr1 db_tablespacerrverbose_name_pluralrrz%s+)r]rrBr) django.dbrDr6rIr:r0rbrcrFrrqrs_get_m2m_db_tabler1rrerModelrr<rBr) rvklassrDrto_modelrcrfrom_metar4r4r5&create_many_to_many_intermediary_model5sL    rcs eZdZdZdZdZdZdZeZ e dZ    d3fdd Z fdd Z d d Zd d Zd4ddZddZfddZd5ddZd4ddZd4ddZddZddZddZfd d!Zd"d#Zd$d%Zd&d'Zd(d)Zdd*fd+d, Zd-d.Zd/d0Z d1d2Z!Z"S)6ManyToManyFieldaK Provide a many-to-many relation by using an intermediary model that holds two ForeignKey fields pointed at the two sides of the relation. Unless a ``through`` model was provided, ManyToManyField will use the create_many_to_many_intermediary_model factory to automatically generate the intermediary model. TFzMany-to-many relationshipNc sz|jWntyt|tsJd|jj|tfYnw|dur'|tk}|dur3| dus3Jd|j|||||||||d | d<d| v|_t j di| | |_ | |_ dS)Nzl%s(%r) is invalid. First parameter to ManyToManyField must be either a model, a model name, or the string %rz;Cannot specify a db_table if an intermediary model is used.)r]rgr symmetricalrthrough_fieldsrBr8rEr4) r0r?r.r/rVrr-r has_null_argrMrrrs) r*rr]rgrrrrrBrrsrCrUr4r5rxs:       zManyToManyField.__init__c sVgtjdi||jdi||jdi||jdi||jdi|SrL)rMrNrD_check_relationship_model_check_ignored_options_check_table_uniquenessrTrUr4r5rNszManyToManyField.checkcKs|jr tjd|ddgSgS)Nz"ManyToManyFields cannot be unique.z fields.E330rk)rrrarTr4r4r5rDszManyToManyField._check_uniquecKsrg}|jr|tjd|dd|jr|tjd|dd|jjr7|jjr7|jjjj s7|tjd|dd|S)Nz&null has no effect on ManyToManyField.z fields.W340rkz,ManyToManyField does not support validators.z fields.W341zGlimit_choices_to has no effect on ManyToManyField with a through model.z fields.W343) rrhrrG _validatorsrIrrr0r)r*rCwarningsr4r4r5rs8  z&ManyToManyField._check_ignored_optionsc st|jjdrd|jjjj|jjjf}n|jj}g}|jj|jjjddvr5| t j d||ddnňdus=Jdt |jj jj}ttrP}njj}|jjjj}k}|rtfd d |jjjjD} | d kr|jjs| t j d ||fd |jjddnptfdd |jjjjD} tfdd |jjjjD} | dkr|jjs| t j d||fdt|f|dd| dkr|jjs| t j d||fdt|f|dd| dks| dkr| t j d|||f|jjdd|jjdurt|jjd kr|jjdr|jjds(| t j d|d|dd|Sdus1Jd|jj|jj } } }|jjdd \}}|| f||ffD]\}}g}| jjD]}t|drqt|jdd|krq| |jqY|rd |jjd!|f}nd}z| j|}Wntjy| t j d"||f||d#dYqOwt|drt|jdd|ks| t j d$| jj||jjf||d%dqO|S)&Nr0r,Tinclude_auto_createdzYField specifies a many-to-many relation through model '%s', which has not been installed.z fields.E331rkzvManyToManyField with intermediate tables cannot be checked if you don't pass the model where the field is attached to.c3"|] }t|jddkVqdSr:NrrIr7rv from_modelr4r5r>  z.zThe model is used as an intermediate model by '%s', but it has more than two foreign keys to '%s', which is ambiguous. You must specify which two foreign keys Django should use via the through_fields keyword argument.zGUse through_fields to specify which two foreign keys Django should use.z fields.E333rXc3rrrrrr4r5r> rc3rrrr)rr4r5r>rrzThe model is used as an intermediate model by '%s', but it has more than one foreign key from '%s', which is ambiguous. You must specify which foreign key Django should use via the through_fields keyword argument.zXIf you want to create a recursive relationship, use ManyToManyField("%s", through="%s").z fields.E334zThe model is used as an intermediate model by '%s', but it has more than one foreign key to '%s', which is ambiguous. You must specify which foreign key Django should use via the through_fields keyword argument.z fields.E335rzgThe model is used as an intermediate model by '%s', but it does not have a foreign key to '%s' or '%s'.z fields.E336zField specifies 'through_fields' but does not provide the names of the two link fields that should be used for the relation through model '%s'.zMMake sure you specify 'through_fields' as through_fields=('field1', 'field2')z fields.E337rIr:z;Did you mean one of the following foreign keys to '%s': %s?rz.The intermediary model '%s' has no field '%s'.z fields.E338z%'%s.%s' is not a foreign key to '%s'.z fields.E339)rrIrr0r1rrlrrmrhrrar6r:rbr.r/sumrzrr-rrrcrrrr)r*rrCqualified_model_namerjfrom_model_name to_model_namerelationship_model_nameself_referential seen_self seen_fromseen_torrtargetsource_field_nametarget_field_namerrKpossible_field_namesrrYrvr4)rrr5rs4            B        z)ManyToManyField._check_relationship_modelc  stjjts jjjjsgSfddjjjddD} }| |}|rq|jj jjjj krq|jj rJdd}|jj j}d|j ||f}n|jj }tjr\tjd}} d |} ntjd }} d} |d ||f| | d gSgS) Ncs*i|]}|jjkr|jjr|jj|qSr4)rIrr0rr)r7r:rJr4r5rs z;ManyToManyField._check_table_uniqueness..TrcSs,|jjjjD] }|jj|ur|jSqdSr<)r0rr{rIrrc)r:rvr4r4r5_get_field_names   z@ManyToManyField._check_table_uniqueness.._get_field_namer,z fields.W344zvYou have configured settings.DATABASE_ROUTERS. Verify that the table of %r is correctly routed to a separate database.z fields.E340zHThe field's intermediary table '%s' clashes with the table name of '%s'.)rZrYr[)r.rIrr/r0rrlrrm m2m_db_tabler+r4rrrrDATABASE_ROUTERSrrGra) r*rCregistered_tablesrr:rrl clashing_obj error_classerror_id error_hintr4rJr5rs>      z'ManyToManyField._check_table_uniquenesscst\}}}}|jdur|j|d<|jjdur|jj|d<t|jjtr-|jj|d<n|jjjj |d<t |jdddurZt|jj trL|jj |d<n|jj jj sZ|jj jj |d<|j }|durt|ddrz|dj|krztd|dj|ft|d||d<||||fS)NrTrBrrrztCannot deconstruct a ManyToManyField pointing to a model that is swapped in place of more than one model (%s and %s))rMrrrIrBr.r:r/r0rrrrrrrrrr)r*rcrrrCrrUr4r5rs6       zManyToManyField.deconstructc Cs|jj}|j|}|j|}|r |}||}n |}||}|dj}|dj } || ur:g} nt |j | j rH| | j } n| |j } g|| |S)z1Called by both direct and indirect m2m traversal.rr)rIrr0rm2m_field_namem2m_reverse_field_namer&rrr issubclassr:get_path_to_parentget_path_from_parent) r*r r! int_model linkfield1 linkfield2 join1infos join2infos join1_final join2_initialintermediate_infosr4r4r5_get_path_infos      zManyToManyField._get_path_infocC|jd|dS)NTr r!rr*r!r4r4r5rr zManyToManyField.get_path_infocCr)NFrrrr4r4r5r&r z%ManyToManyField.get_reverse_path_infocCsL|jjdur |jjjjS|jr|jSdt|j|jf}t|tj S)zg Function that can be curried to provide the m2m table name for this relation. Nr) rIrr0rr strip_quotesrc truncate_namer opsmax_name_length)r*rlm2m_table_namer4r4r5rs  z!ManyToManyField._get_m2m_db_tablecCsd|}t||rt||S|jjdur|jjd}nd}|jjjjD]%}|jrH|jj|j krH|dus8||j krHt ||t||t||Sq#dS)zz Function that can be curried to provide the source accessor or DB column name for the m2m table. z _m2m_%s_cacheNr) rrrIrrr0rz is_relationr:rKrcr2)r*rattr cache_attrlink_field_namerr4r4r5 _get_m2m_attrs   zManyToManyField._get_m2m_attrcCsd|}t||rt||Sd}|jjdur|jjd}nd}|jjjjD]:}|jr_|jj|jkr_|durK|j |jkrK|rHt ||t||nd}q%|dusT||j kr_t ||t||nq%t||S)z{ Function that can be curried to provide the related accessor or DB column name for the m2m table. z_m2m_reverse_%s_cacheFNrT) rrrIrrr0rzrr:rKr2rc)r*rrrfoundrrr4r4r5_get_m2m_reverse_attr"s&    z%ManyToManyField._get_m2m_reverse_attrc s|jjr|jjtks|jj|jjkrd||j_n|jr,d|jj|j |f|j_t j ||fi||jj sY|jjrNdd}t|||jj|dn |jjsYt|||j_t||jt|jddt|j|j|_dS)Nz%s_rel_+z _%s_%s_%s_+cSs ||j_dSr<)rIr)rer:rvr4r4r5resolve_through_model_rzBManyToManyField.contribute_to_class..resolve_through_modelruFreverse)rIrr:r-r0rbr]rfr1rrrMrrrrFrnrr2rcrrrr)r*rrcrCrrUr4r5r@s&   z#ManyToManyField.contribute_to_classcs|js|jjjst||t|jddt|j |d|_ t|j |d|_ t|j |d|_ t|j |d|_t|j |dfdd|_t|j |dfdd|_dS) NTrrrcrIcjSr<rr4) get_m2m_relr4r5yz=ManyToManyField.contribute_to_related_class..crr<rr4)get_m2m_reverse_relr4r5r{r)rIrfrKr0rnr2ryrrrm2m_column_namerm2m_reverse_namerrm2m_target_field_namem2m_reverse_target_field_namer7r4)rrr5rksz+ManyToManyField.contribute_to_related_classcCrr<r4rJr4r4r5r}rpz'ManyToManyField.set_attributes_from_relcCs"|jdurgStt||jSr<)rlistrrallrr4r4r5value_from_objects"z!ManyToManyField.value_from_objectcCst||j|dSr<)rrsetrr4r4r5rruzManyToManyField.save_form_datarhc sdtj|jjj|d|}|ddur)|d}t|r |}dd|D|d<tj di|S)N)rirjinitialcSsg|]}|jqSr4)r)r7ir4r4r5r;rz-ManyToManyField.formfield..r4) rModelMultipleChoiceFieldrIr:rmrRr+rrMr)r*rRrCrrrUr4r5rszManyToManyField.formfieldcCrr<r4rr4r4r5rorpzManyToManyField.db_checkcCrr<r4rr4r4r5rrzManyToManyField.db_typecCs dddSrrr4rr4r4r5rtr[zManyToManyField.db_parameters) NNNNNNTNTr<)FN)#rrrrr{rrrr'rrer~rrNrDrrrrrrr&rrrrrrrrrrorrtrr4r4rUr5rdsF  &  !B + $    +r)Er:r-rdjangor django.appsr django.confrr django.corerrrr r django.db.backendsr django.db.modelsr django.db.models.constantsr django.db.models.deletionrrrdjango.db.models.query_utilsrdjango.db.models.utilsrdjango.utils.functionalrdjango.utils.translationrrer_rmixinsrrelated_descriptorsrrrrrrrelated_lookupsrr r!r"r#r$r%reverse_relatedr&r'r(r)r-r6rFrGrregister_lookupr<rrrr4r4r4r5sV             $k @      2/