o 3aLM@sddlZddlZddlZddlmZddlmZddlmZm Z ddl m Z ddl m Z ddlmZddlmZmZdd lmZmZdd lmZdd lmZdd lmZdd lmZmZdddDZ dde !DZ"edd#dde"DZ$Gddde%Z&ddZ'ddZ(ddZ)ddZ*d d!Z+d"d#Z,d$d%Z-Gd&d'd'e Z.d(d)Z/dEd*d+Z0dEd,d-Z1d.d/Z2dFd1d2Z3d3d4Z4d5d6Z5dGd7d8Z6Gd9d:d:e%Z7d;d<Z8d=d>Z9d?d@Z:dAdBZ;dCdDZsrs":/_#?;@&=+$,"[]<>% \cCsi|] \}}|t|qSr)chr)rkvrrrrsz_(?:%s)|cCsg|]}|ddqS)Nr)rxrrr src@seZdZdZdS)FieldIsAForeignKeyColumnNamez/A field is a foreign key attname, i.e. _id.N)__name__ __module__ __qualname____doc__rrrrrsrc Cs~|t}|D]5}|dkr|jj}z||}Wn ty!Yqwt|dr<|}|dj}t dd|Dr<dSqdS)zT Return True if 'distinct()' should be used to query the given lookup path. pk get_path_infocss|]}|jVqdSN)m2m)rpathrrr /sz(lookup_needs_distinct..TF) splitrr#name get_fieldrhasattrr$to_optsany)opts lookup_path lookup_fields field_namefield path_inforrrlookup_needs_distincts    r6cCs2|dr |d}|S|dr|dv}|S)zJ Return a lookup value prepared to be used in queryset filtering. __in,__isnull)false0)endswithr*lower)keyvaluerrrprepare_lookup_value5s   rAcCst|tr |tS|S)a* Ensure that primary key values do not confuse the admin URLs by escaping any '/', '_' and ':' and similarly problematic characters. Similar to urllib.parse.quote(), except that the quoting is slightly different so that it doesn't get automatically unquoted by the Web browser. ) isinstancestr translate QUOTE_MAPsrrrquoteBsrHcCstdd|S)zUndo the effects of quote().cSs t|dS)Nr) UNQUOTE_MAP)mrrrNs zunquote..) UNQUOTE_REsubrFrrrunquoteLsrNcCs6g}|D]}t|ttfr||q||q|S)zS Return a list which is a single level of flattening of the original list. )rBlisttupleextendappend)fieldsflatr4rrrflattenQs   rUcCs(g}|D] \}}|t|dq|S)z?Return a list of field names from an admin fieldsets structure.rS)rQrU) fieldsets field_namesr+r0rrrflatten_fieldsets^s   rXc sz|d}WntygitgfYSwt|jj}t|d}||tfdd|}fdd|j D}dd|j D}|||fS) a Find all objects related to ``objs`` that should also be deleted. ``objs`` must be a homogeneous iterable of objects (e.g. a QuerySet). Return a nested list of strings suitable for display in the template with the ``unordered_list`` filter. r)usingcs|j}|jv}|j}dt|j|f}|rOj||s%|jztdj|j |j fdt |j f}Wn t yD|YSwtdt|j||S|S)Nz%s: %sz%s:%s_%s_changez{}: {}) __class__ _registry_metar verbose_namehas_delete_permissionaddr r+ app_label model_namerHr#r r )objmodel has_adminr0 no_edit_link admin_url) admin_site perms_neededrequestrrformat_callbackzs2    z,get_deleted_objects..format_callbackcsg|]}|qSrr)rrb)rjrrrsz'get_deleted_objects..cSsi|] \}}|jjt|qSr)r\verbose_name_plurallen)rrcobjsrrrrsz'get_deleted_objects..) IndexErrorsetr db_for_writer\rc NestedObjectscollectnested protected model_objsitems) rmrirgrbrY collector to_deletert model_countr)rgrjrhrirget_deleted_objectshs      rzcsXeZdZfddZddZdfdd Zfdd Zd d Zdd d ZddZ Z S)rqcs.tj|i|i|_t|_tt|_dSr&)super__init__edgesrortrruselfargskwargsrZrrr|szNestedObjects.__init__cCs|j|g|dSr&)r} setdefaultrR)rsourcetargetrrradd_edgeszNestedObjects.add_edgeNc s|D].}|r |ds ||jj|jjd}|t|||n|d||j|jj|qz t j |fd|i|WSt j yY}z|j |jWYd}~dSd}~wt jys}z|j |jWYd}~dSd}~ww)N+)classr` source_attr)r=r\rar`rgetattrrurcr_r{rrrProtectedErrorrtupdateprotected_objectsRestrictedErrorrestricted_objects)rrmrrrrb related_nameerrrrrs$ zNestedObjects.collectcs$t|||}|jdd|DS)NcSsg|]}|jqSr)r+)r related_fieldrrrrsz1NestedObjects.related_objects..)r{related_objectsselect_related)r related_modelrelated_fieldsrmqsrrrrszNestedObjects.related_objectscCsj||vrgS||g}|j|dD] }|||||q|r)||g}n|g}|r3|||S)Nr)r_r}getrQ_nestedrR)rrbseenrjchildrenchildretrrrrs   zNestedObjects._nestedcCs6t}g}|jddD] }|||||q |S)z4 Return the graph as a nested list. Nr)ror}rrQr)rrjrrootsrootrrrrss zNestedObjects.nestedcOsdS)z We always want to load the objects into memory so that we can display them to the user in confirm page. Frr~rrrcan_fast_deleteszNestedObjects.can_fast_delete)NNr&) rr r!r|rrrrrrsr __classcell__rrrrrqs    rqcCsFt|tjtjjfr|j}nt|tjjr|jj}n|}|j |j dS)z Return a `dict` with keys 'verbose_name' and 'verbose_name_plural', typically for use with string formatting. `obj` may be a `Model` instance, `Model` subclass, or `QuerySet` instance. )r]rk) rBrModelbase ModelBaser\queryQuerySetrcr]rk)rbr0rrrmodel_format_dicts rcCsNt|tjjr|dur|}|j}t|}|d|d}}t|||p%dS)a- Return the appropriate `verbose_name` or `verbose_name_plural` value for `obj` depending on the count `n`. `obj` may be a `Model` instance, `Model` subclass, or `QuerySet` instance. If `obj` is a `QuerySet` instance, `n` is optional and the length of the `QuerySet` is used. Nr]rkr)rBrrrcountrcrr)rbndsingularpluralrrrmodel_ngettexts rc Cs|j}zt||}Wn:ttfyDt|r|}||}n"t||r1|dkr1t||}||}nt||}t|r>|}n|}d}Ynwd}t||}|||fS)N__str__)r\_get_non_gfk_fieldrrcallabler-r)r+rb model_adminr0fattrr@rrr lookup_fields&      rcCsR||}|jr|jr|jr|jrt|jr'|js't|dr'|j|kr't |S)a For historical reasons, the admin app relies on GenericForeignKeys as being "not found" by get_field(). This could likely be cleaned up. Reverse relations should also be excluded as these aren't attributes of the model (rather something like `foo_set`). attname) r, is_relation many_to_oner one_to_manyr many_to_manyr-rr)r0r+r4rrrr s  rFc Csd}zt|j|}z|j}Wnty|jjj}YnwWnty|dkr2t|jj}t}n~t|r9|}nCt||rDt ||}n8t||rOt ||}n-|r\||j vr\|j |}n d||jj f}|rn|d|j j 7}|rx|d|j j 7}t|t|dr|j}n+t|trt|drt|jdr|jj}nt|r|j dkrd}n t|j }nt|}Yntyt|}|}Ynw|r||fS|S) ak Return a sensible label for a field name. The name can be a callable, property (but not created with @property decorator), or the name of an object's attribute, as well as a model field. If return_attr is True, also return the resolved attribute (which could be a callable). This will be None if (and only if) the name refers to a field. NrzUnable to lookup '%s' on %sz or %sshort_descriptionfgetzz--)rr\r]AttributeErrorrrrCrr-rrS object_namerZrrrBpropertyrrr) r+rcr return_attrformrr4labelmessagerrrlabel_for_field5s`                 rc CsBd}zt|j|}Wn ttfyY|Swt|dr|j}|S)Nr: help_text)rr\rrr-r)r+rcrr4rrrhelp_text_for_fieldqs rcCs"ddlm}t|ddrt|j||St|tjr||S|dur%|St|tj r3t t |St|tjtjfrAt |St|tjrNt ||jSt|tjtjfr\t |St|tjrk|rktd|j|St|tjr|rz tj|d|jdWStyt||YSwt||S)Nr _boolean_icon flatchoicesz{}F) ensure_asciicls),django.contrib.admin.templatetags.admin_listrrdictrrrBr BooleanField DateTimeFieldr localizer template_localtime DateField TimeField DecimalField number_formatdecimal_places IntegerField FloatField FileFieldr url JSONFieldjsondumpsencoder TypeErrordisplay_for_value)r@r4empty_value_displayrrrrdisplay_for_field}s0         rcCsddlm}|r ||S|dur|St|trt|St|tjr)tt |St|tj tj fr7t|St|t t jtfrEt|St|ttfrVddd|DSt|S)Nrrz, css|]}t|VqdSr&)rC)rrrrrr)sz$display_for_value..)rrrBboolrCdatetimer rr rdatetimeintdecimalDecimalfloatrrOrPjoin)r@rbooleanrrrrrs     rc@s eZdZdS)NotRelationFieldN)rr r!rrrrrsrcCst|dr |djjSt)Nr$r%)r-r$r.rcr)r4rrrget_model_from_relations rc Csg}|}|t}|D]B}|j|}t|t|dkr.zt|Wn ty-Yn!w|jr@|jr7|j r@| }|j j }n|j j}|j}|d|q |t|fS)z Create a reversed field path. E.g. Given (Order, "user__groups"), return (Group, "user__order"). Final field must be a related model, not a data field. rr)r*rr\r,rlrrr auto_createdconcreterelated_query_name remote_fieldrcr4r+rinsertr)rcr( reversed_pathparentpiecespiecer4rrrrreverse_field_paths$     rcCsD|t}g}|D]}|rt|d}n|}||j|q |S)a; Return list of Fields given path relative to model. e.g. (ModelX, "user__groups__name") -> [ , , , ] r%)r*rrrRr\r,)rcr(rrSrrrrrget_fields_from_paths rc Cs:|j}td t||}Wdn1swYg}|r(|diin |jr4|dd|ii|rtdY|D]M}|jD]}|dt|jjt|diqB|jD]\}} |dt|jjt|t|j d| diqX|j D]} |dt| jjt| diqwq=Wd|S1swY|S) z Construct a JSON structure describing changes from a changed object. Translations are deactivated so that strings are stored untranslated. Translation happens later on LogEntry access. NaddedchangedrS)r+objectr)r+rrSdeleted) changed_datatranslation_override#_get_changed_field_labels_from_formrR new_objectsrCr\r]changed_objectsformsdeleted_objects) rformsetsr_rchanged_field_labelschange_messageformset added_objectchanged_objectchanged_fieldsdeleted_objectrrrconstruct_change_messagesP         r c CsLg}|D]}z |j|jp|}Wn ty|}Ynw|t|q|Sr&)rSrKeyErrorrRrC)rrrr3verbose_field_namerrrrs rr&)NFN)F)=rrr collectionsrdjango.core.exceptionsr django.dbrrdjango.db.models.constantsrdjango.db.models.deletionrdjango.forms.utilsr django.urlsr r django.utilsr r django.utils.htmlr django.utils.regex_helperrdjango.utils.textrdjango.utils.translationrrrrErvrIrrL Exceptionrr6rArHrNrUrXrzrqrrrrrrrrrrrrr rrrrrsR            8A   <  1