
    h                         d Z ddlmZ ddlmZ ddlmZ ddlmZ d Z	 G d dej                        Z G d	 d
      Z G d d      Z G d d      Zy)a  
All fields that are attached to the models.

The core design of django-parler is to attach descriptor fields
to the shared model, which then proxies the get/set calls to the translated model.

The :class:`TranslatedField` objects are automatically added to the shared model,
but may be added explicitly as well. This also allows to set the ``any_language`` configuration option.
It's also useful for abstract models; add a :class:`TranslatedField` to
indicate that the derived model is expected to provide that translatable field.
    )ImproperlyConfigured)models)ForwardManyToOneDescriptor)pretty_namec                 (   | j                   rt        | j                   t              st        | j                   d      | j                   j
                  j                  }|j                  }|j                  dk(  r|S 	 |j                  }|k|j                  |       rt        d|j                   d      |j                  |j                        r&t        d|j                   d|j                   d      |S # t        $ r t        d| d      w xY w)	z^
    Check whether the 'master' field on a TranslatedFieldsModel is correctly configured.
    z3.master should be a ForeignKey to the shared table.__fake__zTranslatable model z2 does not appear to inherit from TranslatableModelzThe model 'z.' already has an associated translation table!z5' already has an associated translation field named 'z'!)master
isinstancer   r   __name__fieldremote_fieldmodel
__module___parler_metaAttributeError	TypeError_has_translations_model_has_translations_fieldrelated_name)	new_classr   shared_modelmetas       =/home/dcms/DCMS/lib/python3.12/site-packages/parler/fields.py_validate_masterr      sI    :i.>.>@Z#["!!""UV
 	
 ##))66L%%L *,
(( ''	2&l3344bc  ''(A(AB&l3344ijv  kD  kD  jE  EG  H    
!,/ab
 	

s   =C8 8Dc                   "     e Zd ZdZ fdZ xZS )TranslationsForeignKeyzE
    Foreign Key field that adds translations to the `to` model.
    c                     ddl m} t        |   ||       t	        | j
                         t        | j
                  |      r| j
                  j                  |       y y )Nr   )TranslatedFieldsModelMixin)parler.modelsr   supercontribute_to_related_classr   r   
issubclasscontribute_translations)selfclsrelatedr   	__class__s       r   r!   z2TranslationsForeignKey.contribute_to_related_class;   sG    <+C9$djj"<=JJ..s3 >    )r   r   __qualname____doc__r!   __classcell__)r'   s   @r   r   r   6   s    4 4r(   r   c                   .    e Zd ZdZddZd Zed        Zy)TranslatedFielda=  
    Proxy field attached to a model.

    The field is automatically added to the shared model.
    However, this can be assigned manually to be more explicit, or to pass the ``any_language`` value.
    The ``any_language=True`` option causes the attribute to always return a translated value,
    even when the current language and fallback are missing.
    This can be useful for "title" attributes for example.

    Example:

    .. code-block:: python

        from django.db import models
        from parler.models import TranslatableModel, TranslatedFieldsModel

        class MyModel(TranslatableModel):
            title = TranslatedField(any_language=True)  # Add with any-fallback support
            slug = TranslatedField()                    # Optional, but explicitly mentioned


        class MyModelTranslation(TranslatedFieldsModel):
            # Manual model class:
            master = models.ForeignKey(MyModel, related_name='translations', null=True)
            title = models.CharField("Title", max_length=200)
            slug = models.SlugField("Slug")
    c                 <    d | _         d | _        || _        d | _        y N)r   nameany_language_meta)r$   r1   s     r   __init__zTranslatedField.__init__b   s    
	(
r(   c                 `    || _         || _        t        || j                  t        |              y r/   )r   r0   setattrTranslatedFieldDescriptor)r$   r%   r0   kwargss       r   contribute_to_classz#TranslatedField.contribute_to_classh   s(    
	 	TYY 9$ ?@r(   c                     | j                   4| j                  j                  j                  | j                        | _         | j                   S r/   )r2   r   r   _get_extension_by_fieldr0   r$   s    r   r   zTranslatedField.metap   s6    ::00HHSDJzzr(   N)F)r   r   r)   r*   r3   r8   propertyr    r(   r   r-   r-   E   s&    8A  r(   r-   c                   @    e Zd ZdZd Zd	dZd Zd Zd Ze	d        Z
y)
r6   zv
    Descriptor for translated attributes.

    This attribute proxies all get/set calls to the translated model.
    c                     || _         y)z.
        :type field: TranslatedField
        N)r   )r$   r   s     r   r3   z"TranslatedFieldDescriptor.__init__~   s     
r(   Nc                    |s| S d }| j                   j                  }	 |j                  d|      }t        || j                   j                        S # |j                  j                  $ rd}| j                   j
                  r|j                  |      }|0|j                  d    d| j                   j                   df|_         Y d }~d }~ww xY w)NT)use_fallbackr   r   r   z
Attempted to read attribute .)
r   r   _get_translated_modelr   DoesNotExistr1   _get_any_translated_modelargsr0   getattr)r$   instanceinstance_typetranslationr   es         r   __get__z!TranslatedFieldDescriptor.__get__   s    K zz	"88dQU8VK {DJJOO44 zz&& 		zz&&&@@ A  "VVAYK'EdjjooEVVWXZ #		s   A C*AC		Cc                     |,t        | j                  j                  j                   d      |j	                  dd| j                  j
                        }t        || j                  j                  |       y )Nz must be accessed via instanceFT)rA   auto_creater   )r   r   optsobject_namerD   r   r5   r0   )r$   rI   valuerK   s       r   __set__z!TranslatedFieldDescriptor.__set__   sf     DJJOO$?$?#@@^!_`` 44Dtzz 5 
 	TZZ__e4r(   c                     |j                  | j                  j                        }t        || j                  j                         y )NrB   )rD   r   r   delattrr0   )r$   rI   rK   s      r   
__delete__z$TranslatedFieldDescriptor.__delete__   s1     44$**//4JTZZ__-r(   c                     d| j                   j                   d| j                  j                  j                   d| j                  j                   dS )N<z for rC   >)r'   r   r   r   r0   r;   s    r   __repr__z"TranslatedFieldDescriptor.__repr__   sC    4>>**+51A1A1J1J0K1TZZ__L]]^__r(   c                     | j                   j                  j                  }|t        | j                   j                        S |j
                  j                  | j                   j                        }|j                  S )a$  
        Ensure that the admin ``list_display`` renders the correct verbose name for translated fields.

        The :func:`~django.contrib.admin.utils.label_for_field` function
        uses :func:`~django.db.models.Options.get_field_by_name` to find the find and ``verbose_name``.
        However, for translated fields, this option does not exist,
        hence it falls back to reading the attribute and trying ``short_description``.
        Ideally, translated fields should also appear in this list, to be treated like regular fields.
        )r   r   r   r   r0   r2   	get_fieldverbose_name)r$   translations_modelr   s      r   short_descriptionz+TranslatedFieldDescriptor.short_description   s]     "ZZ__22% tzz//"((224::??C!!!r(   r/   )r   r   r)   r*   r3   rM   rS   rV   rZ   r<   r_   r=   r(   r   r6   r6   w   s5    50	5.` " "r(   r6   c                   $    e Zd ZdZddZd Zd Zy)LanguageCodeDescriptorz\
    This is the property to access the ``language_code`` in the ``TranslatableModel``.
    Nc                 "    |s| S |j                   S r/   )_current_language)r$   rI   rJ   s      r   rM   zLanguageCodeDescriptor.__get__   s    K)))r(   c                     t        d      )NzhThe 'language_code' attribute cannot be changed directly! Use the set_current_language() method instead.r   )r$   rI   rR   s      r   rS   zLanguageCodeDescriptor.__set__   s    v
 	
r(   c                     t        d      )Nz0The 'language_code' attribute cannot be deleted!re   )r$   rI   s     r   rV   z!LanguageCodeDescriptor.__delete__   s    OPPr(   r/   )r   r   r)   r*   rM   rS   rV   r=   r(   r   ra   ra      s    *

Qr(   ra   N)r*   django.core.exceptionsr   	django.dbr   +django.db.models.fields.related_descriptorsr   django.forms.utilsr   r   
ForeignKeyr   r-   r6   ra   r=   r(   r   <module>rl      sT   
 8  R *!H4V.. 4/ /dM" M"`Q Qr(   