# Table

{% hint style="info" %}
For this panel content, the panel frame url\_name must be **frame\_table**, and it must have a url\_action\_name for the Automail URL controller to find the panel content.
{% endhint %}

Below is an example configuration of a panel using the **Table** module:

```python
{
    "title": "Default Lead-Time",
    "width": 12,
    "full_row": True,
    "url_name": "frame_table",
    "url_action_name": "table_defaultleadtimetracker",
    "content": {
        "view": api_views.Table,
        "view_params": {
            "model": custom_models.DefaultLeadTimeTracker,
            "order_by": "id",
            "init_max_rows_threshold": 20000,
            "table_settings": {
                "options": {
                    "hide_id_column": True,
                },
                "permissions": {
                    "read": {
                        "allowed": True,
                        "allowed_user_groups": [],
                        "allowed_users": [],
                    },
                    "update": {
                        "allowed": False,
                        "allowed_user_groups": [],
                        "allowed_users": [],
                    },
                    "insert": {
                        "allowed": False,
                        "allowed_user_groups": [],
                        "allowed_users": [],
                    },
                    "delete": {
                        "allowed": False,
                        "allowed_user_groups": [],
                        "allowed_users": [],
                    },
                },
            },
            "field_definitions": {
                "supplier__name": {
                    "source_include_filters": {
                        "is_t2": True
                    }
                },
                "season__search_reference_suggestion_text": {},
                "web_number": {},
                "update_timestamp": {"read_only": True},
                "user_id": {"read_only": True},
            },
            "include_filters_extra": {
                "report_category": "Delivery Report",
            },
        },
    },
}
```

The **view\_params** are:

* **model** the model this table is based on
* **order\_by** the model field (str) or fields (list) to order the table by when loading (by default ascending alphanumeric order, for descending order use the prefix "-" (e.g. "-id"))
* **is\_empty** sets whether the table should be empty by default until the user clicks the Search button (must have a selectpickers section on top of the page)
* **init\_max\_rows\_threshold** the maximum number of rows that will be displayed without the user clicking the Search button
* **table\_settings** the table-level configuration

Create an uploadfile\_\_.py to upload the table in database

```python
try:
    from _init import *
except ImportError:
    from configurations.workflow_env import *
from polygon.apps.app_flows.controller import process_uploadfiles


def process_uploadfiles_monitor_coc():
    process_uploadfiles(
        **{
            "model": custom_models.Monitor,
            "table_settings": {
                "options": {
                    "hide_id_column": True,
                    "fixed_write_fields": {
                        "survey": "Chain of Custody Management",
                    },
                },
                "uploading_config": {
                    "extract": {
                        "sheet_name": 0,
                    },
                    "load": {
                        "do_bulk_insert": True,
                        "method": {
                            "function": "upsert",
                            "params": {
                                "unique_together": True,
                                "key_fields": [
                                    "season",
                                    "supplier_id",
                                    "surveygroup_id",
                                ],
                            },
                        },
                    },
                },
            },
            "field_definitions": {
                "season": {"allow_empty": False},
                "surveygroup__name": {
                    "allow_empty": False,
                    "source_include_filters": {"survey": "Chain of Custody Management"},
                },
                "supplier__name": {
                    "allow_empty": False,
                    "threshold_level": "strict",
                    # "label_alternatives": ["Select Supplier"],
                },
                "supplier__suppliergroup__name": {
                    "threshold_level": "strict",
                },
                "survey_contact_email": {
                    "allow_empty": False,
                    "internal_type": "EmailField",
                    "threshold_level": "strict",
                },
            },
        }
    )


if __name__ == "__main__":
    write_to_file(log_file_path, "process_uploadfiles_monitor_coc")
    monitoring(process_uploadfiles_monitor_coc)
    write_to_file(log_file_path, "completed")

```

For each column name in "field\_definition",  you can set up additional settings for the table

```python

"field_definitions": {
    "survey": {
        "source": custom_models.KEY_MATERIAL_SURVEYS,
    },
    "question": {
        "width": 300,
        "validations": [
            {
                "name": "custom",
                "params": {
                    "function": custom_functions.validate_question_exist,
                    "message": "The question(s) are not valid for the corresponding survey. <br>",
                },
            }
        ],
    },
    "answer": {
        "width": 300,
    },
    "survey_contact_email": {
        "transformations": [
            "lower",
            {
                "name": "sort_alphabetical_split_by_separator",
                "params": {
                    "separator": ",",
                },
            },
        ],
        "validations": [
            {
                "name": "custom",
                "params": {
                    "function": custom_functions.validate_contact_email,
                    "message": "Only valid email addresses allowed for",
                },
            },
        ],
    },
    "update_timestamp": {"read_only": True},
    "user_id": {"read_only": True},
},
```

* **source** the value in each row for the column should be in the field of the list you provided
* **width** set up the initial width for the column
* **validations** will validate the input value in the column and provide the message showing when the validation fails. You can set up the custom function in f**unction.py** like this&#x20;

<pre class="language-python"><code class="lang-python"><strong>def validate_question_exist(df, filtered_df):
</strong>    def apply_validation(row):
        questions = list(
            custom_models.MonitorQuestionAnswer.objects.filter(
                question_category=row["survey"]
            )
            .values_list("question", flat=True)
            .distinct()
        )
        return row["question"] in questions

    df["is_valid_flag"] = filtered_df.apply(apply_validation, args=(), axis=1)
    return df
</code></pre>

* **transformations** can transform the initial input value in the table to a specific value based on the custom function or a set-up function.

Process\_upload\_file function parameters are:

* **model** the model this table is based on
* **table\_settings** can set up the configurations in the table
* **field\_definitions** determine the column and its constraints, and you can also provide the column label alternatives to catch the column in the table.

<figure><img src="https://3317070279-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F21lWxRGfp98mDu2HVXvf%2Fuploads%2FRufQbUyujDtbsDQx5ruw%2Fimage.png?alt=media&#x26;token=24457ccf-dfbf-466d-ae47-2621881c67fa" alt=""><figcaption></figcaption></figure>

After dropping the Excel file in the upload box, you can run the uploadfile\_\_.py to load the table in the database.

You can also set the uploadfile\_\_.py as a Dag. Check the dag part

{% content-ref url="../../../workflow-configuration/dags" %}
[dags](https://docs.lineverge.com/automail/configurations/workflow-configuration/dags)
{% endcontent-ref %}
