Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/doc/en/nat.xml
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/doc/en/nat.xml	(revision 39585)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/doc/en/nat.xml	(working copy)
@@ -60,6 +60,10 @@
                         </field>
                     </subfields>
                 </field>
+                <field name="priority" type="int">
+                    <verbose_name>DNS Priority</verbose_name>
+                    <help_text>range is [1, 512]</help_text>
+                </field>
                 <field name="description" type="string">
                     <verbose_name>Description</verbose_name>
                     <help_text/>
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/doc/ja/nat.xml
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/doc/ja/nat.xml	(revision 39585)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/doc/ja/nat.xml	(working copy)
@@ -60,6 +60,10 @@
                         </field>
                     </subfields>
                 </field>
+                <field name="priority" type="int">
+                    <verbose_name>DNS優先度</verbose_name>
+                    <help_text>範囲は [1～512] です。</help_text>
+                </field>
                 <field name="description" type="string">
                     <verbose_name>宛先</verbose_name>
                     <help_text/>
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/doc/zh-cn/nat.xml
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/doc/zh-cn/nat.xml	(revision 39585)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/doc/zh-cn/nat.xml	(working copy)
@@ -60,6 +60,10 @@
                         </field>
                     </subfields>
                 </field>
+                <field name="priority" type="int">
+                    <verbose_name>DNS优先级</verbose_name>
+                    <help_text>范围是 [1～512]。</help_text>
+                </field>
                 <field name="description" type="string">
                     <verbose_name>描述信息</verbose_name>
                     <help_text/>
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/doc/zh-tw/nat.xml
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/doc/zh-tw/nat.xml	(revision 39585)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/doc/zh-tw/nat.xml	(working copy)
@@ -60,6 +60,10 @@
                         </field>
                     </subfields>
                 </field>
+                <field name="priority" type="int">
+                    <verbose_name>DNS優先度</verbose_name>
+                    <help_text>範圍為 [1～512]。</help_text>
+                </field>
                 <field name="description" type="string">
                     <verbose_name>描述資訊</verbose_name>
                     <help_text/>
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/models/nat/nat/__init__.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/models/nat/nat/__init__.py	(revision 39585)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/models/nat/nat/__init__.py	(working copy)
@@ -20,9 +20,12 @@
     network_ip = IPAddressField(verbose_name=_('Network IP'))
     timeout = DurationField(verbose_name=_('Timeout'), optional=True, default=60, unit_name=__('Seconds'), editable=True)
     gateway = IPAddressField(verbose_name=_('Gateway IP'), optional=True, editable=True)
+    priority = Uint32Field(verbose_name=_('DNS Priority'), editable=True, default=0,
+            optional=True, help_text=_('range is [1, 512]'),
+            hide_list_condition='nat.nat.NATProtocolSettings._get_dns_method',
+            hidden_condition='nat.nat.NATProtocolSettings._get_dns_method')
     description = CharField(verbose_name=_('Description'),length='0..31', optional=True, editable=True)
     nat_tgt = AssoField2(verbose_name='Static NAT setting', optional=True, tgt='nat.nat.StaticNATSettings.static_nat_entry', mul='*', pos='right', hidden=True)
-    
     stats = FieldGroup(writable=False, verbose_name=_('Global Nat Statistics'), level=STATS,
             fields={
             'outbound_icmp_total_connection':StorableField(verbose_name=_('outbound icmp total connection'), fields=Uint64Field()),
@@ -49,24 +52,27 @@
 
     class Meta:
         verbose_name = _('Static NAT Entry')
-    
+
     class Manager(CLIManager):
         def _get_query_set(self):
             self.cli.set_enable()
             parser = RegexParser('nat static (?P<vip_str>[0-9|\.|:|\w+]+) (?P<network_ip_str>[0-9|\.|:|\w]+)'
                                  ' (?P<timeout>[0-9]+) (?P<gateway_str>[0-9|\.|:|\w]+) "(?P<description>.*?)"', MATCHALL, reflags=re.S)
             result = self.cli.cmd('show nat static', parser)
+            priority_mapping = self._get_priority_mapping()
             for each_result in result:
+                if each_result['vip_str'] in priority_mapping:
+                    each_result['priority'] = priority_mapping[each_result['vip_str']]
                 if is_ipv4(each_result['vip_str']):
                     each_result['vip'] = {'ipv4':each_result['vip_str']}
                 elif is_ipv6(each_result['vip_str']):
                     each_result['vip'] = {'ipv6':each_result['vip_str']}
-                
+
                 if is_ipv4(each_result['network_ip_str']):
                     each_result['network_ip'] = {'ipv4':each_result['network_ip_str']}
                 elif is_ipv6(each_result['network_ip_str']):
                     each_result['network_ip'] = {'ipv6':each_result['network_ip_str']}
-                    
+
                 if is_ipv4(each_result['gateway_str']):
                     each_result['gateway'] = {'ipv4':each_result['gateway_str']}
                 elif is_ipv6(each_result['gateway_str']):
@@ -77,7 +83,7 @@
                 each_result['nat_tgt'] = [{'_asso_idx':0}]
             data = QuerySet(self._model, result)
             return data
-    
+
         def _get_stats(self):
             self._get_query_set()
 
@@ -93,6 +99,16 @@
                                   RegexParser('Warning,', MATCHONE, match_exception=CLICmdNormal, exclusive=True),
                                   RegexParser('updated', MATCHONE, match_exception=CLICmdNormal, exclusive=True),
                                   BlankParser(nonblank_exception=CLICmdError, supplement=True))
+            if "priority" in data and data['priority'] > 0:
+                self._update_priority(instance)
+            return result
+
+        def _update_priority(self, instance):
+            data = instance.get_field_dict(group="default")
+            data['vip_str'] = data['vip'].values()[0]
+            self.cli.set_config()
+            result = self.cli.cmd('nat dnspri %s %s' % (data['vip_str'], data['priority']),
+                                  BlankParser(nonblank_exception=CLICmdError, supplement=True))
             return result
 
         def _delete(self, pk_list):
@@ -102,6 +118,15 @@
                                 BlankParser(nonblank_exception=CLICmdError, supplement=True))
             return
 
+        def _get_priority_mapping(self):
+            self.cli.set_enable()
+            parser = RegexParser('nat dnspri (?P<vip_str>[0-9|\.|:|\w+]+) (?P<priority>[0-9]+)', MATCHALL, reflags=re.S)
+            result = self.cli.cmd('show running nat', parser)
+            mapping = {}
+            for each in result:
+                mapping[str(each['vip_str'])] = int(each['priority'])
+            return mapping
+
 class StaticNATSettings(ANModel):
     pure_ip = BooleanField(verbose_name='Enabled Pure IP')
     static_nat_entry = AssoField2(verbose_name='Static NAT Entry', tgt='nat.nat.StaticNATEntry.nat_tgt', mul='1', pos='left', optional=True)
@@ -685,6 +710,7 @@
                 'method': EnumField(verbose_name=_('DNS NAT Method'),default='proximity', condition=ValueCondition('enable', [True]),values=(
                                     ('rr', 'Round Robin'),
                                     ('proximity', 'Proximity'),
+                                    ('priority', 'Priority'),
                                     ))
         })
 
@@ -701,7 +727,7 @@
             'inbound_out_bytes':StorableField(verbose_name=_('inbound Total Out bytes'), fields=Uint64Field()),
             'inbound_in_bytes':StorableField(verbose_name=_('inbound Total in bytes'), fields=Uint64Field()),
             })
-    
+
     class Meta:
         profile = True
         verbose_name = 'NAT Protocol Settings'
@@ -735,8 +761,8 @@
         @QueryingFields(['enable', 'method'])
         def _get_enable_method(self):
             self.cli.set_enable()
-            parser = RegexParser('nat protocol dns (?P<method>rr|proximity)', MATCHONE, reflags=re.M)
-            
+            parser = RegexParser('nat protocol dns (?P<method>rr|proximity|priority)', MATCHONE, reflags=re.M)
+
             result = self.cli.cmd('show nat protocol dns', parser)
             if result:
                 result = {
@@ -791,4 +817,8 @@
                     result = self.cli.cmd('nat protocol ftp port %d' % port,
                                   BlankParser(nonblank_exception=CLICmdError, supplement=True))
 
-
+        def _get_dns_method(self):
+            data = self._get_enable_method()
+            if not data or "method" not in data or data["method"] != 'priority':
+                return True
+            return False
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/hive/model/fields/__init__.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/hive/model/fields/__init__.py	(revision 39585)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/hive/model/fields/__init__.py	(working copy)
@@ -25,7 +25,8 @@
 from hive.model.utils import CONDITIONAL_NONE
 from hive.exceptions import FieldDoesNotExist
 from hive.document import get_xml_reference, DOCUMENT_OK, DOCUMENT_NEW, DOCUMENT_PENDING
-
+from hive.model.loading import get_model
+from hive.session import current_app
 
 class NOT_PROVIDED:
     """ A placeholder for non-provided arguments
@@ -70,16 +71,19 @@
 
     :param editable: Whether this field is editable.(Value of the field is editable after it's belonging model object was already created in the system) 
     :type  editable: bool
-    
+
     :param configurable: Whether this field is configurable. A non-configurable field will be hidden in the object creation page. The value is always read-only which is got from backend.
     :type configurable: bool
-    
+
     :param hidden: Whether this field is hidden from user. Unlike "configurable", once a field is hidden, it is hidden at both creation page and edit page.
     :type hidden: bool
 
+    :param hidden_condition: Whether this field is hidden by function return. Unlike "configurable", once a field is hidden, it is hidden at both creation page and edit page.
+    :type hidden_condition: str
+
     :param seg_hidden: Whether this field is hidden from segment user. Unlike "configurable", once a field is hidden, it is hidden at both creation page and edit page.
     :type seg_hidden: bool
-    
+
     :param hide_edit: Whether this field is hidden in edit form
     :type hide_edit: bool
 
@@ -89,6 +93,9 @@
     :param hide_list: Whether this field is hidden in list, this only take effect when field in basic group.
     :type hide_list: bool
 
+    :param hide_list_condition: Whether this field is hidden in list by function return, this only take effect when field in basic group.
+    :type hide_list_condition: str
+
     :param help_text: The help_text value of the field.
     :type  help_text: str
 
@@ -109,7 +116,7 @@
     type_name = 'base'
     type_default = NOT_PROVIDED
     type_arguments = {}
-    
+
     # These track each time a Field instance is created. Used to retain order.
     creation_counter = 0
     default_validators = [] # Default set of validators
@@ -131,7 +138,7 @@
 
     def __init__(self, verbose_name=None, name=None, primary_key=False,
             indexed=None, unique=None, optional=False,
-            default=NOT_PROVIDED, editable=NOT_PROVIDED, configurable=True, check_chinese=True, hidden=False, hide_edit=False, hide_in_popup_edit=False,hide_list=False, help_text='',
+            default=NOT_PROVIDED, editable=NOT_PROVIDED, configurable=True, check_chinese=True, hidden=False, hidden_condition=None, hide_edit=False, hide_in_popup_edit=False,hide_list=False,hide_list_condition='', help_text='',
             validators=[], error_messages=None, condition=None, basic_info=False, object_switch=False, cache_expire_time=0, visible_edit=None, custom_display=NOT_PROVIDED, statistics_source="kernel", seg_hidden=False, seg_lock=False, use_default=True):
         self.name = name
         self._verbose_name = verbose_name
@@ -144,9 +151,11 @@
         self.configurable = configurable
         self.check_chinese = check_chinese
         self.hidden = hidden
+        self.hidden_condition = hidden_condition
         self.hide_edit = hide_edit
         self.hide_in_popup_edit = hide_in_popup_edit
         self.hide_list = hide_list
+        self.hide_list_condition = hide_list_condition
         self._help_text = help_text
         self.group = None
         self.model = None # keeps None for nested fields
@@ -250,7 +259,7 @@
         sub classes.
         """
         pass
-        
+
     def clean(self, value, model_instance):
         """
         Convert the value's type and run validation. Validation errors
@@ -270,7 +279,7 @@
     @property
     def unique(self):
         return self._unique or self.primary_key
-    
+
     def _set_attributes_from_name(self, name):
         if not self.name:
             self.name = name
@@ -287,7 +296,7 @@
             self.default_override()
         else:
             self.model = cls
-        
+
         self._set_attributes_from_name(name)
         cls._meta.add_field(self, self.group)
         if self.editable is NOT_PROVIDED:
@@ -296,7 +305,7 @@
             else:
                 self.editable = True
         # if specially provided at definition, should keep the value
-        
+
         """
         if self.choices:
             setattr(cls, 'get_%s_display' % self.name,
@@ -328,7 +337,7 @@
             if self._actions[0].document is not None:
                 xpath = "./field[@name='"+self.name+"']"
                 return self._actions[0].document.find(xpath)
-        
+
         return None
 
     @property
@@ -359,7 +368,7 @@
     @verbose_name.setter
     def verbose_name(self, new_value):
         self._verbose_name = new_value
-    
+
     @property
     def help_text(self): # XXX consider using self.document here? pros and cons?
         if self.is_inherited():
@@ -405,7 +414,7 @@
 
     def get_sub_fields(self):
         return None
-        
+
     def get_attname(self):
         return self.name
 
@@ -518,12 +527,12 @@
         just a shortcut
         """
         return self.value_to_display(obj=obj, style=True, text=False)
-        
+
     def value_split(self, value):
         # used for GroupField, return [[sub_field1,val1],[sub_field2,val2]]
         # for other field, return [[field_name,value]]
         return [[unicode(self.verbose_name), self.value_to_lexical(val=value)]]
-    
+
     def value_to_num(self, obj=None, val=None):
         value = self._get_val_from_obj_or_val(obj, val)
         if type(value) == float:
@@ -551,7 +560,7 @@
         self._optional = value
 
     optional = property(get_optional, set_optional)
-        
+
     @property
     def required(self):
         # if this field is not optional and there's no default value provided, it is required;
@@ -562,7 +571,7 @@
 
     def static_widget(self, model_instance=None, manager=None, context_value=None, context_repr=None):
         return StaticFormWidget(name=self.name, label=self.verbose_name, help_text=self.help_text, context_value=context_value, context_repr=context_repr)
-        
+
     def default_widget(self, model_instance=None, manager=None, **kwargs):
         # The default default widget is a simple TextInput widget that ignores all other keyword parameters
         return TextInput(name=self.name, label=self.verbose_name, help_text=self.help_text, validators=self.validators, required=self.required)
@@ -570,23 +579,23 @@
     def status_widget(self, model_instance=None, manager=None, **kwargs):
         # The default stat widget is a simple Stat widget that ignores all other keyword parameters
         return Stat(name=self.name, label=self.verbose_name, help_text=self.help_text, **kwargs)
-    
+
     def statistics_widget(self, model_instance=None, manager=None, **kwargs):
         # The default stat widget is a simple Stat widget that ignores all other keyword parameters
         return Stat(name=self.name, label=self.verbose_name, help_text=self.help_text, **kwargs)
-                         
+
     def value_from_object(self, obj):
         """
         Returns the value of this field in the given model instance.
         """
         return getattr(obj, self.attname)
-    
+
     def register_related_action(self, action_cls):
         self._actions.append(action_cls)
-        
+
     def has_related_action(self):
         return self.related_actions() != []
-    
+
     def related_actions(self, instance=None):
         tmp_acts = []
         for each_act in self._actions:
@@ -615,11 +624,11 @@
 
     def set_group(self, group):
         self.group = group
-        
+
     def get_pseudo_value(self):
         # should be implemented by sub classes
         raise ValueError('The function is not implemented by this field type')
-    
+
     @property
     def is_scalar_stats(self):
         return self.group.isstats and not self.basic_info and not self.object_switch
@@ -632,15 +641,15 @@
             return self.root_model._meta.get_field(self.name)
         else:
             return None
-    
+
     # Some field type (e.g. AssoField) have some default
     # overriding behavior even if there's no OverrideField defined
     def default_override(self):
         # to be implemented by various field types
         pass
-        
+
     # This function is called by OverrideField
-    def override(self, default=None, optional=None, editable=None, configurable=None, hidden=None, **kwargs):
+    def override(self, default=None, optional=None, editable=None, configurable=None, hidden=None, hidden_condition=None, **kwargs):
         if default is not None:
             self.default=default
         if optional is not None:
@@ -651,24 +660,26 @@
             self.configurable = configurable
         if hidden is not None:
             self.hidden = hidden
-    
+        if hidden_condition is not None:
+            self.hidden_condition = hidden_condition
+
     def is_external_component(self):
         if self.type_name != 'asso':
             return False
-        
+
         if len(self.asso) != 1:
             return False
-            
+
         if self.asso[0] and hasattr(self.asso[0], 'is_one_on_one') and self.asso[0].is_one_on_one():
             target_pk = self.target_end[0].model._meta.pk_set
             if len(target_pk) == 1 and self.target_end[0].field in target_pk:
                 return True
         return False
-    
+
     def is_external_component_target(self):
         if self.type_name != 'asso':
             return False
-            
+
         # As an external component target, the asso count
         # doesn't have to be 1. e.g. HTTPSettings
         # We simply check the first asso's target field as
@@ -677,14 +688,14 @@
             if self.tgt_field[0]:
                 return self.tgt_field[0].is_external_component()
         return False
-    
+
     def get_external_component_obj(self, instance):
         assert self.is_external_component()
         target_manager = self.target_end[0].model.get_manager(get_current_session())
         target_pk = self.value_from_object(instance)[0]
         return target_manager.get(target_pk)
-        
-        
+
+
     def is_composition_asso(self):
         if self.type_name != 'asso':
             return False
@@ -697,26 +708,28 @@
                 return False
             asso_idx += 1
         return True
-    
+
     def is_composition_asso_target(self):
         if self.type_name != 'asso':
             return False
-        
+
         if hasattr(self, 'tgt_field'):
             for each_tgt_field in self.tgt_field:
                 if each_tgt_field and not each_tgt_field.is_composition_asso():
                     return False
             return True # all tgt fields are composition asso
         return False
-    
+
     # the condition / asso_condition in add form is implemented at the front-end
     def visible_in_add(self):
         if self.group.isstats:
             return False
         if self.hidden or not self.configurable or self.is_composition_asso():
             return False
+        if self.hidden_condition is not None:
+            return self.hide_field_condition_check(self.hidden_condition)
         return True
-    
+
     # the condition / asso_condition in edit form is implemented at the Group's visible_in_edit
     def visible_in_edit(self):
         if self.visible_edit is not None:
@@ -725,8 +738,29 @@
             return False
         if self.hidden or self.hide_edit or self.is_external_component_target():
             return False
+        if self.hidden_condition is not None:
+            return self.hide_field_condition_check(self.hidden_condition)
         return True
-    
+
+    def hide_field_condition_check(self, cond):
+        if cond is None:
+            return True
+        if isinstance(cond, str):
+            session = get_current_session()
+            if session is None:
+                return True
+            model_path, func_name = cond.rsplit('.', 1)
+            model_path_list = model_path.split('.')
+            model = get_model(current_app(), model_path_list)
+            manager = model.get_manager(session)
+            if model is None:
+                return True
+            func = getattr(manager, func_name)
+            if func is None:
+                return True
+            return not func()
+        return True
+
     @property
     def path(self):
         if self.model:
@@ -749,7 +783,7 @@
         # 1. Check group condition
         if self.group and self.group.condition and not self.group.condition.check(instance):
             return False
-            
+
         # 2. Check field conditions
         field_condition_pass = True
         if self.condition and not self.condition.check(instance):
@@ -816,7 +850,7 @@
     # These track each time a Field Group instance is created. Used to retain order.
     creation_counter = 1
     # 0 is left for the auto-created default group
-    
+
     def __init__(self, name=None, verbose_name=None, help_text=None, writable=True, level=BASIC, fields=None, condition=None, editable=NOT_PROVIDED, optional=False, override=False, subjoin=False, visible_edit=None, stats_source='kernel', seg_hidden=False):
         self.name = name
         self._verbose_name = verbose_name
@@ -830,7 +864,7 @@
         self._optional = optional
         self.override = override
         self.subjoin = subjoin
-        self.stats_source = stats_source        
+        self.stats_source = stats_source
         # Adjust the appropriate creation counter, and save our local copy.
         if self.name == 'default':
             self.creation_counter = 0
@@ -843,21 +877,21 @@
 
     def __cmp__(self, other):
         return cmp(self.creation_counter, other.creation_counter)
-            
+
     @property
     def fields(self):
         return self._fields
-    
+
     def get_optional(self):
         if self.level is STATS:
             return True
         return self._optional
-    
+
     def set_optional(self, value):
         self._optional = value
-    
+
     optional = property(get_optional, set_optional)
-        
+
     def _set_attributes_from_name(self, name):
         if not self.name:
             self.name = name
@@ -875,7 +909,7 @@
             if old_group:
                 for each in old_group._fields:
                     cls._meta.del_field(each)
-        
+
         self._fields = [] # reset the list here in case its copied from parent cls
         if self.subjoin:
             # add all fields belong to this group in parent class into _fields
@@ -901,7 +935,7 @@
     @verbose_name.setter
     def verbose_name(self, new_value):
         self._verbose_name = new_value
-    
+
     #@cached_property
     @property
     def help_text(self):
@@ -926,7 +960,7 @@
                 return DOCUMENT_OK # this field already exist in current document
         else:
             return DOCUMENT_NEW
-            
+
     def append_field(self, field):
         # append a field to the group after bound to class
         # e.g. add field to the default group
@@ -937,7 +971,7 @@
     def del_field(self, field):
         del self._field_dict[field.name]
         self._fields.remove(field)
-        
+
     def __deepcopy__(self, memodict):
         new = copy.copy(self)
         new._field_dict = copy.deepcopy(self._field_dict, memodict)
@@ -963,7 +997,7 @@
                 if field.get_internal_type() == "AssoField2":
                     return True
         return False
-    
+
     @property
     def has_storeable_statistics(self):
         if self.isstats and self.fields:
@@ -977,10 +1011,10 @@
             if each_field.is_scalar_stats:
                 return True
         return False
-    
+
     def visible_in_edit(self, instance=None):
         if self.visible_edit is not None:
-            if self.visible_edit:                
+            if self.visible_edit:
                 # check condition
                 if instance and self.condition:
                     if self.condition.check(instance) is False:
@@ -990,17 +1024,17 @@
                 return False
         if self.isstats:
             return False
-            
+
         # first check the value condition and asso value conditions
         if instance and self.condition:
             andebug('hive.debug', 'instance %s, self.condition %s, self.condition.check(instance) %s' % (str(instance), str(self.condition), str(self.condition.check(instance))))
             if self.condition.check(instance) is False:
                 return False
-        
+
         for field in self.fields:
             if field.visible_in_edit():
                 return True
-        
+
         return False
 
     # whether this group only contains hidden fields
@@ -1011,7 +1045,7 @@
             if not field.hidden:
                 return False
         return True
-    
+
     def is_special_fieldgrp(self):
         if len(self.fields) == 1 and self.fields[0].type_name == 'clitext':
             return True
@@ -1020,7 +1054,7 @@
 
     def register_related_action(self, action_cls):
         self._actions.append(action_cls)
-    
+
     def related_actions(self, instance=None):
         tmp_acts = []
         for each_act in self._actions:
@@ -1035,7 +1069,7 @@
     def __init__(self, fieldname, data):
         self._fieldname = fieldname
         self._data = data
-    
+
     def to_dict(self):
         return {'field':self._fieldname, 'value':self._data}
 
@@ -1058,10 +1092,10 @@
         Check whether the condition matches. Should be overwritten by subclasses.
         """
         return True
-    
+
     def __and__(self, other):
         return AndCondition(self, other)
-    
+
     def __or__(self, other):
         return OrCondition(self, other)
 
@@ -1082,7 +1116,7 @@
         if realvalue in self._fieldvalue:
             return True
         return False
-    
+
     def to_dict(self):
         return {'field':self._fieldname, 'value':self._fieldvalue}
 
@@ -1128,7 +1162,7 @@
         if realvalue in self._fieldvalue:
             return False
         return True
-    
+
     def to_dict(self):
         return {'field':self._fieldname, 'value':self._fieldvalue, 'except':True}
 
@@ -1145,7 +1179,7 @@
         if realvalue:
             return True
         return False
-    
+
     def to_dict(self):
         return {'field':self._fieldname, 'nonempty':True}
 
@@ -1162,7 +1196,7 @@
         if realvalue:
             return False
         return True
-    
+
     def to_dict(self):
         return {'field':self._fieldname, 'nonempty':False}
 
@@ -1189,7 +1223,7 @@
         except IndexError:
             return False
         return getattr(target_obj, self._fieldname, None) in self._fieldvalue
-    
+
     def to_dict(self):
         return {'asso_field':self._asso_fieldname, 'field':self._fieldname, 'value':self._fieldvalue}
 
@@ -1197,14 +1231,14 @@
     def __init__(self, *args):
         super(AndCondition, self).__init__()
         self._sub_conditions = list(args)
-    
+
     def check(self, obj):
         for each in self._sub_conditions:
             andebug('hive.debug', 'checking sub condition: %s' % str(each.to_dict()))
             if not each.check(obj):
                 return False
         return True
-    
+
     def to_dict(self):
         # XXX simply return the first sub condition's dict here
         # we will consider an enhancement together with the frontend
@@ -1212,19 +1246,19 @@
         for each in self._sub_conditions:
             rst.append(each.to_dict())
         return {'multi':True,'conditions':rst,'rel':'and'}
-    
+
 class OrCondition(Condition):
     def __init__(self, *args):
         super(OrCondition, self).__init__()
         self._sub_conditions = list(args)
-    
+
     def check(self, obj):
         for each in self._sub_conditions:
             andebug('hive.debug', 'checking sub condition: %s' % str(each.to_dict()))
             if each.check(obj):
                 return True
         return False
-        
+
     def to_dict(self):
         # XXX simply return the first sub condition's dict here
         # we will consider an enhancement together with the frontend
@@ -1232,7 +1266,7 @@
         for each in self._sub_conditions:
             rst.append(each.to_dict())
         return {'multi':True,'conditions':rst,'rel':'or'}
-    
+
 def get_parent_field_types(field_class):
     """
     returns a list of field classes from which the class
@@ -1269,7 +1303,7 @@
             copied_parent_field.default = self._value
             if not self.editable:
                 copied_parent_field.validators.append(validators.SingleValueValidator(self._value))
-        
+
         copied_parent_field.derived = True
 
         # Establish "children" data structure of ancestor model classes
@@ -1283,31 +1317,31 @@
 class OverrideField(object):
     def __init__(self, **kwargs):
         self.kwargs = dict(kwargs)
-        
+
     def contribute_to_class(self, cls, name):
         # find the field from the fields
         # that have already been loaded
         # from parent model
         copied_parent_field = None
-        
+
         try:
             copied_parent_field = cls._meta.get_field(name)
         except FieldDoesNotExist:
             raise ValueError('OverrideField %s must has the same name as the parent\'s field' % name)
-            
+
         # call the field's override() function
         copied_parent_field.override(**self.kwargs)
 
 class ReplaceField(object):
     def __init__(self, field, **kwargs):
         self.field = field(**kwargs)
-        
+
     def contribute_to_class(self, cls, name):
         # find the field from the fields
         # that have already been loaded
         # from parent model
         copied_parent_field = None
-        
+
         try:
             copied_parent_field = cls._meta.get_field(name)
         except FieldDoesNotExist:
@@ -1316,7 +1350,3 @@
         cls._meta.real_del_field(copied_parent_field)
         self.field.creation_counter = copied_parent_field.creation_counter
         self.field.contribute_to_class(cls, name)
-
-        
-        
-        
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/hive/model/options.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/hive/model/options.py	(revision 39585)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/hive/model/options.py	(working copy)
@@ -103,7 +103,7 @@
         #                              if the 'name' is not a field_name for current class, 'title' must set
         #                'width':  any CSS value (3em, 20px etc) 
         #                'className': adds a class to each cell in a column
-        #                'defaultContent': if no data is set for this column, the default content will display       
+        #                'defaultContent': if no data is set for this column, the default content will display
         #              },
         #              ...
         #    ], default get all fields in basic fieldGroup.
@@ -135,7 +135,7 @@
         #                              if the 'name' is not a field_name for current class, 'title' must set
         #                'width':  any CSS value (3em, 20px etc) 
         #                'className': adds a class to each cell in a column
-        #                'defaultContent': if no data is set for this column, the default content will display       
+        #                'defaultContent': if no data is set for this column, the default content will display
         #              },
         #              ...
         #    ], default get all fields in stats fieldGroup.
@@ -147,7 +147,7 @@
         self.abstract_parents = SortedDict()
         self.children = SortedDict()
         self.conditional_deriving_fields = []
-        
+
         self.duplicate_targets = {}
         self.auto_created = False
         self.quantity = '0..65535'
@@ -167,7 +167,7 @@
         self.repr_by_pk = None
         self._actions = []
         self.object_switch_field = None
-        
+
         #self.document = get_model_element(self.app_label, self.path)
         self._package = None
         self._default_node = None
@@ -287,7 +287,7 @@
         if self.object_name == 'HTTPVirtualService':
             for each_name, each_value in self.field_groups.iteritems():
                 andebug('hive.debug', 'field group now includes: %s %d' % (each_name, each_value.creation_counter))
-    
+
     def get_field_group(self, group_name):
         # get FieldGroup from the model class, if not found, return None
         if group_name in  self.field_groups:
@@ -307,33 +307,33 @@
                 # the creation counter of 'default' field group is set to 0
                 # the default group won't call the contribute_to_class method, so we should set the class reference manually here
                 default_grp.model = self._model
-                            
+
             self.field_groups['default'].append_field(field)
-            
+
         # Insert the given field in the order in which it was created, using
         # the "creation_counter" attribute of the field.
         self.local_fields.insert(bisect(self.local_fields, field), field)
         self._setup_index(field)
         if field.object_switch:
             self.object_switch_field = field
-            
+
         if hasattr(self, '_field_cache'):
             del self._field_cache
             del self._field_name_cache
 
         if hasattr(self, '_name_map'):
             del self._name_map
-            
+
     def del_field(self, field):
         """ Delete a ``Field`` object to the model class.
         !!! Only delete in local_fields, do NOT delete in field_group
         """
         self._remove_index(field)
         self.local_fields.remove(field)
-        
+
         if field.object_switch:
             self.object_switch_field = None
-            
+
         if hasattr(self, '_field_cache'):
             del self._field_cache
             del self._field_name_cache
@@ -344,14 +344,14 @@
     def real_del_field(self, field):
         """ Delete a ``Field`` object to the model class and in the field_group.
         """
-        
+
         self._remove_index(field)
         self.local_fields.remove(field)
         field.group.del_field(field)
 
         if field.object_switch:
             self.object_switch_field = None
-            
+
         if hasattr(self, '_field_cache'):
             del self._field_cache
             del self._field_name_cache
@@ -416,11 +416,11 @@
             top_pkg = self.path[0]
             return get_xml_reference(top_pkg, self.document.find('./verbose_name'), default=self._verbose_name)
         return self._verbose_name
-    
+
     @verbose_name.setter
     def verbose_name(self, new_value):
         self._verbose_name = new_value
-    
+
     @property
     def help_text(self):
         " The help text of the model "
@@ -428,7 +428,7 @@
             top_pkg = self.path[0]
             return get_xml_reference(top_pkg, self.document.find('./help_text'), default=self._help_text)
         return self._help_text
-    
+
     @help_text.setter
     def help_text(self, new_value):
         self._help_text = new_value
@@ -439,7 +439,7 @@
         if self.document is not None:
             return self.document.findtext('./help_link', default='')
         return ''
-    
+
     def get_help_link(self):
         if self.help_link:
             return get_current_lang() + '/' + self.help_link
@@ -447,10 +447,10 @@
             return self._package.get_help_link()
         else:
             return ''
-        
+
     def set_package(self, package):
         self._package = package
-        
+
     @property
     def document_status(self):
         if self.document is not None:
@@ -459,7 +459,7 @@
             return status_str2obj(status_str) # this model already exist in current document
         else:
             return DOCUMENT_NEW
-    
+
     def reload_document(self):
         clear_per_sess_property_cache(self)
         # clear all field grps' and fields' property cache
@@ -473,7 +473,7 @@
 
         for each_field in self.fields:
             reload_per_field(each_field)
-                    
+
     def _fields(self):
         """
         Returns the list of field objects
@@ -488,7 +488,7 @@
             self._fill_fields_cache()
         return self._field_name_cache
     fields = property(_fields)
- 
+
     def get_fields_with_model(self):
         """
         Returns a sequence of (field, model) pairs for all fields. The "model"
@@ -569,7 +569,7 @@
                 continue
             rtn_list.append(each_field)
         return rtn_list
-        
+
     def _init_name_map(self):
         """
         Initialises the field name -> field object mapping.
@@ -649,14 +649,14 @@
         assert association
         assert field
         self._associations[association] = field
-    
+
     # obsoleted !!! for old Associations only
-    def add_association_obsolete(self, association, end, target_end):    
+    def add_association_obsolete(self, association, end, target_end):
         """ Add an association to the model class,
             This should be called after the model is already loaded
         """
         self._associations[association] = None
-        
+
         # Register the association to the corresponding asso field
         for each in self.fields:
             # Importing the builtin.py will cause round importing.
@@ -674,7 +674,7 @@
     @property
     def associations(self):
         return self._associations
-        
+
     @property
     def parents(self):
         """ Returns a ``SortedDict`` of parents of the field class
@@ -682,16 +682,16 @@
         Here 'parents' means class inheritence tree rather than model package tree
         """
         return self.abstract_parents
-        
+
     def register_deriving_field(self, field_name, condition_value, sub_class):
         if field_name not in self.conditional_deriving_fields:
             self.conditional_deriving_fields.append(field_name)
-            
+
         if sub_class in self.children:
             self.children[sub_class][field_name] = condition_value
         else:
             self.children[sub_class] = SortedDict({field_name:condition_value})
-    
+
     def get_all_concrete_children(self):
         final_rtn_list = []
         def _all_direct_children(model_meta, rtn_list):
@@ -700,7 +700,6 @@
                 _all_direct_children(each._meta, rtn_list)
         _all_direct_children(self, final_rtn_list)
         return final_rtn_list
-        
 
     def get_child_by_field_cond(self, field_cond_dict):
         """ Get child class by a dict of field conditions
@@ -727,7 +726,7 @@
             if current_matching_field_count > max_matching_field_count:
                 max_matching_field_count = current_matching_field_count
                 matching_sub_class = sub_class
-                
+
         # Search is over for current level, enter next level
         if matching_sub_class is None:
             raise KeyError('No sub class matching these field conditions')
@@ -735,7 +734,7 @@
             return matching_sub_class._meta.get_child_by_field_cond(field_cond_dict)
         else:
             return matching_sub_class
-    
+
     def _find_deriving_fields(self, children_data, field_dict):
         for sub_class in children_data:
             for field_name in children_data[sub_class]:
@@ -759,7 +758,7 @@
         else:
             param_str = ''
         return '/api/' + self.app_label + '/' + '/'.join(self.path) + '/_' + action + param_str
-        
+
     def append_action_cls(self, name, action_cls):
         # register actions to related fields
         #if action_cls.related:
@@ -768,17 +767,17 @@
             field.register_related_action(action_cls)
             field.init_sub_fields()
         self._actions.insert(bisect(self._actions, action_cls), action_cls)
-        
+
     @property
     def actions(self):
         return self._actions
-        
+
     def get_action_by_name(self, name):
         for each in self.actions:
             if each.name == name:
                 return each
         return None
-    
+
     @property
     def explicit_actions(self):
         tmp_acts = []
@@ -789,7 +788,7 @@
             if each_act.model_action and each_act.condition():
                 tmp_acts.append(each_act)
         return tmp_acts
-    
+
     def gen_dataset_for_update(self, existing_queryset, count=100):
         # for now, ignore existing_queryset
         it = nd_iter_space(len(self.fields))
@@ -813,7 +812,7 @@
                 dataset_list.append(dataset)
                 i += 1
         return dataset_list
-    
+
     def gen_test_dataset_for_fieldset(self, fieldset, count=100, pk_dict_list=None, fixed_assos={}):
         it = nd_iter_coordinate(len(fieldset))
         dataset_list = []
@@ -823,7 +822,7 @@
         while i < count:
             bias_list = it.next()
             dataset = {}
-            
+
             field_validation_error = 0
             for j in range(len(fieldset)):
                 #print self.verbose_name + "in gen_basic_dataset j - " + str(j) + "-" + self.fields[j].name
@@ -842,11 +841,11 @@
                         dataset[fieldset[j].name] = fieldset[j].clean(dataset[fieldset[j].name], None)
                     except exceptions.ValidationError:
                         field_validation_error += 1
-            
+
             # if there is validation error, skip this case
             if field_validation_error > 0:
                 continue
-                
+
             # Check whether dataset is repeated
             if dataset in dataset_list:
                 repeated += 1
@@ -858,22 +857,22 @@
                 repeated = 0
                 dataset_list.append(dataset)
                 i += 1
-                
+
             #print dataset_list
         return dataset_list
-        
+
     def gen_test_dataset(self, existing_data=None, fixed_pk=None, count=100):
         per_fieldset_results = []
         left_fields = self.get_config_fields()
         pk_dict_list = None
-        
+
         # primary key set
         if len(self.pk_set) > 0:
             pk_dict_list = self.gen_test_dataset_for_fieldset(self.pk_set, count)
             per_fieldset_results.append(pk_dict_list)
             for each_field in self.pk_set:
                 left_fields.remove(each_field)
-        
+
         # unique sets
         for name, unique_set in self.unique_sets.iteritems():
             if name is True:
@@ -882,10 +881,10 @@
             per_fieldset_results.append(self.gen_test_dataset_for_fieldset(unique_set, count, pk_dict_list=pk_dict_list))
             for each_field in unique_set:
                 left_fields.remove(each_field)
-        
+
         # all left fields into a fieldset
         per_fieldset_results.append(self.gen_test_dataset_for_fieldset(left_fields, count, pk_dict_list=pk_dict_list))
-        
+
         # the first list, must copy it out !!! or else the "update" below will cause bug
         merged_dataset_list = copy.deepcopy(per_fieldset_results[0])
 
@@ -904,7 +903,7 @@
                 return True
         for m in self.children:
             return m._meta.has_statistics
-        
+
         return False
 
     @property
@@ -927,7 +926,7 @@
         for m in self.children:
             return m._meta.has_not_only_asso_stats
 
-        return False 
+        return False
 
     @property
     def has_storeable_statistics(self):
@@ -954,18 +953,18 @@
     def stats_mapper_cls(self):
         if self.stats_mapper == None:
             self.stats_mapper = CreateMapper(self._model)
-        return self.stats_mapper            
-       
+        return self.stats_mapper
+
     @property
     def has_fast_stats_interface(self):
         path_list = copy.copy(self.path)
         if path_list[0] == "loadbalancing":
             path_list[0] = "lb"
-        result = getattr(libustat, "ustat_" + '_'.join(path_list) + "_all", False)                      
+        result = getattr(libustat, "ustat_" + '_'.join(path_list) + "_all", False)
         if result != False:
-            result = True   
+            result = True
         return result
-        
+
     def get_indexed_list(self):
         ret = {"group":{}, "order":{}, "search":{}}
         for field in self.fields:
@@ -1037,12 +1036,12 @@
                 fields.append(each.name)
             ret[field_group.name] = fields
         return ret
-        
+
     def get_group_condition_dict(self):
         ret = {}
         for field_group in self.field_groups.values():
             if field_group.condition:
-                ret[field_group.name] = field_group.condition.to_dict()     
+                ret[field_group.name] = field_group.condition.to_dict()
         return ret
 
     def get_field_default_value_confition_dict(self):
@@ -1051,7 +1050,7 @@
             if isinstance(field.default, DefaultValueCondition):
                 ret[field.name] = field.default.to_dict()
         return ret
-    
+
     def get_field_condition_dict(self):
         ret = {}
         for field in self.fields:
@@ -1067,13 +1066,13 @@
                         get_sub_field_dict['owngroupfield'] = field.name
                         ret[sub_field.name] = get_sub_field_dict
         return ret
-        
+
     def mark_delay_query(self, data_dict):
         for field in self.fields:
             if field.name not in data_dict:
                 data_dict[field.name] = DelayedQuery
         return data_dict
-        
+
     # type: 'config'|'stats'
     def get_list_columns(self, type='config', format=False, custom_options=None):
         columns = []
@@ -1084,7 +1083,7 @@
                 # add check box as the first column
                 columns.append({'name':'check_box_column', 'title':'<input class="checkbox select-all" type="checkbox">', 'width':'20px', 'orderable':False, 'defaultContent':'<input class="checkbox" type="checkbox">'})
             if "columns" in custom_options and custom_options["columns"]:
-                columns_list = copy.deepcopy(custom_options["columns"])               
+                columns_list = copy.deepcopy(custom_options["columns"])
                 for column in columns_list:
                     column['data'] = column['name']
                     if 'title' not in column:
@@ -1100,7 +1099,7 @@
                     if 'defaultContent' not in column:
                         column['defaultContent'] = 'N/A'
                     columns.append(column)
-                        
+
             else:
                 # default: get all config fields name in base class
                 for gn, g in self.field_groups.iteritems():
@@ -1111,6 +1110,10 @@
                                 continue
                             if f.hidden or f.hide_list:
                                 continue
+                            if f.hide_list_condition:
+                                cond = hide_list_condition_check(f, self.app_label, sess)
+                                if cond:
+                                    continue
                             columns.append({'name':f.attname, 'title': unicode(f.verbose_name), 'defaultContent':'N/A', 'data':f.attname})
             # For config list, the -1 column is for 'external data'
             if "external_data_enable" not in custom_options or custom_options["external_data_enable"]:
@@ -1120,7 +1123,7 @@
             columns.append({'name': 'repr','title':'Name', 'data':'repr'})
             custom_options = self.list_stats_options
             if "columns" in custom_options and custom_options["columns"]:
-                columns_list = copy.deepcopy(custom_options["columns"])           
+                columns_list = copy.deepcopy(custom_options["columns"])
                 for column in columns_list:
                     column['data'] = column['name']
                     if 'title' not in column:
@@ -1136,7 +1139,7 @@
                     if 'defaultContent' not in column:
                         column['defaultContent'] = 'N/A'
                     columns.append(column)
-                        
+
             else:
                 # default: get all config fields name in stats class
                 for gn, g in self.field_groups.iteritems():
@@ -1162,7 +1165,7 @@
                         columns.append(name)
         else:
             custom_options = self.list_config_options
-            if "columns" in custom_options and custom_options["columns"]:         
+            if "columns" in custom_options and custom_options["columns"]:
                 for column in custom_options["columns"]:
                     columns.append(column['name'])
             else:
@@ -1195,7 +1198,7 @@
                 #                              if the 'name' is not a field_name for current class, 'title' must set
                 #                'width':  any CSS value (3em, 20px etc) 
                 #                'className': adds a class to each cell in a column
-                #                'defaultContent': if no data is set for this column, the default content will display       
+                #                'defaultContent': if no data is set for this column, the default content will display
                 #              },
                 #              ...
                 #    ], default get all fields in basic fieldGroup.
@@ -1277,18 +1280,18 @@
             if 'auto_refresh_time' not in ret:
                 ret['auto_refresh_time'] = 10
         return json.dumps(ret)
-    
+
     def set_default_node(self, node):
         self._default_node = node
-    
+
     def get_default_node(self):
         if self._default_node:
             return self._default_node
-            
+
         for parent in self.parents.keys():
             if parent._meta._default_node:
                 return parent._meta._default_node
-            
+
         return None
 
     def get_syncable_field_item(self, field_info, model):
@@ -1327,7 +1330,7 @@
             for child in field_info['children']:
                 rst = self.get_syncable_field_item(child, model)
                 rst_dict['children'].append(rst)
-        
+
         return rst_dict
     def get_syncable_fields(self):
         if self.syncable_fields:
@@ -1355,7 +1358,7 @@
                 # add check box as the first column
                 columns.append({'name':'check_box_column', 'title':'<input class="checkbox select-all" type="checkbox">', 'width':'20px', 'orderable':False, 'defaultContent':'<input class="checkbox" type="checkbox">'})
             if "columns" in custom_options and custom_options["columns"]:
-                columns_list = copy.deepcopy(custom_options["columns"])            
+                columns_list = copy.deepcopy(custom_options["columns"])
                 for column in columns_list:
                     column['data'] = column['name']
                     if 'title' not in column:
@@ -1378,7 +1381,7 @@
                     if 'defaultContent' not in column:
                         column['defaultContent'] = 'N/A'
                     columns.append(column)
-                        
+
             else:
                 # default: get all config fields name in base class
                 for gn, g in self.field_groups.iteritems():
@@ -1395,7 +1398,7 @@
             columns.append({'name': 'repr','title':'Name', 'data':'repr'})
             custom_options = self.list_stats_options
             if "columns" in custom_options and custom_options["columns"]:
-                columns_list = copy.deepcopy(custom_options["columns"])             
+                columns_list = copy.deepcopy(custom_options["columns"])
                 for column in columns_list:
                     column['data'] = column['name']
                     if 'title' not in column:
@@ -1418,7 +1421,7 @@
                     if 'defaultContent' not in column:
                         column['defaultContent'] = 'N/A'
                     columns.append(column)
-                        
+
             else:
                 # default: get all config fields name in stats class
                 for gn, g in self.field_groups.iteritems():
@@ -1450,4 +1453,21 @@
                 else:
                     l[i] = pk_field.to_python(l[i])
         return l
-    return f
\ No newline at end of file
+    return f
+
+def hide_list_condition_check(feild, app_label, session):
+    cond = getattr(feild, 'hide_list_condition', None)
+    if cond is None:
+        return False
+    if isinstance(cond, str):
+        model_path, func_name = cond.rsplit('.', 1)
+        model_path_list = model_path.split('.')
+        model = get_model(app_label, model_path_list)
+        manager = model.get_manager(session)
+        if model is None:
+            return False
+        func = getattr(manager, func_name)
+        if func is None:
+            return False
+        return func()
+    return False
