o
    /hZL                     @   s  d Z ddlZddlZddlZddlmZ ddlmZ ddlm	Z	m
Z
mZmZ ddlmZmZ ddl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ZdZdZg dZ ej!dej"dej#dej$dej%dej&dej'diZ(dd Z)G dd dZ*d"ddZ+dd Z,d d! Z-dS )#z
modelviz.py - DOT file generator for Django Models

Based on:
  Django model to DOT (Graphviz) converter
  by Antonio Cavedoni <antonio@cavedoni.org>
  Adapted to be used with django-extensions
    N)apps)deletion)
ForeignKeyManyToManyFieldOneToOneFieldRelatedField)OneToOneRelManyToOneRel)GenericRelation)ContextTemplateloader)	force_str)	mark_safe)activatez1.1Python)z'Bas van Oostveen <v.oostveen@gmail.com>)zQAntonio Cavedoni <https://cavedoni.com/>Stefano J. Attardi <https://attardi.org/>limodouzCarlo C8E Mironz Andre Campos <cahenan@gmail.com>z#Justin Findlay <jfindlay@gmail.com>z&Alexander Houben <alexander@houben.ch>z Joern Hees <gitdev@joernhees.de>z%Kevin Cherepski <cherepski@gmail.com>z&Jose Tomas Tocino <theom3ga@gmail.com>z#Adam Dobrawy <naczelnik@jawnosc.tk>z6Mikkel Munch Mortensen <https://www.detfalskested.dk/>z+Andrzej Bistram <andrzej.bistram@gmail.com>z%Daniel Lipsitt <danlipsitt@gmail.com>z%Florian Anceau <flow.gunso@gmail.com>redblueorangegreenyellowgreypurplec                 C   sZ   | sg S t | tttfr| S d| vr#tj| r#dd t|  D S dd | 	dD S )N,c                 S      g | ]}|  qS  strip.0er   r   `/var/www/html/env_mimamsha/lib/python3.10/site-packages/django_extensions/management/modelviz.py
<listcomp>H       z&parse_file_or_list.<locals>.<listcomp>c                 S   r   r   r   r   r   r   r"   r#   I   r$   )

isinstancelisttuplesetospathisfileopen	readlinessplit)argr   r   r"   parse_file_or_listB   s   r0   c                   @   s   e Zd Zdd Zdd Zd0ddZdd	 Zd1d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S )2
ModelGraphc                 K   s^  g | _ |dd | _|dd| _|dd| _t|dd| _|dd| _|dd| _|d	d| _	|d
d| _
|dd| _|dd| _|dd| _|dd | _| jd urct| j t|dd| _t|dd| _|dd| _|d| _|dd| _| jrdd t D | _n|| _|d| _|dd| _|d| _d S )Ncli_optionsdisable_fieldsFdisable_abstract_fieldsinclude_models all_applicationsgroup_modelsverbose_namesinheritanceTrelations_as_fieldsrelation_fields_onlysort_fieldslanguageexclude_columnsexclude_modelshide_edge_labelsarrow_shapecolor_code_deletionsc                 S   s   g | ]}|j qS r   )label)r    appr   r   r"   r#   c   s    z'ModelGraph.__init__.<locals>.<listcomp>rankdirdisplay_field_choicesordering)graphsgetr2   r3   r4   r0   r5   r7   use_subgraphr9   r:   r;   r<   r=   r>   activate_languager?   r@   rA   rB   rC   r   get_app_configs
app_labelsrF   rG   rH   )selfrN   kwargsr   r   r"   __init__M   s4   

zModelGraph.__init__c                 C   sx   |    g }| jD ]}|dd |d D  q	| jD ]}|d D ]}|d D ]}|d ur7|d |v r7d|d< q'q!qd S )Nc                 S   s   g | ]}|d  qS )namer   r   r   r   r"   r#   o   r$   z2ModelGraph.generate_graph_data.<locals>.<listcomp>models	relationstargetF
needs_node)process_appsrI   extend)rO   nodesgraphmodelrelationr   r   r"   generate_graph_dataj   s   

zModelGraph.generate_graph_dataFc              	   C   s   t j  }|d| j| j| j| j| j| j| j	d}|rGdd | j
D }|D ]}|d D ]}|d |d D ]}|d q7q,q&||d	< |S | j
|d	< |S )
Nz%Y-%m-%d %H:%M)
created_atr2   r3   r4   rG   rK   rF   rH   c                 S   r   r   )flatten)r    contextr   r   r"   r#      r$   z-ModelGraph.get_graph_data.<locals>.<listcomp>rS   r[   fieldsfieldrI   )datetimenowstrftimer2   r3   r4   rG   rK   rF   rH   rI   pop)rO   as_jsonrd   
graph_datarI   r`   
model_data
field_datar   r   r"   get_graph_datax   s.   


zModelGraph.get_graph_datac              	      s   | j r jrt j}| r| }n j}t j}t t	t
fr,|d jj7 }| jr@ jd ur@dd  jD }t|}  j|| jt fdd|D t t jdS )Nz ({0})c                 S   s   h | ]\}}|qS r   r   )r    c_r   r   r"   	<setcomp>   r$   z,ModelGraph.add_attributes.<locals>.<setcomp>c                 3   s    | ]	} j |j kV  qd S N)creation_counter)r    abstract_fieldrb   r   r"   	<genexpr>   s
    

z,ModelGraph.add_attributes.<locals>.<genexpr>)rb   rR   rD   typeblankabstractr\   primary_key)r9   verbose_namer   islower
capitalizerR   rt   __name__r%   r   r   formatremote_field
field_namerG   choicesstrru   anyr   rw   )rO   rb   abstract_fieldsrD   tr   r   rr   r"   add_attributes   s.   

zModelGraph.add_attributesr6   Nc                 C   s2  | j r|jrt|j}| r| }n|j}t|dr7| }| j r/| r/|dd }d	|t|}| j
r<d}t|jjtrn|jjdkrM|j}n%d|jjv r^|jjdd\}}	n	|jjj}|jj}	t||	}n|jj}|r~d		|dd
 |}| ||||}
|
|d vr| |
d r|
S d S d S )Nrelated_query_namerm    z{} ({})r6   rO   .   z[{}, color={}]rT   rU   )r9   rx   r   ry   rz   rR   hasattrr   replacer|   rA   r%   r}   r[   r   r.   _meta	app_labelr   	get_modelget_relation_context	use_model)rO   rb   r[   extrascolorrD   r   target_modelr   
model_name_relr   r   r"   add_relation   s8   


zModelGraph.add_relationc                 C   s2   g }|D ]}|dd |j D 7 }qtt|}|S )Nc                 S   s"   g | ]}t |d r|jjr|qS r   )r   r   rv   r    abstract_modelr   r   r"   r#      s    z2ModelGraph.get_abstract_models.<locals>.<listcomp>)	__bases__r&   r(   )rO   	appmodelsabstract_modelsappmodelr   r   r"   get_abstract_models   s   
zModelGraph.get_abstract_modelsc                 C   s,   t d|j d|j d|jdd g dS )Nz"%s"z%sz
cluster_%sr   rm   )rR   app_namecluster_app_namerS   )r   rR   r   )rO   rE   r   r   r"   get_app_context   s   zModelGraph.get_app_contextc                 C   s2   | j rdd |jjD }|S dd |jjD }|S )Nc                 S   s   g | ]}|qS r   r   r    rb   r   r   r"   r#      s    z6ModelGraph.get_appmodel_attributes.<locals>.<listcomp>c                 S   s   g | ]	}t |ts|qS r   )r%   r   r   r   r   r"   r#      s    )r;   r   local_fields)rO   r   
attributesr   r   r"   get_appmodel_attributes   s   	z"ModelGraph.get_appmodel_attributesc                 C   s   dd |j D S )Nc                 S   s$   g | ]}t |d r|jjr|jqS r   )r   r   rv   r{   r   r   r   r"   r#      s    z5ModelGraph.get_appmodel_abstracts.<locals>.<listcomp>)r   )rO   r   r   r   r"   get_appmodel_abstracts   s   z!ModelGraph.get_appmodel_abstractsc                 C   sP   ||j dd|j|g g d}| jr |jjr t|jj|d< |S |d |d< |S )Nr   rm   )r[   r   rR   	abstractsra   rT   rD   rR   )
__module__r   r{   r9   r   rx   r   )rO   r   appmodel_abstractsr`   r   r   r"   get_appmodel_context  s   	zModelGraph.get_appmodel_contextc                 C   sD   g }|j D ]}t|dr|jjr||jj || | q|S )Nr   )r   r   r   rv   rX   ra   get_bases_abstract_fields)rO   rl   _abstract_fieldsr!   r   r   r"   r     s   
z$ModelGraph.get_bases_abstract_fieldsc                 C   sN   d}|j jrd}|j jrd}|d7 }| jrd}|jdd|jdd|d	d
dS )Nzmulti-tablerv   proxyz\ninheritancer6   r   rm   r:   z+[arrowhead=empty, arrowtail=none, dir=both]T
target_apprU   rt   rR   rD   arrowsrV   )r   rv   r   rA   r   r   r{   )rO   r   parentrD   r   r   r"   get_inheritance_context  s    z"ModelGraph.get_inheritance_contextc                 C   s   t | }|S ro   )r&   
get_models)rO   rE   r   r   r   r"   r   .  s   zModelGraph.get_modelsc                 C   s(   |j dd|jt|j|j||ddS )Nr   rm   Tr   )r   r   r{   rt   rR   )rO   r   rb   rD   r   r   r   r"   r   2  s   zModelGraph.get_relation_contextc                 C   s<   |  }| |s|r||kr|S |d | || |S )Nra   )copy
skip_fieldappendr   )rO   rb   r[   pkr   newmodelr   r   r"   process_attributes=  s
   zModelGraph.process_attributesc              	   C   s^  | j D ]}t|}|sq| |}| |}| |}|| }|D ]}| |jjs,q"| 	|}| 
|}| ||}	| |}
|jj}|rZ|jjsZ||
v rZ|	d | || |
D ]
}| ||	||}	q\| jro| |	}	|jjD ]	}| ||	|}	qs|jjD ]}| ||	}	q| jr|jD ]	}| |||	}	q|d |	 q"|d r| j| qd S )Nra   rS   )rN   r   get_app_configr   r   r   r   r   object_namer   r   r   r   r   rv   r   r   r   r=   sort_model_fieldsr   process_local_fieldslocal_many_to_manyprocess_local_many_to_manyr:   r   process_parentrI   )rO   r   rE   	app_graph
app_modelsr   r   r   r   r[   r   r   rb   r   r   r   r"   rW   D  sD   









zModelGraph.process_appsc                 C   s   |  }|jds||v s| |r|S d }| jr-t|ttfr-t|j	dd }t
|}t|tr;| ||d|}nt|trM| ||d| j|}nd }|d urZ|d | |S )N_ptr_id	on_deletez*[arrowhead=none, arrowtail=none, dir=both]z([arrowhead=none, arrowtail={}, dir=both]rT   )r   attnameendswithr   rC   r%   r   r   getattrr}   ON_DELETE_COLORSrJ   r   r|   rB   r   )rO   rb   r[   r   r   r   field_on_deleter\   r   r   r"   r   q  s4   




zModelGraph.process_local_fieldsc                 C   s   |  }| |r|S d }t|tr-t|jjdr,|jjjjr,| 	||d
| j| j}nt|tr;| 	||td}|d urF|d | |S )Nr   z%[arrowhead={} arrowtail={}, dir=both]z>[style="dotted", arrowhead=normal, arrowtail=normal, dir=both]rT   )r   r   r%   r   r   r}   throughr   auto_createdr   r|   rB   r
   r   r   )rO   rb   r[   r   r\   r   r   r"   r     s8   



z%ModelGraph.process_local_many_to_manyc                 C   sJ   |  }t|dr#| ||}||d vr#| |d r#|d | |S )Nr   rT   rU   )r   r   r   r   r   )rO   r   r   r[   r   r   r   r   r"   r     s   
zModelGraph.process_parentc                 C   s$   |  }t|d dd d|d< |S )Nra   c                 S   s   | d  | d  | d fS )Nrw   r\   rD   r   rr   r   r   r"   <lambda>  s   z.ModelGraph.sort_model_fields.<locals>.<lambda>)key)r   sorted)rO   r[   r   r   r   r"   r     s   
zModelGraph.sort_model_fieldsc                 C   sp   | j r| j D ]}d|dd }t||r dS q| jr4| jD ]}d|dd }t||r3 dS q | j  S )z
        Decide whether to use a model, based on the model name and the lists of
        models to exclude and include.
        z^%s$*z.*TF)r5   r   researchr@   )rO   r   model_patternr   r   r"   r     s   

zModelGraph.use_modelc                 C   sV   | j r| jr|jr|j| j v rdS |j| j v rdS | jr)t|tttt	t
tfs)dS dS )NTF)r?   r9   rx   rR   r<   r%   r   r   r   r   r   r	   )rO   rb   r   r   r"   r     s&   zModelGraph.skip_field)F)r6   N)r{   r   __qualname__rQ   r]   rk   r   r   r   r   r   r   r   r   r   r   r   r   rW   r   r   r   r   r   r   r   r   r   r"   r1   L   s.    

'
-"
r1   *django_extensions/graph_models/digraph.dotc                 C   sV   t |tr
t|}t |tst|drt |jtstdt| 	 }|
|}|S )NtemplatezyDefault Django template loader isn't used. This can lead to the incorrect template rendering. Please, check the settings.)r%   r   r   get_templater   r   r   	Exceptionr   r_   render)rh   r   rl   dotr   r   r"   generate_dot  s   




r   c                  O   s   t | i |}|  | S ro   )r1   r]   rk   )argsrP   	generatorr   r   r"   r]     s   r]   c                 C   s   t g ||d}|| S )N)r5   r@   )r1   r   )r[   r5   r@   r   r   r   r"   r   
  s   
r   )r   ).__doc__rc   r)   r   django.appsr   django.db.modelsr   django.db.models.fields.relatedr   r   r   r   'django.db.models.fields.reverse_relatedr   r	   "django.contrib.contenttypes.fieldsr
   django.templater   r   r   django.utils.encodingr   django.utils.safestringr   django.utils.translationr   rL   __version____license__
__author____contributors__CASCADEPROTECTSET_NULLSET_DEFAULTSET
DO_NOTHINGRESTRICTr   r0   r1   r   r]   r   r   r   r   r"   <module>   sB   	
   
(