a
    Dgx                     @   s  d dl Z d dlZd dlmZ d dlmZ d dlmZ d dlm	Z	 d dl
mZ d dlmZmZmZ d dlmZmZ d d	lmZmZmZ d d
lmZ d dlmZ d dlmZ d dlmZ d dlm Z  G dd deZ!G dd dZ"G dd de e"e!Z#G dd deZ$G dd deZ%dS )    N)defaultdict)Iterable)Any)apps)ContentType)	CharFieldPrefetchQ)ExistsOuterRef)CastLengthSubstr)ModelIterable)MP_NodeQuerySet)Locale)Site)SearchableQuerySetMixinc                       s   e Zd ZdZ fddZde_d$ddZd%dd	Zd&d
dZdd Z	dd Z
dd Zd'ddZd(ddZd)ddZdd Zdd Zdd Zd*ddZd+d d!Zd,d"d#Z  ZS )-TreeQuerySetz]
    Extends Treebeard's MP_NodeQuerySet with additional useful tree-related operations.
    c                    s   t    dS )zNRedefine the delete method unbound, so we can set the queryset_only parameter.N)superdeleteself	__class__ L/var/www/lab.imftr.de/x/nb_venv/lib/python3.9/site-packages/wagtail/query.pyr      s    zTreeQuerySet.deleteTFc                 C   s2   t |jdt |jd@ }|s.|t |jd M }|S )NZpath__startswith)Z
depth__gtepk)r	   pathdepthr   r   other	inclusiveqr   r   r   descendant_of_q   s    zTreeQuerySet.descendant_of_qc                 C   s   |  | ||S )z
        This filters the QuerySet to only contain pages that descend from the specified page.

        If inclusive is set to True, it will also contain the page itself (instead of just its descendants).
        )filterr&   r   r#   r$   r   r   r   descendant_of'   s    zTreeQuerySet.descendant_ofc                 C   s   |  | ||S )z
        This filters the QuerySet to not contain any pages that descend from the specified page.

        If inclusive is set to True, it will also exclude the specified page.
        )excluder&   r(   r   r   r   not_descendant_of/   s    zTreeQuerySet.not_descendant_ofc                 C   s   |  |t|jd d@ S )N   r!   )r&   r	   r!   r   r#   r   r   r   
child_of_q7   s    zTreeQuerySet.child_of_qc                 C   s   |  | |S )zq
        This filters the QuerySet to only contain pages that are direct children of the specified page.
        )r'   r/   r.   r   r   r   child_of:   s    zTreeQuerySet.child_ofc                 C   s   |  | |S )zt
        This filters the QuerySet to not contain any pages that are direct children of the specified page.
        )r*   r/   r.   r   r   r   not_child_of@   s    zTreeQuerySet.not_child_ofc                    sR    fddt dt jd  jdd  D }t|d}|sN|t jd M }|S )Nc                    s   g | ]} j d | qS )r   r    ).0posr#   r   r   
<listcomp>G   s   z.TreeQuerySet.ancestor_of_q.<locals>.<listcomp>r   r,   )Zpath__inr   )rangelenr    steplenr	   r   )r   r#   r$   pathsr%   r   r5   r   ancestor_of_qF   s    

zTreeQuerySet.ancestor_of_qc                 C   s   |  | ||S )z
        This filters the QuerySet to only contain pages that are ancestors of the specified page.

        If inclusive is set to True, it will also include the specified page.
        )r'   r;   r(   r   r   r   ancestor_ofR   s    zTreeQuerySet.ancestor_ofc                 C   s   |  | ||S )z
        This filters the QuerySet to not contain any pages that are ancestors of the specified page.

        If inclusive is set to True, it will also exclude the specified page.
        )r*   r;   r(   r   r   r   not_ancestor_ofZ   s    zTreeQuerySet.not_ancestor_ofc                 C   s   t | j|jdS )Nr2   )r	   model_get_parent_path_from_pathr    r.   r   r   r   parent_of_qb   s    zTreeQuerySet.parent_of_qc                 C   s   |  | |S )z]
        This filters the QuerySet to only contain the parent of the specified page.
        )r'   r@   r.   r   r   r   	parent_ofe   s    zTreeQuerySet.parent_ofc                 C   s   |  | |S )zX
        This filters the QuerySet to exclude the parent of the specified page.
        )r*   r@   r.   r   r   r   not_parent_ofk   s    zTreeQuerySet.not_parent_ofc                 C   s:   t | j|jdt |jd@ }|s6|t |jd M }|S )Nr   r-   r   )r	   r>   r?   r    r!   r   r"   r   r   r   sibling_of_qq   s    zTreeQuerySet.sibling_of_qc                 C   s   |  | ||S )a!  
        This filters the QuerySet to only contain pages that are siblings of the specified page.

        By default, inclusive is set to True so it will include the specified page in the results.

        If inclusive is set to False, the page will be excluded from the results.
        )r'   rC   r(   r   r   r   
sibling_of{   s    zTreeQuerySet.sibling_ofc                 C   s   |  | ||S )a$  
        This filters the QuerySet to not contain any pages that are siblings of the specified page.

        By default, inclusive is set to True so it will exclude the specified page from the results.

        If inclusive is set to False, the page will be included in the results.
        )r*   rC   r(   r   r   r   not_sibling_of   s    zTreeQuerySet.not_sibling_of)F)F)F)F)F)F)T)T)T)__name__
__module____qualname____doc__r   Zqueryset_onlyr&   r)   r+   r/   r0   r1   r;   r<   r=   r@   rA   rB   rC   rD   rE   __classcell__r   r   r   r   r      s$   









r   c                       sn   e Zd Z fddZ fddZdddZedd	 Zdd
ed
 fddZ	dd
ed
 fddZ
  ZS )SpecificQuerySetMixinc                    s(   t  j|i | d| _d| _d| _dS )zSet custom instance attributesFr   N)r   __init___defer_streamfields_specific_select_related_fields"_specific_prefetch_related_lookups)r   argskwargsr   r   r   rL      s    zSpecificQuerySetMixin.__init__c                    s&   t   }| j|_| j|_| j|_|S )z.Ensure clones inherit custom attribute values.)r   _clonerM   rN   rO   )r   cloner   r   r   rR      s    
zSpecificQuerySetMixin._cloneFc                 C   s   |   }|rt|_nt|_|S )a  
        This efficiently gets all the specific items for the queryset, using
        the minimum number of queries.

        When the "defer" keyword argument is set to True, only generic
        field values will be loaded and all specific fields will be deferred.
        )rR   DeferredSpecificIterable_iterable_classSpecificIterable)r   deferrS   r   r   r   specific   s
    zSpecificQuerySetMixin.specificc                 C   s   t | jttfS )zU
        Returns True if this queryset is already specific, False otherwise.
        )
issubclassrU   rV   rT   r   r   r   r   is_specific   s    z!SpecificQuerySetMixin.is_specific)for_specific_subqueriesc                   sD   |st  j| S |std|  }|dkr4d|_n| j| |_|S )an
  
        Overrides Django's native :meth:`~django.db.models.query.QuerySet.select_related`
        to allow related objects to be fetched by the subqueries made when a specific
        queryset is evaluated.

        When ``for_specific_subqueries`` is ``False`` (the default), the method functions
        exactly like the original method. However, when ``True``, ``fields`` are
        **required**, and must match names of ForeignKey fields on all specific models
        that might be included in the result (which can include fields inherited from
        concrete parents). Unlike when ``for_specific_subqueries`` is ``False``, no
        validation is applied to ``fields`` when the method is called. Rather, that when
        the method is called. Instead, that validation is applied for each individual
        subquery when the queryset is evaluated. This difference in behaviour should be
        taken into account when experimenting with ``for_specific_subqueries=True`` .

        As with Django's native implementation, you chain multiple applications of
        ``select_related()`` with ``for_specific_subqueries=True`` to progressively add
        to the list of fields to be fetched. For example:

        .. code-block:: python

            # Fetch 'author' when retrieving specific page data
            queryset = Page.objects.specific().select_related("author", for_specific_subqueries=True)

            # We're rendering cards with images, so fetch the listing image too
            queryset = queryset.select_related("listing_image", for_specific_subqueries=True)

            # Fetch some key taxonomy data too
            queryset = queryset.select_related("topic", "target_audience", for_specific_subqueries=True)

        As with Django's native implementation, ``None`` can be supplied in place of
        ``fields`` to negate a previous application of ``select_related()``. By default,
        this will only work for cases where ``select_related()`` was called without
        ``for_specific_subqueries``, or with ``for_specific_subqueries=False``. However,
        you can use ``for_specific_subqueries=True`` to negate subquery-specific
        applications too. For example:

        .. code-block:: python

            # Fetch 'author' and 'listing_image' when retrieving specific page data
            queryset = Page.objects.specific().select_related(
                "author",
                "listing_image",
                for_specific_subqueries=True
            )

            # I've changed my mind. Do not fetch any additional data
            queryset = queryset.select_related(None, for_specific_subqueries=True)
        zZ'fields' must be specified when calling select_related() with for_specific_subqueries=TrueNr   )r   select_related
ValueError_chainrN   )r   r[   fieldsrS   r   r   r   r]      s    3z$SpecificQuerySetMixin.select_relatedc                   sD   |st  j| S |std|  }|dkr4d|_n| j| |_|S )a
  
        Overrides Django's native :meth:`~django.db.models.query.QuerySet.prefetch_related`
        implementation to allow related objects to be fetched alongside the subqueries made
        when a specific queryset is evaluated.

        When ``for_specific_subqueries`` is ``False`` (the default), the method functions
        exactly like the original method. However, when ``True``, ``lookups`` are
        **required**, and must match names of related fields on all specific models that
        might be included in the result (which can include relationships inherited from
        concrete parents). Unlike when ``for_specific_subqueries`` is ``False``, no
        validation is applied to ``lookups`` when the method is called. Instead, that
        validation is applied for each individual subquery when the queryset is
        evaluated. This difference in behaviour should be taken into account when
        experimenting with ``for_specific_subqueries=True``.

        As with Django's native implementation, you chain multiple applications of
        ``prefetch_related()`` with ``for_specific_subqueries=True`` to progressively
        add to the list of lookups to be made. For example:

        .. code-block:: python

            # Fetch 'contributors' when retrieving specific page data
            queryset = Page.objects.specific().prefetch_related("contributors", for_specific_subqueries=True)

            # We're rendering cards with images, so prefetch listing image renditions too
            queryset = queryset.prefetch_related("listing_image__renditions", for_specific_subqueries=True)

            # Fetch some key taxonomy data also
            queryset = queryset.prefetch_related("tags", for_specific_subqueries=True)

        As with Django's native implementation, ``None`` can be supplied in place of
        ``lookups`` to negate a previous application of ``prefetch_related()``. By default,
        this will only work for cases where ``prefetch_related()`` was called without
        ``for_specific_subqueries``, or with ``for_specific_subqueries=False``. However,
        you can use ``for_specific_subqueries=True`` to negate subquery-specific
        applications too. For example:

        .. code-block:: python

            # Fetch 'contributors' and 'listing_image' renditions when retrieving specific page data
            queryset = Page.objects.specific().prefetch_related(
                "contributors",
                "listing_image__renditions",
                for_specific_subqueries=True
            )

            # I've changed my mind. Do not make any additional queries
            queryset = queryset.prefetch_related(None, for_specific_subqueries=True)
        z\'lookups' must be provided when calling prefetch_related() with for_specific_subqueries=Truer\   r   )r   prefetch_relatedr^   r_   rO   )r   r[   lookupsrS   r   r   r   ra      s    2z&SpecificQuerySetMixin.prefetch_related)F)rF   rG   rH   rL   rR   rX   propertyrZ   boolr]   ra   rJ   r   r   r   r   rK      s   


	BrK   c                   @   s  e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd?d(d)Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd@d2d3ZdAd4d5Zd6d7 Zd8d9 Zd:d; Zd<d= Z d>S )BPageQuerySetc                 C   s
   t ddS )NT)liver	   r   r   r   r   live_qA  s    zPageQuerySet.live_qc                 C   s   |  |  S )zL
        This filters the QuerySet to only contain published pages.
        )r'   rh   r   r   r   r   rf   D  s    zPageQuerySet.livec                 C   s   |  |  S )zN
        This filters the QuerySet to only contain unpublished pages.
        )r*   rh   r   r   r   r   not_liveJ  s    zPageQuerySet.not_livec                 C   s
   t ddS )NT)Zshow_in_menusrg   r   r   r   r   	in_menu_qP  s    zPageQuerySet.in_menu_qc                 C   s   |  |  S )zX
        This filters the QuerySet to only contain pages that are in the menus.
        )r'   rj   r   r   r   r   in_menuS  s    zPageQuerySet.in_menuc                 C   s   |  |  S )z\
        This filters the QuerySet to only contain pages that are not in the menus.
        )r*   rj   r   r   r   r   not_in_menuY  s    zPageQuerySet.not_in_menuc                 C   s   t |jdS )N)id)r	   rm   r.   r   r   r   page_q_  s    zPageQuerySet.page_qc                 C   s   |  | |S )zS
        This filters the QuerySet so it only contains the specified page.
        )r'   rn   r.   r   r   r   pageb  s    zPageQuerySet.pagec                 C   s   |  | |S )zU
        This filters the QuerySet so it doesn't contain the specified page.
        )r*   rn   r.   r   r   r   not_pageh  s    zPageQuerySet.not_pagec                    s4    fddt  D }tjj| }tt| dS )Nc                    s   h | ]}t | r|qS r   )rY   )r3   r>   typesr   r   	<setcomp>o  s   z&PageQuerySet.type_q.<locals>.<setcomp>Zcontent_type__in)r   Z
get_modelsr   objectsget_for_modelsr	   listvalues)r   rr   Zall_subclassescontent_typesr   rq   r   type_qn  s
    
zPageQuerySet.type_qc                 G   s   |  | j| S )z
        This filters the QuerySet to only contain pages that are an instance
        of the specified model(s) (including subclasses).
        )r'   rz   r   rr   r   r   r   typeu  s    zPageQuerySet.typec                 G   s   |  | j| S )zq
        This filters the QuerySet to exclude any pages which are an instance of the specified model(s).
        )r*   rz   r{   r   r   r   not_type|  s    zPageQuerySet.not_typec                 G   s   t jj| }tt| dS )Nrt   )r   ru   rv   r	   rw   rx   )r   rr   ry   r   r   r   exact_type_q  s    zPageQuerySet.exact_type_qc                 G   s   |  | j| S )z
        This filters the QuerySet to only contain pages that are an instance of the specified model(s)
        (matching the model exactly, not subclasses).
        )r'   r~   r{   r   r   r   
exact_type  s    zPageQuerySet.exact_typec                 G   s   |  | j| S )z
        This filters the QuerySet to exclude any pages which are an instance of the specified model(s)
        (matching the model exactly, not subclasses).
        )r*   r~   r{   r   r   r   not_exact_type  s    zPageQuerySet.not_exact_typec                 C   sN   ddl m} t }|jd D ]}|| j|jddO }q"|rD|S tg dS )Nr   )PageViewRestrictionro   Tr$   Zpk__in)Zwagtail.modelsr   r	   ru   r]   allr&   ro   )r   r   r%   Zrestrictionr   r   r   	private_q  s
    zPageQuerySet.private_qc                 C   s   |  |  S )z}
        Filters the QuerySet to only contain pages that are not in a private
        section and their descendants.
        )r*   r   r   r   r   r   public  s    zPageQuerySet.publicc                 C   s   |  |  S zy
        Filters the QuerySet to only contain pages that are in a private
        section and their descendants.
        r'   r   r   r   r   r   
not_public  s    zPageQuerySet.not_publicc                 C   s   |  |  S r   r   r   r   r   r   private  s    zPageQuerySet.privateFc                 C   s   |   s"|r| jd| j S |r:|  jddd}n<|  jtddtd| jj	 t
dddd	jd
dd }t|}t|| jj	 }|dkr|d|  }|dkr|r| jd| j S | jjj|dS )a7  
        Find the first ancestor that all pages in this queryset have in common.
        For example, consider a page hierarchy like::

            - Home/
                - Foo Event Index/
                    - Foo Event Page 1/
                    - Foo Event Page 2/
                - Bar Event Index/
                    - Bar Event Page 1/
                    - Bar Event Page 2/

        The common ancestors for some queries would be:

        .. code-block:: python

            >>> Page.objects\
            ...     .type(EventPage)\
            ...     .first_common_ancestor()
            <Page: Home>
            >>> Page.objects\
            ...     .type(EventPage)\
            ...     .filter(title__contains='Foo')\
            ...     .first_common_ancestor()
            <Page: Foo Event Index>

        This method tries to be efficient, but if you have millions of pages
        scattered across your page tree, it will be slow.

        If `include_self` is True, the ancestor can be one of the pages in the
        queryset:

        .. code-block:: python

            >>> Page.objects\
            ...     .filter(title__contains='Foo')\
            ...     .first_common_ancestor()
            <Page: Foo Event Index>
            >>> Page.objects\
            ...     .filter(title__exact='Bar Event Index')\
            ...     .first_common_ancestor()
            <Page: Bar Event Index>

        A few invalid cases exist: when the queryset is empty, when the root
        Page is in the queryset and ``include_self`` is False, and when there
        are multiple page trees with no common root (a case Wagtail does not
        support). If ``strict`` is False (the default), then the first root
        node is returned in these cases. If ``strict`` is True, then a
        ``ObjectDoesNotExist`` is raised.
        z'Can not find ancestor of empty querysetr    T)Zflatr,      )
max_lengthZoutput_field)parent_pathr   r   N zNo common ancestor found!r2   )existsr>   ZDoesNotExistZget_first_root_nodeZorder_byZvalues_listannotater   r   r9   r   Zdistinct	posixpathcommonprefixr8   ru   get)r   Zinclude_selfstrictr:   Zcommon_parent_pathZextra_charsr   r   r   first_common_ancestor  s4    4
	

z"PageQuerySet.first_common_ancestorc                 C   s   |   D ]}|  qdS )zB
        This unpublishes all live pages in the QuerySet.
        N)rf   	unpublish)r   ro   r   r   r   r     s    zPageQuerySet.unpublishc                 C   s*   |   }d|_| j }|s |S |j| S )a7  
        Apply to a queryset to prevent fetching/decoding of StreamField values on
        evaluation. Useful when working with potentially large numbers of results,
        where StreamField values are unlikely to be needed. For example, when
        generating a sitemap or a long list of page links.
        T)rR   rM   r>   Zget_streamfield_namesrW   )r   rS   Zstreamfield_namesr   r   r   defer_streamfields$  s    
zPageQuerySet.defer_streamfieldsc                 C   s   | j |jddS )z\
        This filters the QuerySet to only contain pages within the specified site.
        Tr   )r)   Z	root_page)r   siter   r   r   in_site2  s    zPageQuerySet.in_sitec                 C   s&   t |jd}|s"|t |jd M }|S )Ntranslation_keyr   )r	   r   r   )r   ro   r$   r%   r   r   r   translation_of_q8  s    zPageQuerySet.translation_of_qc                 C   s   |  | ||S )z
        This filters the QuerySet to only contain pages that are translations of the specified page.

        If inclusive is True, the page itself is returned.
        )r'   r   r   ro   r$   r   r   r   translation_of@  s    zPageQuerySet.translation_ofc                 C   s   |  | ||S )a`  
        This filters the QuerySet to only contain pages that are not translations of the specified page.

        Note, this will include the page itself as the page is technically not a translation of itself.
        If inclusive is True, we consider the page to be a translation of itself so this excludes the page
        from the results.
        )r*   r   r   r   r   r   not_translation_ofH  s    zPageQuerySet.not_translation_ofc                 C   s>   ddl m} |j d}d}| jr*d}| t||ddS )a  
        Performance optimisation for listing pages.
        Prefetches the active workflow states on each page in this queryset.
        Used by `workflow_in_progress` and `current_workflow_progress` properties on
        `wagtailcore.models.Page`.
        r,   )WorkflowStateZcurrent_task_state__taskZ_workflow_statesZ_specific_workflow_statesZ_current_workflow_states)querysetZto_attr)modelsr   ru   activer]   rZ   ra   r   )r   r   Zworkflow_statesZrelationr   r   r   prefetch_workflow_statesR  s    
z%PageQuerySet.prefetch_workflow_statesc                 C   s<   ddl m} | jt|jjddjttdt	 dddS )	z
        Performance optimisation for listing pages.
        Annotates each page with the existence of an approved go live time.
        Used by `approved_schedule` property on `wagtailcore.models.Page`.
        r,   )RevisionT)Zapproved_go_live_at__isnullr   r   )Z	object_id)Z_approved_schedule)
r   r   r   r
   Zpage_revisionsr*   r'   r   r   r   )r   r   r   r   r   annotate_approved_schedulek  s    z'PageQuerySet.annotate_approved_schedulec                 C   s   | j ttjjtdddS )z
        Performance optimisation for listing pages.
        Annotates each object with whether it is a root page of any site.
        Used by `is_site_root` method on `wagtailcore.models.Page`.
        r   )Zroot_page__translation_key)Z_is_site_root)r   r
   r   ru   r'   r   r   r   r   r   annotate_site_root_state{  s    z%PageQuerySet.annotate_site_root_statec                 C   s4   | j ttjj| jjjttdddddS )Nr   r   Z	locale_id)Zid__in)Z_has_untranslated_locale)	r   r
   r   ru   r*   r>   r'   r   rx   r   r   r   r    annotate_has_untranslated_locale  s    
z-PageQuerySet.annotate_has_untranslated_localeN)FF)F)F)!rF   rG   rH   rh   rf   ri   rj   rk   rl   rn   ro   rp   rz   r|   r}   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   re   @  s<   

j


re   c                   @   s2   e Zd Zdd Zeeeeef   dddZ	dS )rV   c              
   #   s  | j }|jj |jddg R  }| |D ]}tt} rf|D ]"} fdd| D ||d < qBdd |D }tt}|D ]\}}	||	 | qdd |D }
i }g }| D ]\}	}|
|	 	 p|j
}|jj|d}|jr|j|j }|jr|j|j }|jr t|d	r | }d
d |D ||	< |fdd|D  q|r|j
jj|dd }tjddd | D td ni }|D ]n\}}	z||	 | }W n ty   || }Y n0  r||ji  D ]\}}t||| q|V  qq,dS )z
        Identify and return all specific items in a queryset, and return them
        in the same order, with any annotations intact.
        r   content_typec                    s   i | ]\}}| v r||qS r   r   )r3   kv)annotation_aliasesr   r   
<dictcomp>  s   z-SpecificIterable.__iter__.<locals>.<dictcomp>c                 S   s   g | ]}|d  |d gqS )r   r   r   )r3   r   r   r   r   r6         z-SpecificIterable.__iter__.<locals>.<listcomp>c                 S   s   i | ]\}}|t j|qS r   )r   ru   Z
get_for_id)r3   _r   r   r   r   r     s   r   r   c                 S   s   i | ]}|j |qS r   r   )r3   itemr   r   r   r     r   c                 3   s   | ]}| vr|V  qd S r\   r   )r3   r   )items_for_typer   r   	<genexpr>  r   z,SpecificIterable.__iter__.<locals>.<genexpr>zSpecific versions of the following items could not be found. This is most likely because a database migration has removed the relevant table or record since the item was created:
{}c                 S   s   g | ]}|j |j|jd qS ))rm   titler|   )rm   r   r   )r3   pr   r   r   r6     s   categoryN)r   queryZannotation_selectrx   _get_chunksr   rw   itemsappendZmodel_classr>   ru   r'   rN   r]   rO   ra   rM   hasattrr   extendZin_bulkwarningswarnformatRuntimeWarningKeyErrorr   r   setattr)r   qsZ	values_qsrx   Zannotations_by_pkdataZpks_and_typesZpks_by_typer   r   ry   Zitems_by_typeZmissing_pksZpksr>   r   Zgeneric_itemsr   
annotationvaluer   )r   r   r   __iter__  sp    
zSpecificIterable.__iter__)returnc                 c   sd   | j st|V  nNg }|| jD ].}|| t|| jkr"t|V  |  q"|r`t|V  d S r\   )Zchunked_fetchtupleiterator
chunk_sizer   r8   clear)r   r   Zcurrent_chunkrr   r   r   r     s    


zSpecificIterable._get_chunksN)
rF   rG   rH   r   r   r   dictstrr   r   r   r   r   r   rV     s   WrV   c                       s   e Zd Z fddZ  ZS )rT   c                 #   s\   t   D ]L}|jr|jV  q
tjd|jj d|j d|j	 d|j
 d	td |V  q
d S )NzA specific version of the following object could not be returned because the specific model is not present on the active branch: <z id='z	' title='z' type='z'>r   )r   r   Zspecific_classZspecific_deferredr   r   r   rF   rm   r   r   r   )r   objr   r   r   r     s     
z!DeferredSpecificIterable.__iter__)rF   rG   rH   r   rJ   r   r   r   r   rT      s   rT   )&r   r   collectionsr   collections.abcr   typingr   Zdjango.appsr   Z"django.contrib.contenttypes.modelsr   Zdjango.db.modelsr   r   r	   Zdjango.db.models.expressionsr
   r   Zdjango.db.models.functionsr   r   r   Zdjango.db.models.queryr   Ztreebeard.mp_treer   Zwagtail.models.i18nr   Zwagtail.models.sitesr   Zwagtail.search.querysetr   r   rK   re   rV   rT   r   r   r   r   <module>   s,   | 1  Wk