U
    Ha+                     @   s   d 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eZG dd deZG dd deZdS )al  
"Rel objects" for related fields.

"Rel objects" (for lack of a better name) carry information about the relation
modeled by a related field and provide some utility functions. They're stored
in the ``remote_field`` attribute of the field.

They also act as reverse fields for the purposes of the Meta API because
they're the closest concept currently available.
    )
exceptions)cached_property)make_hashable   )BLANK_CHOICE_DASH)FieldCacheMixinc                   @   s,  e Zd ZdZdZdZdZdZdZdZ	d8ddZ
edd Zed	d
 Zedd Zedd Zedd Zedd Zedd Zedd Zedd Zdd Zdd Zedd Zdd  Zed!d" Zd#d$ Zd%d& Zdedd'fd(d)Zd*d+ Zd,d- Z d.d/ Z!d0d1 Z"d9d2d3Z#d:d4d5Z$d6d7 Z%dS );ForeignObjectRelz
    Used by ForeignObject to store information about the relation.

    ``_meta.get_fields()`` returns this class to provide access to the field
    flags for the reverse relation.
    TFNc                 C   sF   || _ || _|| _|| _|d kr$i n|| _|| _|| _d| _d| _d S )NFT)	fieldmodelrelated_namerelated_query_namelimit_choices_toparent_link	on_deletesymmetricalmultiple)selfr	   tor   r   r   r   r    r   K/tmp/pip-unpacked-wheel-3jxiddxt/django/db/models/fields/reverse_related.py__init__'   s    zForeignObjectRel.__init__c                 C   s   |   S N)	is_hiddenr   r   r   r   hidden8   s    zForeignObjectRel.hiddenc                 C   s
   | j  S r   )r	   r   r   r   r   r   name<   s    zForeignObjectRel.namec                 C   s   | j S r   )r	   r   r   r   r   remote_field@   s    zForeignObjectRel.remote_fieldc                 C   s,   |   d j}t|dkr$td|d S )z
        When filtering against this relation, return the field on the remote
        model against which the filtering should happen.
        r   z1Can't use target_field for multicolumn relations.r   )get_path_infotarget_fieldslenr   Z
FieldError)r   r   r   r   r   target_fieldD   s    
zForeignObjectRel.target_fieldc                 C   s   | j jstd| j jS )NzVThis property can't be accessed before self.field.contribute_to_class has been called.)r	   r
   AttributeErrorr   r   r   r   related_modelO   s
    zForeignObjectRel.related_modelc                 C   s   | j jS r   )r	   many_to_manyr   r   r   r   r$   V   s    zForeignObjectRel.many_to_manyc                 C   s   | j jS r   )r	   one_to_manyr   r   r   r   many_to_oneZ   s    zForeignObjectRel.many_to_onec                 C   s   | j jS r   )r	   r&   r   r   r   r   r%   ^   s    zForeignObjectRel.one_to_manyc                 C   s   | j jS r   )r	   
one_to_oner   r   r   r   r'   b   s    zForeignObjectRel.one_to_onec                 C   s   | j |S r   )r	   
get_lookup)r   lookup_namer   r   r   r(   f   s    zForeignObjectRel.get_lookupc                 C   s
   | j  S r   )r	   get_internal_typer   r   r   r   r*   i   s    z"ForeignObjectRel.get_internal_typec                 C   s   | j jS r   )r	   db_typer   r   r   r   r+   l   s    zForeignObjectRel.db_typec                 C   s    dt | j| jjj| jjjf S )Nz<%s: %s.%s>)type__name__r#   _metaZ	app_label
model_namer   r   r   r   __repr__p   s
    zForeignObjectRel.__repr__c              	   C   s,   | j | j| j| jt| j| j| j| j| j	f	S r   )
r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   identityw   s    zForeignObjectRel.identityc                 C   s   t || jstS | j|jkS r   )
isinstance	__class__NotImplementedr1   )r   otherr   r   r   __eq__   s    zForeignObjectRel.__eq__c                 C   s
   t | jS r   )hashr1   r   r   r   r   __hash__   s    zForeignObjectRel.__hash__r   c                 C   s@   |p| j }| jj|}|r&|j| }|r.|ng dd |D  S )a  
        Return choices with a default blank choices included, for use
        as <select> choices for this field.

        Analog of django.db.models.fields.Field.get_choices(), provided
        initially for utilization by RelatedFieldListFilter.
        c                 S   s   g | ]}|j t|fqS r   )pkstr).0xr   r   r   
<listcomp>   s    z0ForeignObjectRel.get_choices.<locals>.<listcomp>)r   r#   Z_default_managerZcomplex_filterZorder_by)r   Zinclude_blankZblank_choicer   Zorderingqsr   r   r   get_choices   s    

zForeignObjectRel.get_choicesc                 C   s   t | jo| jd dkS )z$Should the related object be hidden?r   +)boolr   r   r   r   r   r      s    zForeignObjectRel.is_hiddenc                 C   s
   | j  S r   )r	   Zget_reverse_joining_columnsr   r   r   r   get_joining_columns   s    z$ForeignObjectRel.get_joining_columnsc                 C   s   | j |||S r   )r	   get_extra_restriction)r   Zwhere_classaliasZrelated_aliasr   r   r   rC      s    z&ForeignObjectRel.get_extra_restrictionc                 C   s
   d| _ dS )z
        Set the related field's name, this is not available until later stages
        of app loading, so set_field_name is called from
        set_attributes_from_rel()
        N)
field_namer   r   r   r   set_field_name   s    zForeignObjectRel.set_field_namec                 C   sV   |r
|j n| jj }|p| j}| jr6| jr6|| jkr6d S | jrB| jS |j| jrPdnd S )NZ_set )r.   r#   r   r   r
   r   r/   )r   r
   optsr   r   r   get_accessor_name   s    
z"ForeignObjectRel.get_accessor_namec                 C   s   | j |S r   )r	   Zget_reverse_path_info)r   Zfiltered_relationr   r   r   r      s    zForeignObjectRel.get_path_infoc                 C   s   |   S )z
        Return the name of the cache key to use for storing an instance of the
        forward model on the reverse model.
        )rI   r   r   r   r   get_cache_name   s    zForeignObjectRel.get_cache_name)NNNFN)N)N)&r-   
__module____qualname____doc__Zauto_createdconcreteeditableZis_relationnullZempty_strings_allowedr   r   r   r   propertyr   r!   r#   r$   r&   r%   r'   r(   r*   r+   r0   r1   r6   r8   r   r?   r   rB   rC   rF   rI   r   rJ   r   r   r   r   r      sf         












  



r   c                       sJ   e Zd ZdZd fdd	Zdd Ze fdd	Zd
d Zdd Z	  Z
S )ManyToOneRela+  
    Used by the ForeignKey field to store information about the relation.

    ``_meta.get_fields()`` returns this class to provide access to the field
    flags for the reverse relation.

    Note: Because we somewhat abuse the Rel objects by using them as reverse
    fields we get the funny situation where
    ``ManyToOneRel.many_to_one == False`` and
    ``ManyToOneRel.one_to_many == True``. This is unfortunate but the actual
    ManyToOneRel class is a private API and there is work underway to turn
    reverse relations into actual fields.
    NFc	           	   	      s$   t  j|||||||d || _d S )Nr   r   r   r   r   )superr   rE   	r   r	   r   rE   r   r   r   r   r   r3   r   r   r      s     	zManyToOneRel.__init__c                 C   s   | j  }|dd  |S )Nr#   )__dict__copypop)r   stater   r   r   __getstate__   s    
zManyToOneRel.__getstate__c                    s   t  j| jf S r   )rT   r1   rE   r   rV   r   r   r1      s    zManyToOneRel.identityc                 C   s*   | j j| j}|js&td| j |S )zY
        Return the Field in the 'to' object to which this relationship is tied.
        zNo related field named '%s')r
   r.   	get_fieldrE   rN   r   ZFieldDoesNotExist)r   r	   r   r   r   get_related_field   s    zManyToOneRel.get_related_fieldc                 C   s   | j p| jjjj| _ d S r   )rE   r
   r.   r9   r   r   r   r   r   rF      s    zManyToOneRel.set_field_name)NNNFN)r-   rK   rL   rM   r   r[   rQ   r1   r]   rF   __classcell__r   r   rV   r   rR      s         	rR   c                       s"   e Zd ZdZd fdd	Z  ZS )OneToOneRelz
    Used by OneToOneField to store information about the relation.

    ``_meta.get_fields()`` returns this class to provide access to the field
    flags for the reverse relation.
    NFc	           	   
      s&   t  j||||||||d d| _d S )NrS   F)rT   r   r   rU   rV   r   r   r   
  s      	zOneToOneRel.__init__)NNNFN)r-   rK   rL   rM   r   r^   r   r   rV   r   r_     s         r_   c                       s:   e Zd ZdZd
 fdd	Ze fddZdd	 Z  ZS )ManyToManyRelz
    Used by ManyToManyField to store information about the relation.

    ``_meta.get_fields()`` returns this class to provide access to the field
    flags for the reverse relation.
    NTc
           
         sR   t  j|||||d |r&|	s&td|| _|r<|s<td|| _|| _|	| _d S )N)r   r   r   z4Can't supply a through model and db_constraint=Falsez5Cannot specify through_fields without a through model)rT   r   
ValueErrorthroughthrough_fieldsr   db_constraint)
r   r	   r   r   r   r   r   rb   rc   rd   rV   r   r   r      s     zManyToManyRel.__init__c                    s   t  j| jt| j| jf S r   )rT   r1   rb   r   rc   rd   r   rV   r   r   r1   5  s
    zManyToManyRel.identityc                 C   sV   | j j}| jr || jd }n,|jD ]$}t|dd}|r&|j| jkr& qLq&|jd S )z
        Return the field in the 'to' object to which this relationship is tied.
        Provided for symmetry with ManyToOneRel.
        r   r   N)rb   r.   rc   r\   fieldsgetattrr
   Zforeign_related_fields)r   rH   r	   relr   r   r   r]   =  s    
zManyToManyRel.get_related_field)NNNTNNT)	r-   rK   rL   rM   r   rQ   r1   r]   r^   r   r   rV   r   r`     s            r`   N)rM   Zdjango.corer   Zdjango.utils.functionalr   Zdjango.utils.hashabler   rG   r   Zmixinsr   r   rR   r_   r`   r   r   r   r   <module>   s    =2