<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="th">
	<id>http://wiki.cuneifox.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Noina</id>
	<title>คูนิฟ็อกซ์ วิกิ - การเข้ามีส่วนร่วมของผู้ใช้ [th]</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.cuneifox.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Noina"/>
	<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/wiki/%E0%B8%9E%E0%B8%B4%E0%B9%80%E0%B8%A8%E0%B8%A9:%E0%B9%80%E0%B8%A3%E0%B8%B7%E0%B9%88%E0%B8%AD%E0%B8%87%E0%B8%97%E0%B8%B5%E0%B9%88%E0%B9%80%E0%B8%82%E0%B8%B5%E0%B8%A2%E0%B8%99/Noina"/>
	<updated>2026-06-15T03:14:19Z</updated>
	<subtitle>การเข้ามีส่วนร่วมของผู้ใช้</subtitle>
	<generator>MediaWiki 1.39.3</generator>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2147</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2147"/>
		<updated>2025-05-23T10:01:11Z</updated>

		<summary type="html">&lt;p&gt;Noina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่มี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน table.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน html.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า route: จะถูกเขียนอยู่ใน routes.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== model.py ===&lt;br /&gt;
model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่ [[CuneiModel]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
&lt;br /&gt;
=== html.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวฟอร์ม(ฟอร์มต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน form.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน html.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า route จะถูกเขียนอยู่ใน routes.py&lt;br /&gt;
** ถ้าFormมีการคิดวิเคราะห์ที่ลึกมากขึ้น ไม่สามารถเขียนใน routes.py ได้ ให้ไปเขียนไว้ใน functions.py แทน&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== model.py ===&lt;br /&gt;
model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    passport = CharField()&lt;br /&gt;
    first_name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    middle_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    last_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    birthday = CharField()&lt;br /&gt;
    saving = FloatField()&lt;br /&gt;
    gender = CharField()&lt;br /&gt;
    status = CharField()&lt;br /&gt;
    spouse_first_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    spouse_middle_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    spouse_last_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    address = TextField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    pict = CharField(null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== html.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Tag ต่างๆที่ควรรู้&lt;br /&gt;
&lt;br /&gt;
:- &#039;&#039;&#039;general_form_head / general_form_tail&#039;&#039;&#039; : Tagเปิด/ปิดส่วนของform ช่องข้อมูลทั้งหมดที่แสดงจะต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
:- &#039;&#039;&#039;&amp;lt;img id=&amp;quot;form.pict.id&amp;quot;&amp;gt;&#039;&#039;&#039; : หากข้อมูลที่ใส่เป็นข้อมูลประเภทรูปภาพ ให้ใช้Tagนี้&lt;br /&gt;
:- &#039;&#039;&#039;render_check&#039;&#039;&#039; : เป็น Tag ที่สร้างcheck box&lt;br /&gt;
:- &#039;&#039;&#039;render_upload&#039;&#039;&#039; : เป็น Tag ที่สร้างแถบอัพโหลดไฟล์&lt;br /&gt;
:- &#039;&#039;&#039;render_blank&#039;&#039;&#039; : เป็น Tag ที่สร้างช่อง label และหัวของlabel&lt;br /&gt;
:- &#039;&#039;&#039;render_radio&#039;&#039;&#039; : เป็น Tag ที่สร้าง Text redio&lt;br /&gt;
:- &#039;&#039;&#039;render_submit&#039;&#039;&#039; : เป็น Tag ที่สร้างปุ่มsubmit ทุกครั้งที่สร้างฟอร์มจำเป็นต้องมี&lt;br /&gt;
:- &#039;&#039;&#039;block greeter_jvs / endblock greeter_jvs&#039;&#039;&#039; : เป็น Tag ที่ไว้สำหรับเขียน javascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2146</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2146"/>
		<updated>2025-05-23T09:57:39Z</updated>

		<summary type="html">&lt;p&gt;Noina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่มี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน table.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน html.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า route: จะถูกเขียนอยู่ใน routes.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== model.py ===&lt;br /&gt;
model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
&lt;br /&gt;
=== html.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวฟอร์ม(ฟอร์มต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน form.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน html.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า route จะถูกเขียนอยู่ใน routes.py&lt;br /&gt;
** ถ้าFormมีการคิดวิเคราะห์ที่ลึกมากขึ้น ไม่สามารถเขียนใน routes.py ได้ ให้ไปเขียนไว้ใน functions.py แทน&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== model.py ===&lt;br /&gt;
model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    passport = CharField()&lt;br /&gt;
    first_name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    middle_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    last_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    birthday = CharField()&lt;br /&gt;
    saving = FloatField()&lt;br /&gt;
    gender = CharField()&lt;br /&gt;
    status = CharField()&lt;br /&gt;
    spouse_first_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    spouse_middle_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    spouse_last_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    address = TextField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    pict = CharField(null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== html.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Tag ต่างๆที่ควรรู้&lt;br /&gt;
&lt;br /&gt;
:- &#039;&#039;&#039;general_form_head / general_form_tail&#039;&#039;&#039; : Tagเปิด/ปิดส่วนของform ช่องข้อมูลทั้งหมดที่แสดงจะต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
:- &#039;&#039;&#039;&amp;lt;img id=&amp;quot;form.pict.id&amp;quot;&amp;gt;&#039;&#039;&#039; : หากข้อมูลที่ใส่เป็นข้อมูลประเภทรูปภาพ ให้ใช้Tagนี้&lt;br /&gt;
:- &#039;&#039;&#039;render_check&#039;&#039;&#039; : เป็น Tag ที่สร้างcheck box&lt;br /&gt;
:- &#039;&#039;&#039;render_upload&#039;&#039;&#039; : เป็น Tag ที่สร้างแถบอัพโหลดไฟล์&lt;br /&gt;
:- &#039;&#039;&#039;render_blank&#039;&#039;&#039; : เป็น Tag ที่สร้างช่อง label และหัวของlabel&lt;br /&gt;
:- &#039;&#039;&#039;render_radio&#039;&#039;&#039; : เป็น Tag ที่สร้าง Text redio&lt;br /&gt;
:- &#039;&#039;&#039;render_submit&#039;&#039;&#039; : เป็น Tag ที่สร้างปุ่มsubmit ทุกครั้งที่สร้างฟอร์มจำเป็นต้องมี&lt;br /&gt;
:- &#039;&#039;&#039;block greeter_jvs / endblock greeter_jvs&#039;&#039;&#039; : เป็น Tag ที่ไว้สำหรับเขียน javascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2145</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2145"/>
		<updated>2025-05-23T09:53:59Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* Rount.py */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่มี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวฟอร์ม(ฟอร์มต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Form.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
** ถ้าFormมีการคิดวิเคราะห์ที่ลึกมากขึ้น ไม่สามารถเขียนในrounts.pyได้ ให้ไปเขียนไว้ในfunctions.pyแทน&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    passport = CharField()&lt;br /&gt;
    first_name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    middle_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    last_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    birthday = CharField()&lt;br /&gt;
    saving = FloatField()&lt;br /&gt;
    gender = CharField()&lt;br /&gt;
    status = CharField()&lt;br /&gt;
    spouse_first_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    spouse_middle_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    spouse_last_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    address = TextField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    pict = CharField(null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Tag ต่างๆที่ควรรู้&lt;br /&gt;
&lt;br /&gt;
:- &#039;&#039;&#039;general_form_head / general_form_tail&#039;&#039;&#039; : Tagเปิด/ปิดส่วนของform ช่องข้อมูลทั้งหมดที่แสดงจะต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
:- &#039;&#039;&#039;&amp;lt;img id=&amp;quot;form.pict.id&amp;quot;&amp;gt;&#039;&#039;&#039; : หากข้อมูลที่ใส่เป็นข้อมูลประเภทรูปภาพ ให้ใช้Tagนี้&lt;br /&gt;
:- &#039;&#039;&#039;render_check&#039;&#039;&#039; : เป็น Tag ที่สร้างcheck box&lt;br /&gt;
:- &#039;&#039;&#039;render_upload&#039;&#039;&#039; : เป็น Tag ที่สร้างแถบอัพโหลดไฟล์&lt;br /&gt;
:- &#039;&#039;&#039;render_blank&#039;&#039;&#039; : เป็น Tag ที่สร้างช่อง label และหัวของlabel&lt;br /&gt;
:- &#039;&#039;&#039;render_radio&#039;&#039;&#039; : เป็น Tag ที่สร้าง Text redio&lt;br /&gt;
:- &#039;&#039;&#039;render_submit&#039;&#039;&#039; : เป็น Tag ที่สร้างปุ่มsubmit ทุกครั้งที่สร้างฟอร์มจำเป็นต้องมี&lt;br /&gt;
:- &#039;&#039;&#039;block greeter_jvs / endblock greeter_jvs&#039;&#039;&#039; : เป็น Tag ที่ไว้สำหรับเขียน javascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2144</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2144"/>
		<updated>2025-05-23T09:52:51Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* rounts.py */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่มี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวฟอร์ม(ฟอร์มต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Form.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
** ถ้าFormมีการคิดวิเคราะห์ที่ลึกมากขึ้น ไม่สามารถเขียนในrounts.pyได้ ให้ไปเขียนไว้ในfunctions.pyแทน&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    passport = CharField()&lt;br /&gt;
    first_name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    middle_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    last_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    birthday = CharField()&lt;br /&gt;
    saving = FloatField()&lt;br /&gt;
    gender = CharField()&lt;br /&gt;
    status = CharField()&lt;br /&gt;
    spouse_first_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    spouse_middle_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    spouse_last_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    address = TextField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    pict = CharField(null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Tag ต่างๆที่ควรรู้&lt;br /&gt;
&lt;br /&gt;
:- &#039;&#039;&#039;general_form_head / general_form_tail&#039;&#039;&#039; : Tagเปิด/ปิดส่วนของform ช่องข้อมูลทั้งหมดที่แสดงจะต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
:- &#039;&#039;&#039;&amp;lt;img id=&amp;quot;form.pict.id&amp;quot;&amp;gt;&#039;&#039;&#039; : หากข้อมูลที่ใส่เป็นข้อมูลประเภทรูปภาพ ให้ใช้Tagนี้&lt;br /&gt;
:- &#039;&#039;&#039;render_check&#039;&#039;&#039; : เป็น Tag ที่สร้างcheck box&lt;br /&gt;
:- &#039;&#039;&#039;render_upload&#039;&#039;&#039; : เป็น Tag ที่สร้างแถบอัพโหลดไฟล์&lt;br /&gt;
:- &#039;&#039;&#039;render_blank&#039;&#039;&#039; : เป็น Tag ที่สร้างช่อง label และหัวของlabel&lt;br /&gt;
:- &#039;&#039;&#039;render_radio&#039;&#039;&#039; : เป็น Tag ที่สร้าง Text redio&lt;br /&gt;
:- &#039;&#039;&#039;render_submit&#039;&#039;&#039; : เป็น Tag ที่สร้างปุ่มsubmit ทุกครั้งที่สร้างฟอร์มจำเป็นต้องมี&lt;br /&gt;
:- &#039;&#039;&#039;block greeter_jvs / endblock greeter_jvs&#039;&#039;&#039; : เป็น Tag ที่ไว้สำหรับเขียน javascript&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2143</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2143"/>
		<updated>2025-05-23T09:41:20Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* Model.py */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่มี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวฟอร์ม(ฟอร์มต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Form.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
** ถ้าFormมีการคิดวิเคราะห์ที่ลึกมากขึ้น ไม่สามารถเขียนในrounts.pyได้ ให้ไปเขียนไว้ในfunctions.pyแทน&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    passport = CharField()&lt;br /&gt;
    first_name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    middle_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    last_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    birthday = CharField()&lt;br /&gt;
    saving = FloatField()&lt;br /&gt;
    gender = CharField()&lt;br /&gt;
    status = CharField()&lt;br /&gt;
    spouse_first_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    spouse_middle_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    spouse_last_name = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    address = TextField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    pict = CharField(null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Tag ต่างๆที่ควรรู้&lt;br /&gt;
&lt;br /&gt;
:- &#039;&#039;&#039;general_form_head / general_form_tail&#039;&#039;&#039; : Tagเปิด/ปิดส่วนของform ช่องข้อมูลทั้งหมดที่แสดงจะต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
:- &#039;&#039;&#039;&amp;lt;img id=&amp;quot;form.pict.id&amp;quot;&amp;gt;&#039;&#039;&#039; : หากข้อมูลที่ใส่เป็นข้อมูลประเภทรูปภาพ ให้ใช้Tagนี้&lt;br /&gt;
:- &#039;&#039;&#039;render_check&#039;&#039;&#039; : เป็น Tag ที่สร้างcheck box&lt;br /&gt;
:- &#039;&#039;&#039;render_upload&#039;&#039;&#039; : เป็น Tag ที่สร้างแถบอัพโหลดไฟล์&lt;br /&gt;
:- &#039;&#039;&#039;render_blank&#039;&#039;&#039; : เป็น Tag ที่สร้างช่อง label และหัวของlabel&lt;br /&gt;
:- &#039;&#039;&#039;render_radio&#039;&#039;&#039; : เป็น Tag ที่สร้าง Text redio&lt;br /&gt;
:- &#039;&#039;&#039;render_submit&#039;&#039;&#039; : เป็น Tag ที่สร้างปุ่มsubmit ทุกครั้งที่สร้างฟอร์มจำเป็นต้องมี&lt;br /&gt;
:- &#039;&#039;&#039;block greeter_jvs / endblock greeter_jvs&#039;&#039;&#039; : เป็น Tag ที่ไว้สำหรับเขียน javascript&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2142</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2142"/>
		<updated>2025-05-23T09:40:47Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* สร้าง Form - non Database */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่มี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวฟอร์ม(ฟอร์มต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Form.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
** ถ้าFormมีการคิดวิเคราะห์ที่ลึกมากขึ้น ไม่สามารถเขียนในrounts.pyได้ ให้ไปเขียนไว้ในfunctions.pyแทน&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Tag ต่างๆที่ควรรู้&lt;br /&gt;
&lt;br /&gt;
:- &#039;&#039;&#039;general_form_head / general_form_tail&#039;&#039;&#039; : Tagเปิด/ปิดส่วนของform ช่องข้อมูลทั้งหมดที่แสดงจะต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
:- &#039;&#039;&#039;&amp;lt;img id=&amp;quot;form.pict.id&amp;quot;&amp;gt;&#039;&#039;&#039; : หากข้อมูลที่ใส่เป็นข้อมูลประเภทรูปภาพ ให้ใช้Tagนี้&lt;br /&gt;
:- &#039;&#039;&#039;render_check&#039;&#039;&#039; : เป็น Tag ที่สร้างcheck box&lt;br /&gt;
:- &#039;&#039;&#039;render_upload&#039;&#039;&#039; : เป็น Tag ที่สร้างแถบอัพโหลดไฟล์&lt;br /&gt;
:- &#039;&#039;&#039;render_blank&#039;&#039;&#039; : เป็น Tag ที่สร้างช่อง label และหัวของlabel&lt;br /&gt;
:- &#039;&#039;&#039;render_radio&#039;&#039;&#039; : เป็น Tag ที่สร้าง Text redio&lt;br /&gt;
:- &#039;&#039;&#039;render_submit&#039;&#039;&#039; : เป็น Tag ที่สร้างปุ่มsubmit ทุกครั้งที่สร้างฟอร์มจำเป็นต้องมี&lt;br /&gt;
:- &#039;&#039;&#039;block greeter_jvs / endblock greeter_jvs&#039;&#039;&#039; : เป็น Tag ที่ไว้สำหรับเขียน javascript&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2141</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2141"/>
		<updated>2025-05-23T09:30:02Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* สร้าง Form - non Database */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่มี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวฟอร์ม(ฟอร์มต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Form.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
** ถ้าFormมีการคิดวิเคราะห์ที่ลึกมากขึ้น ไม่สามารถเขียนในrounts.pyได้ ให้ไปเขียนไว้ในfunctions.pyแทน&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Tag ต่างๆที่ควรรู้&lt;br /&gt;
&lt;br /&gt;
:- &#039;&#039;&#039;general_form_head / general_form_tail&#039;&#039;&#039; : Tagเปิด/ปิดส่วนของform ช่องข้อมูลทั้งหมดที่แสดงจะต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
:- &#039;&#039;&#039;&amp;lt;img id=&amp;quot;form.pict.id&amp;quot;&amp;gt;&#039;&#039;&#039; : หากข้อมูลที่ใส่เป็นข้อมูลประเภทรูปภาพ ให้ใช้Tagนี้&lt;br /&gt;
:- &#039;&#039;&#039;render_check&#039;&#039;&#039; : เป็น Tag ที่สร้างcheck box&lt;br /&gt;
:- &#039;&#039;&#039;render_upload&#039;&#039;&#039; : เป็น Tag ที่สร้างแถบอัพโหลดไฟล์&lt;br /&gt;
:- &#039;&#039;&#039;render_blank&#039;&#039;&#039; : เป็น Tag ที่สร้างช่อง label และหัวของlabel&lt;br /&gt;
:- &#039;&#039;&#039;render_radio&#039;&#039;&#039; : เป็น Tag ที่สร้าง Text redio&lt;br /&gt;
:- &#039;&#039;&#039;render_submit&#039;&#039;&#039; : เป็น Tag ที่สร้างปุ่มsubmit ทุกครั้งที่สร้างฟอร์มจำเป็นต้องมี&lt;br /&gt;
:- &#039;&#039;&#039;block greeter_jvs / endblock greeter_jvs&#039;&#039;&#039; : เป็น Tag ที่ไว้สำหรับเขียน javascript&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2140</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2140"/>
		<updated>2025-05-23T09:22:19Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* สร้าง Form - non Database */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่มี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวฟอร์ม(ฟอร์มต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Form.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
** ถ้าFormมีการคิดวิเคราะห์ที่ลึกมากขึ้น ไม่สามารถเขียนในrounts.pyได้ ให้ไปเขียนไว้ในfunctions.pyแทน&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Tag ต่างๆที่ควรรู้&lt;br /&gt;
&lt;br /&gt;
:- &#039;&#039;&#039;general_form_head / general_form_tail&#039;&#039;&#039; : Tagเปิด/ปิดส่วนของform ช่องข้อมูลทั้งหมดที่แสดงจะต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
:- &#039;&#039;&#039;&amp;lt;img id=&amp;quot;form.pict.id&amp;quot;&amp;gt;&#039;&#039;&#039; : หากข้อมูลที่ใส่เป็นข้อมูลประเภทรูปภาพ ให้ใช้Tagนี้&lt;br /&gt;
:- &#039;&#039;&#039;render_check&#039;&#039;&#039; : เป็น Tag ที่สร้างcheck box&lt;br /&gt;
:- &#039;&#039;&#039;render_upload&#039;&#039;&#039; : เป็น Tag ที่สร้างแถบอัพโหลดไฟล์&lt;br /&gt;
:- &#039;&#039;&#039;render_blank&#039;&#039;&#039; : เป็น Tag ที่สร้างช่อง label และหัวของlabel&lt;br /&gt;
:- &#039;&#039;&#039;render_radio&#039;&#039;&#039; : เป็น Tag ที่สร้าง Text redio&lt;br /&gt;
:- &#039;&#039;&#039;render_submit&#039;&#039;&#039; : เป็น Tag ที่สร้างปุ่มsubmit ทุกครั้งที่สร้างฟอร์มจำเป็นต้องมี&lt;br /&gt;
:- &#039;&#039;&#039;block greeter_jvs / endblock greeter_jvs&#039;&#039;&#039; : เป็น Tag ที่ไว้สำหรับเขียน javascript&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2139</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2139"/>
		<updated>2025-05-23T08:49:34Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* สร้าง Form - non Database */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่มี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวฟอร์ม(ฟอร์มต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Form.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Tag ต่างๆที่ควรรู้&lt;br /&gt;
&lt;br /&gt;
:- &#039;&#039;&#039;general_form_head / general_form_tail&#039;&#039;&#039; : Tagเปิด/ปิดส่วนของform ช่องข้อมูลทั้งหมดที่แสดงจะต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
:- &#039;&#039;&#039;&amp;lt;img id=&amp;quot;form.pict.id&amp;quot;&amp;gt;&#039;&#039;&#039; : หากข้อมูลที่ใส่เป็นข้อมูลประเภทรูปภาพ ให้ใช้Tagนี้&lt;br /&gt;
:- &#039;&#039;&#039;render_check&#039;&#039;&#039; : เป็น Tag ที่สร้างcheck box&lt;br /&gt;
:- &#039;&#039;&#039;render_upload&#039;&#039;&#039; : เป็น Tag ที่สร้างแถบอัพโหลดไฟล์&lt;br /&gt;
:- &#039;&#039;&#039;render_blank&#039;&#039;&#039; : เป็น Tag ที่สร้างช่อง label และหัวของlabel&lt;br /&gt;
:- &#039;&#039;&#039;render_radio&#039;&#039;&#039; : เป็น Tag ที่สร้าง Text redio&lt;br /&gt;
:- &#039;&#039;&#039;render_submit&#039;&#039;&#039; : เป็น Tag ที่สร้างปุ่มsubmit ทุกครั้งที่สร้างฟอร์มจำเป็นต้องมี&lt;br /&gt;
:- &#039;&#039;&#039;block greeter_jvs / endblock greeter_jvs&#039;&#039;&#039; : เป็น Tag ที่ไว้สำหรับเขียน javascript&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2138</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2138"/>
		<updated>2025-05-23T08:37:31Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* สร้าง Table - Database */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่มี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบตัวตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Tag ต่างๆที่ควรรู้&lt;br /&gt;
&lt;br /&gt;
:- &#039;&#039;&#039;general_form_head / general_form_tail&#039;&#039;&#039; : Tagเปิด/ปิดส่วนของform ช่องข้อมูลทั้งหมดที่แสดงจะต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
:- &#039;&#039;&#039;&amp;lt;img id=&amp;quot;form.pict.id&amp;quot;&amp;gt;&#039;&#039;&#039; : หากข้อมูลที่ใส่เป็นข้อมูลประเภทรูปภาพ ให้ใช้Tagนี้&lt;br /&gt;
:- &#039;&#039;&#039;render_check&#039;&#039;&#039; : เป็น Tag ที่สร้างcheck box&lt;br /&gt;
:- &#039;&#039;&#039;render_upload&#039;&#039;&#039; : เป็น Tag ที่สร้างแถบอัพโหลดไฟล์&lt;br /&gt;
:- &#039;&#039;&#039;render_blank&#039;&#039;&#039; : เป็น Tag ที่สร้างช่อง label และหัวของlabel&lt;br /&gt;
:- &#039;&#039;&#039;render_radio&#039;&#039;&#039; : เป็น Tag ที่สร้าง Text redio&lt;br /&gt;
:- &#039;&#039;&#039;render_submit&#039;&#039;&#039; : เป็น Tag ที่สร้างปุ่มsubmit ทุกครั้งที่สร้างฟอร์มจำเป็นต้องมี&lt;br /&gt;
:- &#039;&#039;&#039;block greeter_jvs / endblock greeter_jvs&#039;&#039;&#039; : เป็น Tag ที่ไว้สำหรับเขียน javascript&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2137</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2137"/>
		<updated>2025-05-23T08:36:27Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* สร้าง Table - Database */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่มี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Tag ต่างๆที่ควรรู้&lt;br /&gt;
&lt;br /&gt;
:- &#039;&#039;&#039;general_form_head / general_form_tail&#039;&#039;&#039; : Tagเปิด/ปิดส่วนของform ช่องข้อมูลทั้งหมดที่แสดงจะต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
:- &#039;&#039;&#039;&amp;lt;img id=&amp;quot;form.pict.id&amp;quot;&amp;gt;&#039;&#039;&#039; : หากข้อมูลที่ใส่เป็นข้อมูลประเภทรูปภาพ ให้ใช้Tagนี้&lt;br /&gt;
:- &#039;&#039;&#039;render_check&#039;&#039;&#039; : เป็น Tag ที่สร้างcheck box&lt;br /&gt;
:- &#039;&#039;&#039;render_upload&#039;&#039;&#039; : เป็น Tag ที่สร้างแถบอัพโหลดไฟล์&lt;br /&gt;
:- &#039;&#039;&#039;render_blank&#039;&#039;&#039; : เป็น Tag ที่สร้างช่อง label และหัวของlabel&lt;br /&gt;
:- &#039;&#039;&#039;render_radio&#039;&#039;&#039; : เป็น Tag ที่สร้าง Text redio&lt;br /&gt;
:- &#039;&#039;&#039;render_submit&#039;&#039;&#039; : เป็น Tag ที่สร้างปุ่มsubmit ทุกครั้งที่สร้างฟอร์มจำเป็นต้องมี&lt;br /&gt;
:- &#039;&#039;&#039;block greeter_jvs / endblock greeter_jvs&#039;&#039;&#039; : เป็น Tag ที่ไว้สำหรับเขียน javascript&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2136</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2136"/>
		<updated>2025-05-23T08:32:53Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* HTML.py */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Tag ต่างๆที่ควรรู้&lt;br /&gt;
&lt;br /&gt;
:- &#039;&#039;&#039;general_form_head / general_form_tail&#039;&#039;&#039; : Tagเปิด/ปิดส่วนของform ช่องข้อมูลทั้งหมดที่แสดงจะต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
:- &#039;&#039;&#039;&amp;lt;img id=&amp;quot;form.pict.id&amp;quot;&amp;gt;&#039;&#039;&#039; : หากข้อมูลที่ใส่เป็นข้อมูลประเภทรูปภาพ ให้ใช้Tagนี้&lt;br /&gt;
:- &#039;&#039;&#039;render_check&#039;&#039;&#039; : เป็น Tag ที่สร้างcheck box&lt;br /&gt;
:- &#039;&#039;&#039;render_upload&#039;&#039;&#039; : เป็น Tag ที่สร้างแถบอัพโหลดไฟล์&lt;br /&gt;
:- &#039;&#039;&#039;render_blank&#039;&#039;&#039; : เป็น Tag ที่สร้างช่อง label และหัวของlabel&lt;br /&gt;
:- &#039;&#039;&#039;render_radio&#039;&#039;&#039; : เป็น Tag ที่สร้าง Text redio&lt;br /&gt;
:- &#039;&#039;&#039;render_submit&#039;&#039;&#039; : เป็น Tag ที่สร้างปุ่มsubmit ทุกครั้งที่สร้างฟอร์มจำเป็นต้องมี&lt;br /&gt;
:- &#039;&#039;&#039;block greeter_jvs / endblock greeter_jvs&#039;&#039;&#039; : เป็น Tag ที่ไว้สำหรับเขียน javascript&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2135</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2135"/>
		<updated>2025-05-23T08:22:27Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* HTML.py */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Tag ต่างๆที่ควรรู้&lt;br /&gt;
&lt;br /&gt;
:- &#039;&#039;&#039;general_form_head / general_form_tail&#039;&#039;&#039; : Tagเปิด/ปิดส่วนของform ช่องข้อมูลทั้งหมดที่แสดงจะต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
:- &#039;&#039;&#039;&amp;lt;img id=&amp;quot;form.pict.id&amp;quot;&amp;gt;&#039;&#039;&#039; : หากข้อมูลที่ใส่เป็นข้อมูลประเภทรูปภาพ ให้ใช้Tagนี้&lt;br /&gt;
:- &#039;&#039;&#039;render_check&#039;&#039;&#039; : เป็น Tag ที่สร้างcheck box&lt;br /&gt;
:- &#039;&#039;&#039;render_upload&#039;&#039;&#039; : เป็น Tag ที่สร้างแถบอัพโหลดไฟล์&lt;br /&gt;
:- &#039;&#039;&#039;render_blank&#039;&#039;&#039; : เป็น Tag ที่สร้างช่อง label และหัวของlabel&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2134</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2134"/>
		<updated>2025-05-23T07:10:38Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* HTML.py */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยาย Code&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
general_form_head&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
general_form_tail&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; Tagเปิด/ปิดส่วนของform ช่องข้อมูลทั้งหมดที่แสดงจะต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot;style=&amp;quot;width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;หากข้อมูลที่ใส่เป็นข้อมูลประเภทรูปภาพ ให้ใช้Tagนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
render_check&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น Tag ที่สร้างcheck box&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
render_upload&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น Tag ที่สร้างแถบอัพโหลดไฟล์&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
render_blank&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น Tag ที่สร้างช่อง label และหัวของlabel&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2133</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2133"/>
		<updated>2025-05-23T04:06:31Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* HTML.py */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยาย Code&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; Tagเปิด/ปิดส่วนของform ช่องข้อมูลทั้งหมดที่แสดงจะต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot;style=&amp;quot;width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;หากข้อมูลที่ใส่เป็นข้อมูลประเภทรูปภาพ ให้ใช้Tagนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นTagที่สร้างแถบอัพโหลดไฟล์&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2132</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2132"/>
		<updated>2025-05-23T02:53:24Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* ฟังก์ชั่นการใช้งานและชนิดช้อมูล */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def validate_spouse_first_name(...)&lt;br /&gt;
def validate_saving(...)&lt;br /&gt;
def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2131</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2131"/>
		<updated>2025-05-23T02:51:24Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* ฟังก์ชั่นการใช้งานและชนิดช้อมูล */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2130</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2130"/>
		<updated>2025-05-23T02:49:42Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* ฟังก์ชั่นการใช้งานและชนิดช้อมูล */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย &lt;br /&gt;
**:สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2129</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2129"/>
		<updated>2025-05-22T08:46:36Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีลัด */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2128</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2128"/>
		<updated>2025-05-22T08:46:09Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีลัด */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนfunctionนี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ข้างในfunctionเขียนดังนี้&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ข้างในfunctionเขียนดังนี้&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2127</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2127"/>
		<updated>2025-05-22T08:12:50Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีลัด */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2126</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2126"/>
		<updated>2025-05-22T08:03:07Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีลัด */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยทำให้โค้ดดูสั้นขึ้นและอ่านง่ายขึ้น โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้ไปsetไว้ในที่เดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่จัดการค่าเริ่มต้นต่างๆที่ระบบควรมี&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ฟังก์ชั่นนี้ จะทำหน้าที่ดึงข้อมูลมีระบบควรจะรู้ออกมา&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2125</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2125"/>
		<updated>2025-05-22T07:42:41Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีลัด */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยกำหนดแค่ค่าเริ่มต้น และรวบรวมตัวแปรให้อยู่ในชุดเดียวกัน (ขั้นตอนในการดำเนินการเหมือนกัน เพียงแค่ย่อมันให้สั้นลงเท่านั้น)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2124</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2124"/>
		<updated>2025-05-22T07:19:37Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + submit(สถานะการบันทึก) + del_submit(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ is_del(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2123</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2123"/>
		<updated>2025-05-22T07:18:44Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน แต่ละfield ก็จะเก็บ dataของตัวเองไว้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดในdatabase + &#039;submit&#039;(สถานะการบันทึก) + &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2122</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2122"/>
		<updated>2025-05-22T07:04:43Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;{{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2121</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2121"/>
		<updated>2025-05-22T07:00:37Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด {{code|lang=python|&#039;fetch&#039;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &#039;&#039;&#039;: ถ้าเป็นโหมด {{code|lang=python|&#039;is_submit&#039;}}&#039;&#039;&#039;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2120</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2120"/>
		<updated>2025-05-22T06:59:27Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด {{code|lang=python|&#039;&amp;quot;fetch&amp;quot;}}&#039;&#039;&#039; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &amp;quot;is_submit&amp;quot;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2119</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2119"/>
		<updated>2025-05-22T06:57:53Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &amp;quot;fetch&amp;quot; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;:ถ้าเป็นโหมด &amp;quot;is_submit&amp;quot;(มีข้อมูลที่จะต้องเข้าdata base หรือมีกิจกรรมที่ต้องยุ่งกับdata base)สามารถเปิด data base แล้วดำเนินการได้เลย&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2118</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2118"/>
		<updated>2025-05-22T06:38:08Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get&#039;}}&#039;&#039;&#039;: ถ้าเป็นโหมด &amp;quot;fetch&amp;quot; (มีการเคลื่อนไหวของข้อมูล แต่ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2117</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2117"/>
		<updated>2025-05-22T06:26:00Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;(fetch, False)==Yes&#039;}}&#039;&#039;&#039;: เมื่อข้อมูลถูกfetch(ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2116</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2116"/>
		<updated>2025-05-22T06:25:27Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;if request.args.get(fetch, False)==Yes&#039;}}&#039;&#039;&#039;: เมื่อข้อมูลถูกfetch(ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2115</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2115"/>
		<updated>2025-05-22T06:22:14Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get(fetch, False)==&amp;quot;Yes&amp;quot;&#039;}}&#039;&#039;&#039;: เมื่อข้อมูลถูกfetch(ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2114</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2114"/>
		<updated>2025-05-22T06:21:52Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get(fetch, False)==Yes&#039;}}&#039;&#039;&#039;: เมื่อข้อมูลถูกfetch(ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2113</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2113"/>
		<updated>2025-05-22T06:21:15Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get(fetch, False)&#039;}}&#039;&#039;&#039;: เมื่อข้อมูลถูกfetch(ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2112</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2112"/>
		<updated>2025-05-22T06:12:56Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get(fetch, False)==Yes&#039;}}&#039;&#039;&#039;: เมื่อข้อมูลถูกfetch(ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2111</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2111"/>
		<updated>2025-05-22T06:12:13Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get(&#039;fetch&#039;, False)&#039;}}&#039;&#039;&#039;: เมื่อข้อมูลถูกfetch(ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2110</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2110"/>
		<updated>2025-05-22T06:09:43Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get(&#039;fetch&#039;, False)==&#039;Yes&#039;&#039;}}&#039;&#039;&#039;: เมื่อข้อมูลถูกfetch(ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2109</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2109"/>
		<updated>2025-05-22T06:06:09Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;&#039;}}&#039;&#039;&#039;: เมื่อข้อมูลถูกfetch(ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2108</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2108"/>
		<updated>2025-05-22T06:05:19Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039; if request.args&#039;}}&#039;&#039;&#039;: เมื่อข้อมูลถูกfetch(ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2107</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2107"/>
		<updated>2025-05-22T05:13:48Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะปุ่มแก้ไขใน Table Anime จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะปุ่มค้นหาใน Table Publisher จะทำการdimหรือไม่ &lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;suppress_copy&#039;}}&#039;&#039;&#039;: สถานะปุ่มคัดลอกใน Table Publisher จะทำการdimหรือไม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้าง database ตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039; if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;&#039;}}&#039;&#039;&#039;: เมื่อข้อมูลถูกfetch(ยังไม่ได้เข้าdata base)จะมีอยู่ 3 กรณี&lt;br /&gt;
**:1. &amp;quot;qsch&amp;quot; กรณีนำเข้าข้อมูลจากการค้นหา (ครั้งแรกที่มีการเปิดpageขึ้นมา จะต้องเรียกข้อมูลทั้งหมดมาใส่ในtable)&lt;br /&gt;
**:2. &amp;quot;ncol&amp;quot; กรณีเพิ่มข้อมูลขึ้นบันทักใหม่&lt;br /&gt;
**:3. &amp;quot;sel&amp;quot; กรณีเลือกข้อมูล&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2106</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2106"/>
		<updated>2025-05-22T04:14:22Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีลัด */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะการปล่อยให้มีการค้นหาในtableนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะการเปิดให้มีการแก้ไข้ตารางนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: สดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้างdatabaseตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy=False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2105</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2105"/>
		<updated>2025-05-22T04:13:57Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีลัด */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะการปล่อยให้มีการค้นหาในtableนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะการเปิดให้มีการแก้ไข้ตารางนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: สดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้างdatabaseตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
suppress_copy&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
hide ปุ่มแก้ไขเอาไว้(ทำให้ปุ่มแก้ไขเป็นสีเทาๆไม่สมารถกดได้)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2104</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2104"/>
		<updated>2025-05-22T03:22:38Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีลัด */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะการปล่อยให้มีการค้นหาในtableนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะการเปิดให้มีการแก้ไข้ตารางนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: สดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้างdatabaseตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ is_submit=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2103</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2103"/>
		<updated>2025-05-22T03:05:01Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีลัด */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะการปล่อยให้มีการค้นหาในtableนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะการเปิดให้มีการแก้ไข้ตารางนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: สดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้างdatabaseตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง โดยโค้ดอีกชุดนึง(ขั้นตอนในการวิธีคิดเหมือนกัน )แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ fetch=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2102</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2102"/>
		<updated>2025-05-22T02:52:38Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะการปล่อยให้มีการค้นหาในtableนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะการเปิดให้มีการแก้ไข้ตารางนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: สดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้างdatabaseตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table ที่จะแสดงบนหน้าจอ สามารถเพิ่ม Obj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ fetch=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2101</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2101"/>
		<updated>2025-05-22T02:50:56Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะการปล่อยให้มีการค้นหาในtableนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะการเปิดให้มีการแก้ไข้ตารางนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: สดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้างdatabaseตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เก็บ Obj Table สามารถเพิ่มObj Table ได้มากกว่า 1 Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ fetch=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2100</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2100"/>
		<updated>2025-05-22T02:29:03Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะการปล่อยให้มีการค้นหาในtableนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะการเปิดให้มีการแก้ไข้ตารางนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argument ที่1: สดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argument ที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argument ที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้างdatabaseตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เป็นการเพิ่มTableอื่นเข้ามาใช้งานร่วมกัน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ fetch=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2099</id>
		<title>Quick Start for Developers</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=Quick_Start_for_Developers&amp;diff=2099"/>
		<updated>2025-05-22T02:25:22Z</updated>

		<summary type="html">&lt;p&gt;Noina: /* วิธีตรง */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Start here&lt;br /&gt;
&lt;br /&gt;
== สร้าง Table - Database ==&lt;br /&gt;
เป็นหน้าที่ทั้งหน้ามี table อย่างเดียวดังในภาพ&lt;br /&gt;
&amp;lt;image1&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
* สิ่งของที่จำเป็นในการสร้างมี&lt;br /&gt;
** สร้างดาต้าเบส: จะถูกเขียนอยู่ใน Model.py&lt;br /&gt;
** สร้างองค์ประกอบหน้าตาราง(ตารางต้องมีรูปร่างหน้าตาอย่างไร ต้องโชว์คอลัมน์อะไรบ้าง): จะถูกเขียนอยู่ใน Teble.py&lt;br /&gt;
** สร้างหน้าHTML: จะถูกเขียนอยู่ใน HTML.py&lt;br /&gt;
** สร้างท่องที่เชื่อมระหว่าง UX-UI เราจะเรียกท่อนนี้ว่า rount: จะถูกเขียนอยู่ใน rounts.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
โดยไฟล์ที่จำเป็นมีดังนี้&lt;br /&gt;
=== Model.py ===&lt;br /&gt;
Model.py จะเป็นตัวกำหนดโครงสร้างดาต้าเบส โดยชื่อคาสจะเอาไปตั้งเป็นชื่อตารางดาต้าเบส และตัวแปรแต่ละตัวเปรียบเสมือนfield ที่จะต้องกำหนดชนิดตัวแปรเข้าไป (สามารถไปดูวิธีการสร้างModelแบบละเอียดได้ที่[[cunei#...]])&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime(CuneiModel):&lt;br /&gt;
    id = AutoIncrementField()&lt;br /&gt;
    stid = IntegerField()&lt;br /&gt;
    code = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    name = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    type = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    Publisher = CharField(default=&amp;quot;&amp;quot;)&lt;br /&gt;
    writer = CharField(default=&amp;quot;&amp;quot;, null=True)&lt;br /&gt;
    class Meta:&lt;br /&gt;
        database = SqliteExtDatabase(None)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;AutoIncrementField()&#039;}}&#039;&#039;&#039;: กำหนดให้มีรันตัวเลขอัตโนมัติ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;null&#039;}}&#039;&#039;&#039;: กำหนดให้databaseสามารถเว้นว่างได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SqliteExtDatabase&#039;}}&#039;&#039;&#039;: เปิดdatabase&lt;br /&gt;
*กำหนดชนิดของข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่เป็นจำนวนเต็ม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;CharField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;DateField()&#039;}}&#039;&#039;&#039;: ?&lt;br /&gt;
&lt;br /&gt;
=== Table.py ===&lt;br /&gt;
ออกแบบรูปร่างหน้าตาตัวตาราง เพื่อที่จะเอาข้อมูลที่สร้างไว้ในดาตาเบสมาลง ทั้งนี้สามารถกำหนดความกว้างคอลัมน์เป็น0ได้ หากไม่ต้องการให้ผู้ใช้เห็น และสามารถกำหนดคอลัมน์เพิ่มเติมจากAttributeที่มีอยู่ในดาต้าเบสได้ (Attributeที่มีอยู่ในดาต้าเบสต้องนำมาสร้างใส่คอลัมน์ให้หมด และสามารถสร้างคอลัมน์ในตารางเพิ่มนอกเหนือจากAttributeที่มีอยู่ในดาตาเบสได้)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Anime_table(CuneiTable):&lt;br /&gt;
    MASTER_colsizes = [1,3,10,10,0,7,7,7]&lt;br /&gt;
    MASTER_colnames = [&amp;quot;stid&amp;quot;, &amp;quot;code&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;publisher_stid&amp;quot;, &lt;br /&gt;
                        &amp;quot;publisher_code&amp;quot;, &amp;quot;publisher_name&amp;quot;, &amp;quot;writer&amp;quot;]&lt;br /&gt;
    MASTER_coltypes = [&amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;sel&amp;quot;, &amp;quot;int&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;, &amp;quot;str&amp;quot;]&lt;br /&gt;
    MASTER_choicecols = [&amp;quot;type&amp;quot;]&lt;br /&gt;
    MASTER_choices = [[(&amp;quot;Comedy&amp;quot;, &amp;quot;Comedy&amp;quot;), (&amp;quot;Action&amp;quot;, &amp;quot;Action&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Fiction&amp;quot;, &amp;quot;Fiction&amp;quot;), (&amp;quot;Fantasy&amp;quot;, &amp;quot;Fantasy&amp;quot;), &lt;br /&gt;
                        (&amp;quot;Adventure&amp;quot;, &amp;quot;Adventure&amp;quot;)]]&lt;br /&gt;
    MASTER_schfill = {&amp;quot;publisher_code&amp;quot;:[&amp;quot;ModalPublisher:code&amp;quot;, &lt;br /&gt;
                                        &amp;quot;publisher_stid:stid,publisher_name:name&amp;quot;]}&lt;br /&gt;
&lt;br /&gt;
    class SubForm(FlaskForm, CuneiSubForm):&lt;br /&gt;
        stid = StringField(&amp;quot;&amp;quot;)&lt;br /&gt;
        code = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        name = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        type = SelectField(&amp;quot;&amp;quot;)&lt;br /&gt;
        publisher_stid = StringField(&amp;quot;Publisher StID&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))], &lt;br /&gt;
                        render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        publisher_code = StringField(&amp;quot;Publisher Code&amp;quot;, &lt;br /&gt;
                        validators=[InputRequired(lazy_gettext(&amp;quot;Required!&amp;quot;))])&lt;br /&gt;
        publisher_name = StringField(&amp;quot;Publisher Name&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
        writer = StringField(&amp;quot;&amp;quot;, validators=[InputRequired(&amp;quot;Required!&amp;quot;)])&lt;br /&gt;
        def validate_writer(self, writer):&lt;br /&gt;
            if len(writer.data) &amp;lt;= 1:&lt;br /&gt;
                raise ValidationError(lazy_gettext(&amp;quot;Very short&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและตัวแปร ====&lt;br /&gt;
*คำสั่งในการใช้งาน สามารถเข้าไปดูวิธีสร้างตารางแบบละเอียดได้ที่ [[CuneiTable#Define]]&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colsizes&#039;}}&#039;&#039;&#039;: ความกว้างของช่องข้อมมูล(ทุกคอลัมน์ที่อยู่ในdatabaseต้องมีช่องข้อมูลเป็นของตัวเองทั้งหมด แต่สามารถใส่ค่าเป็น 0 ได้ หากไม่อยากให้ผู้ใช้เห็น)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_colnames&#039;}}&#039;&#039;&#039;: หัวคอลัมน์ที่ผู้ใช้เห็น(ไม่จำเป็นต้องตรงกับที่อยู่ในdatabase)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_coltypes&#039;}}&#039;&#039;&#039;: ชนิดของช่องข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choicecols&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะทำเป็นDrop Drown&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_choices&#039;}}&#039;&#039;&#039;: ข้อมูลที่อยู่ใน Choices&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;MASTER_schfill&#039;}}&#039;&#039;&#039;: กำหนดช่องข้อมูลที่จะใช้ค้นหาโดยการขึ้นหน้าต่างใหม่&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;class SubForm&#039;}}&#039;&#039;&#039;: เป็นเรื่องของ Form กรุณาไปดูที่ [[CuneiForm#Define]]&lt;br /&gt;
=== rounts.py ===&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
มีส่วนประกอบที่สำคัญดังนี้&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms with context %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;layout.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content %}&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content %}&lt;br /&gt;
&lt;br /&gt;
{% block jvs %}&lt;br /&gt;
{% endblock jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block content/endblock content&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่แสดงเนื้อหา ในที่นี้เนื้อหาจะเป็นการแสดง Table&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiTables.general_table_block(table, block_height) }}&lt;br /&gt;
{{ CuneiTables.general_table_tail(table) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เป็นวิธีสร้าง Table แบบมารตราฐาน&lt;br /&gt;
* &#039;&#039;&#039;{{code|lang=python|&#039;block jvs/endblock jvs&#039;}}&#039;&#039;&#039;: เปิด/ปิดส่วนที่การแสดงเนื้อหาjavascript&lt;br /&gt;
&lt;br /&gt;
=== routes.py ===&lt;br /&gt;
==== วิธีตรง ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
table = Anime_Table(prefix=&amp;quot;anime_table&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.test_table&amp;quot;, is_submit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    publisher_tb = Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, searchable=True, editable=True,&lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;),&lt;br /&gt;
                perm_bit=4)&lt;br /&gt;
    table.sch_tbs = [publisher_tb]&lt;br /&gt;
&lt;br /&gt;
    dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;anime.db&amp;quot;)&lt;br /&gt;
    db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
    if request.args.get(&amp;quot;fetch&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;qsch&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) &lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;ncol&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
        if request.form.get(&amp;quot;mode&amp;quot;) == &amp;quot;sel&amp;quot;:&lt;br /&gt;
            return jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]})&lt;br /&gt;
    if request.args.get(&amp;quot;is_submit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        dbpath = path.join(session[&amp;quot;company&amp;quot;][&amp;quot;datadir&amp;quot;], &amp;quot;table&amp;quot;, &amp;quot;publisher.db&amp;quot;)&lt;br /&gt;
        db = SqliteExtDatabase(dbpath, pragmas={&amp;quot;journal_mode&amp;quot;:&amp;quot;wal&amp;quot;})&lt;br /&gt;
        model_fields = Publisher._meta.fields.keys()&lt;br /&gt;
        vals = {cn:getattr(table.form, cn).data for cn in table.cnames if cn in model_fields}&lt;br /&gt;
        vals.pop(&amp;quot;id&amp;quot;, None)&lt;br /&gt;
        isid = int(table.form.id.data)&lt;br /&gt;
        isdel = table.form.is_del.data&lt;br /&gt;
        with db.bind_ctx([Publisher]):&lt;br /&gt;
            if isdel:          // delete case&lt;br /&gt;
                qry = Publisher.delete().where(Publisher.id==isid).execute()&lt;br /&gt;
                return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=&amp;quot;deleted&amp;quot;))&lt;br /&gt;
            elif isid == -1:   // add case&lt;br /&gt;
                new_entry = Publisher.create(**vals)&lt;br /&gt;
            else:              // edit case&lt;br /&gt;
                try:&lt;br /&gt;
                    new_entry = Publisher.select().where(Publisher.id==isid)&lt;br /&gt;
                except DoesNotExist:&lt;br /&gt;
                    new_entry = Publisher.create(**vals)&lt;br /&gt;
                else:&lt;br /&gt;
                    for k,v in vals.items():&lt;br /&gt;
                        setattr(new_entry, k, v)&lt;br /&gt;
                    new_entry.save()&lt;br /&gt;
            return_entry = [getattr(new_entry, cn, None) for cn in table.cnames]&lt;br /&gt;
        return jsonify(dict(data=&amp;quot;success&amp;quot;, flash_messages=[], entry=return_entry))&lt;br /&gt;
    else:&lt;br /&gt;
        return jsonify(dict(err=table.form.errors, flash_messages=[]))&lt;br /&gt;
&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/anime_table.html&amp;quot;, table=table)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* ตัวแปร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;prefix&#039;}}&#039;&#039;&#039;: ชื่อที่ใช้ตั้งเป็นIDของTable (ต้องตั้งชื่อไฟล์HTMLเป็นชื่อนี้ด้วย)&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;perm_bit&#039;}}&#039;&#039;&#039;: สิทธิ์ในการเข้าถึงหน้านี้&lt;br /&gt;
**:- 4 สามารถ เพิ่ม/แก้ไข/ลบ&lt;br /&gt;
**:- 3 สามารถ เพิ่ม/แก้ไข&lt;br /&gt;
**:- 2 สามารถ เพิ่ม&lt;br /&gt;
**:- 1 สามารถ ดูได้เพียงอย่างเดียว&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;searchable&#039;}}&#039;&#039;&#039;: สถานะการปล่อยให้มีการค้นหาในtableนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;editable&#039;}}&#039;&#039;&#039;: สถานะการเปิดให้มีการแก้ไข้ตารางนี้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;populate_route&#039;}}&#039;&#039;&#039;: เปิดให้มีการrefetchหน้าใหม่ &lt;br /&gt;
**:- argumentที่1: สดงถึงหน้าที่ต้องการให้มีการrefetch&lt;br /&gt;
**:- argumentที่2: เป็นคำสั่งยืนยันการrefetch&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;post_route&#039;}}&#039;&#039;&#039;: เรียกใช้mode Submit บันทึกลงdatabase&lt;br /&gt;
**:- argumentที่1: แสดงถึงหน้าที่ต้องการให้มีการบันทึก&lt;br /&gt;
**:- argumentที่2: เป็นคำสั่งยืนยันการบันทึก&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;in_modal&#039;}}&#039;&#039;&#039;: Tableนี้ใช้โครงสร้างdatabaseตัวไหน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;modal_head&#039;}}&#039;&#039;&#039;: ชื่อที่จะอยู่บนหัวpopup&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.form&#039;}}&#039;&#039;&#039;: เป็น Obj form ที่เก็บ field ทั้งหมดในหน้านี้ไว้ และใน field ก็จะเก็ยdataอีกที&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;getattr(x,y).data&#039;}}&#039;&#039;&#039;: ดึงข้อมูลจาก Obj มาใช้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;setattr&#039;}}&#039;&#039;&#039;: วิธีบันทึกของลงในObj&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;table.cnames&#039;}}&#039;&#039;&#039;: เก็บชื่อคอลัมน์ที่มีทั้งหมดของdatabase + &#039;submit&#039;(สถานะการบันทึก), &#039;del_submit&#039;(เป็นปุ่มที่เมื่อกดมันจะไปบังคับติ๊๊กถูกที่is_delอีกที)และ &#039;is_del&#039;(สภานะการลบ)&lt;br /&gt;
&lt;br /&gt;
*ขยายcode&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;publisher_tb = ...&amp;lt;/syntaxhighlight&amp;gt;เป็นการเพิ่มTableอื่นเข้ามาใช้งานร่วมกัน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;request.arge.get()&amp;lt;/syntaxhighlight&amp;gt;sectionทำงานอยู่ 2 แบบคือ&lt;br /&gt;
**:- fetch : จะทำงานทุกครั้งที่มีการreload หน้า(ทุกการreloadจะมีการดึงข้อมูลใหม่ทุกครั้ง)&lt;br /&gt;
**:- is_submit : จะทำงานก็ต่อเมื่อมีการบึนทึกของลงdatabase&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;if request.form.get(&amp;quot;mode&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;โหมดในการทำงานมีทั้งหมด 4 โหมด คือ&lt;br /&gt;
**:- sch : โหมดการค้นหาข้อมูล กรณีกดปุ่มค้นหา สามารถreturnได้  2 แบบ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx], &amp;quot;qs_status&amp;quot;:&amp;quot;success&amp;quot;}) คือ returnผลลัพธ์ที่มีตัวเดียว&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx],...]}) คือ returnผลลัพธ์ที่มีหลายตัว&lt;br /&gt;
**:- ncol : โหมดใส่ค่าเริ่มต้นตามdatabaseนั้นๆ&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- sel : โหมดการเลือกบรรทัด&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
**:- grab : โหมดการค้นหาข้อมูล กรณีที่co-database นำstidไปหาค่า&lt;br /&gt;
**:::- &#039;&#039;&#039;{{code|lang=python|return}}&#039;&#039;&#039; jsonify({&amp;quot;data&amp;quot;:[&#039;code&#039;:xxxxx, &#039;name&#039;:xxxx]}) คือ returnผลลัพธ์ที่มี&lt;br /&gt;
&lt;br /&gt;
==== วิธีลัด ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/anime&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def anime():&lt;br /&gt;
    table = Anime_Table(prefix=&amp;quot;test_table&amp;quot;, suppress_copy=False, editable=True)&lt;br /&gt;
    table.sch_tbs = [Publisher_Table(prefix=&amp;quot;PublisherTable&amp;quot;, perm_bit=4, editable=True,&lt;br /&gt;
                        populate_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, fetch=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        post_route=url_for(&amp;quot;cunei_pos.publisher&amp;quot;, is_submit=&amp;quot;yes&amp;quot;),&lt;br /&gt;
                        in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&lt;br /&gt;
    dbtype, tbname = &amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;&lt;br /&gt;
    model, module = Anime, &amp;quot;cunei_pos&amp;quot;&lt;br /&gt;
    new_default = get_default_anime&lt;br /&gt;
    fetch_all = anime_grab_all&lt;br /&gt;
    return single_tb_page(dbtype, tbname, model, module, table, new_default, fetch_all, request, forced_perm=4, in_modal=&amp;quot;ModalPublisher&amp;quot;, modal_head=lazy_gettext(&amp;quot;Choose Publisher&amp;quot;))]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
วิธีนี้จะช่วยลดขั้นตอนต่างๆให้สั้นลง แต่ขั้นตอนไม่ได้หายไปไหนเพียงแค่ย่อมันให้สั้นลงเท่านั้น&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
 table = Anime_Table(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Seach Publisher_Table จะถูกเขียนลงไปใน table.sch_tbs และเพิ่ม argument fetch=&amp;quot;yes&amp;quot; และ fetch=&amp;quot;yes&amp;quot;เข้าไป&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
new_default = get_default_anime&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผล default กลับมา โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def get_default_anime():&lt;br /&gt;
    return dict(stid=get_next_stid(&amp;quot;Anime&amp;quot;, Anime), id=-1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
fetch_all = anime_grab_all&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
เป็นfunction Obj ที่จะคืนผลการselect โดยปกติแล้วจะเขียนฟังชั่นก์นี้ในไฟล์ functions.py&lt;br /&gt;
::&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
def anime_grab_all(qsch_spec={}):&lt;br /&gt;
    tb_db = get_db(&amp;quot;table&amp;quot;, &amp;quot;anime&amp;quot;, auto_create=[Anime])&lt;br /&gt;
    crits = get_where(Anime, qsch_spec)&lt;br /&gt;
    with tb_db.bind_ctx([Anime]):&lt;br /&gt;
        if len(crits) == 0:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code))&lt;br /&gt;
        else:&lt;br /&gt;
            return Anime.select().order_by(fn.LOWER(Anime.code)).where(*crits)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - non Database ==&lt;br /&gt;
เป็นหน้าที่แสดง Form อย่างเดียว โดยไม่มีการบันทึกของลงdatabase&lt;br /&gt;
&amp;lt;image2&amp;gt;&lt;br /&gt;
โดยต้องเตรียมไฟล์ดังนี้&lt;br /&gt;
=== Form.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
class Foreigner_Form(FlaskForm, CuneiForm):&lt;br /&gt;
    id = StringField(&amp;quot;ID&amp;quot;)&lt;br /&gt;
    passport = StringField(lazy_gettext(&amp;quot;Passport&amp;quot;), &lt;br /&gt;
                validators=[Length(8,8,lazy_gettext(&amp;quot;Wrong passport number&amp;quot;))])&lt;br /&gt;
    first_name = StringField(lazy_gettext(&amp;quot;First Name&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Who the fack are you&amp;quot;))])&lt;br /&gt;
    middle_name = StringField(lazy_gettext(&amp;quot;Middle Name&amp;quot;))&lt;br /&gt;
    last_name = StringField(lazy_gettext(&amp;quot;Last Name&amp;quot;))&lt;br /&gt;
    birthday = StringField(lazy_gettext(&amp;quot;Birthday&amp;quot;), &lt;br /&gt;
                validators=[InputRequired(lazy_gettext(&amp;quot;Birthday la?&amp;quot;))])&lt;br /&gt;
    saving = StringField(lazy_gettext(&amp;quot;Saving&amp;quot;))&lt;br /&gt;
    gender = RadioField(lazy_gettext(&amp;quot;Gender&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;male&amp;quot;, lazy_gettext(&amp;quot;Male&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;female&amp;quot;, lazy_gettext(&amp;quot;Female&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;other&amp;quot;, lazy_gettext(&amp;quot;Other&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;male&amp;quot;)&lt;br /&gt;
    status = RadioField(lazy_gettext(&amp;quot;status&amp;quot;), &lt;br /&gt;
                        choices=[(&amp;quot;single&amp;quot;, lazy_gettext(&amp;quot;Single&amp;quot;)), &lt;br /&gt;
                            (&amp;quot;widow&amp;quot;, lazy_gettext(&amp;quot;Widowed&amp;quot;)),&lt;br /&gt;
                            (&amp;quot;married&amp;quot;, lazy_gettext(&amp;quot;Married&amp;quot;))], &lt;br /&gt;
                        default=&amp;quot;single&amp;quot;)&lt;br /&gt;
    spouse_first_name = StringField(lazy_gettext(&amp;quot;Spouse first name&amp;quot;))&lt;br /&gt;
    spouse_middle_name = StringField(lazy_gettext(&amp;quot;Spouse middle name&amp;quot;))&lt;br /&gt;
    spouse_last_name = StringField(lazy_gettext(&amp;quot;Spouse last name&amp;quot;))&lt;br /&gt;
    address = TextAreaField(lazy_gettext(&amp;quot;Address&amp;quot;))&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def validate_spouse_first_name(self, spouse_first_name):&lt;br /&gt;
        if self.status.data == &amp;quot;married&amp;quot; and spouse_first_name.data == &amp;quot;&amp;quot;:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;What is your spouse&#039;s name&amp;quot;))&lt;br /&gt;
    def validate_saving(self, saving):&lt;br /&gt;
        try:&lt;br /&gt;
            test_money = float(saving.data)&lt;br /&gt;
        except (TypeError, ValueError):&lt;br /&gt;
            test_money = 0.0&lt;br /&gt;
        if test_money &amp;lt; 80000.0:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;Eww! Peasant!&amp;quot;))&lt;br /&gt;
    def validate_birthday(self, birthday):&lt;br /&gt;
        bth = date_from_dbstr(birthday.data)&lt;br /&gt;
        if bth &amp;gt; datetime.now():&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You are embryo&amp;quot;))&lt;br /&gt;
        if datetime.now().year - bth.year &amp;gt;150:&lt;br /&gt;
            raise ValidationError(lazy_gettext(&amp;quot;You&#039;re really old&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
สร้าง filedที่ ต้องการใช้ในหน้า Form นี้ขึ้นมา พร้อมทั้งกำหนดชนิดของตัวแปร&lt;br /&gt;
==== ฟังก์ชั่นการใช้งานและชนิดช้อมูล ====&lt;br /&gt;
*คำสั่งในการใช้งาน&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;lazy_gettext&#039;}}&#039;&#039;&#039;: แปรช่องนี้ให้เป็นภาษาที่มนุยษ์เข้าใจ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;validators&#039;}}&#039;&#039;&#039;: สร้างเงื่อนไขให้กับช่องเช่น วันที่ที่กรอกต้อง ไม่น้อยกว่าหรือมากกว่าเท่านี้นะ&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;InputRequired&#039;}}&#039;&#039;&#039;: แจ้งErrorหากไม่ผ่านเงือนไขที่ให้&lt;br /&gt;
&lt;br /&gt;
*ตัวแปรและชนิดข้อมูล&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;StringField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษร&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;TextField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดที่เป็นตัวอักษรและช่องข้อความขยายได้&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;IntegerField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลข&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FloatField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดตัวเลขที่จุดทศนิยม&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;BoolField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดTrue/False&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;RadioField()&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดติ๊กถูก&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;choices&#039;}}&#039;&#039;&#039;: ตัวเลือกของ RadioField&lt;br /&gt;
*** &#039;&#039;&#039;{{code|lang=python|&#039;default&#039;}}&#039;&#039;&#039;: ค่าเริ่มต้นของ RadioField&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;FileField&#039;}}&#039;&#039;&#039;: ตัวแปรชนิดไฟล์&lt;br /&gt;
** &#039;&#039;&#039;{{code|lang=python|&#039;SubmitField&#039;}}&#039;&#039;&#039;: ตัวแปรสร้างปุ่มของ Form นั้นๆ&lt;br /&gt;
&lt;br /&gt;
*ขยาย Code&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    pict = FileField(lazy_gettext(&amp;quot;Photo&amp;quot;))&lt;br /&gt;
    pict_isdel = BoolField(&amp;quot;Pict: isdel&amp;quot;, render_kw={&amp;quot;readonly&amp;quot;:&amp;quot;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เรื่องการใส่รูปกรุณาไปดูรายละเอียดได้ที่ [[CuneiForm#File_&amp;amp;_Image_Fields]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    submit = SubmitField(&amp;quot;Submit&amp;quot;)&lt;br /&gt;
    del_submit = SubmitField(&amp;quot;Delete&amp;quot;)&lt;br /&gt;
    is_del = BoolField(&amp;quot;is_del&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็นการสร้างปุ่ม Submit และ Delete ส่วน is_del เป็น check box ที่ไม่ได้เปิดให้เห็น ทุกครั้งที่กดปุ่ม Delete check box จะเปลี่ยนเป็น true โดยทันที ระบบข้างในจะทำงานกับ check boxตัวนี้แทนปุ่ม Delete เพราะว่าปุ่ม Submit และปุ่ม Delete ไม่สามารถใช้งานภายในFormเดียวกันได้ จึงต้องมีcheck boxมารับค่าแทน&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
MASTER_sptypes = [(&amp;quot;id&amp;quot;, &amp;quot;int&amp;quot;), (&amp;quot;birthday&amp;quot;, &amp;quot;date&amp;quot;), (&amp;quot;saving&amp;quot;, &amp;quot;amt&amp;quot;), &lt;br /&gt;
                        (&amp;quot;pict&amp;quot;, [&amp;quot;img&amp;quot;, &amp;quot;table&amp;quot;, &amp;quot;foreigner&amp;quot;])]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; แปลงชนิดตัวแปรก่อนเอาเข้า database, จาก field ที่โชว์อยู่บนหน้าจอ field พวกนี้จะเป็นตัวแปรชนิด String ทั้งหมด เพราะอย่างนั้นเวลาจะบันทึกเข้า database จึงต้องแปลงชนิดตัวแปรสะก่อน &lt;br /&gt;
*** ชนิดตัวแปรที่เป็นตัวเลข &lt;br /&gt;
****int: เลขจำนวนเต็ม&lt;br /&gt;
****amt: ตัวเลขระบุที่เกี่ยวกับยอดเงิน&lt;br /&gt;
****acc: ตัวเลขที่ไว้ลงบัญชี&lt;br /&gt;
****pct: จำนวนที่เป็นพวกร้อนละ/เปอร์เซ็น&lt;br /&gt;
****qty: ตัวเลขที่เกี่ยวกับจำนวน/หน่วย&lt;br /&gt;
สามารถไปอ่านเพิ่มเติมได้ที่ [[CuneiForm#Available_Types]]&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    def validate_spouse_first_name(...)&lt;br /&gt;
    def validate_saving(...)&lt;br /&gt;
    def validate_birthday(...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; เป็น function สร้างเงื่อนไขให้กับ field เช่น วันที่ที่กรอกต้องไม่น้อยกว่าหรือมากกว่าเท่านี้นะ โดยวิธีการตั้งชื่อให้ใส่ validate ไว้ข้างหน้าแล้วตามชื่อ _ชื่อ field ที่ต้องการสร้างเงื่อนไขให้ แล้วส่ง argument selfและชื่อfieldมาด้วย&lt;br /&gt;
&lt;br /&gt;
=== HTML.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{% import &amp;quot;cunei_forms.html&amp;quot; as CuneiForms %}&lt;br /&gt;
{% import &amp;quot;cunei_tables.html&amp;quot; as CuneiTables with context %}&lt;br /&gt;
{% import &amp;quot;cunei_modals.html&amp;quot; as CuneiModals with context %}&lt;br /&gt;
{% import &amp;quot;cunei_scripts.html&amp;quot; as CuneiScripts %}&lt;br /&gt;
&lt;br /&gt;
{% extends &amp;quot;greeter_slim.html&amp;quot; %}&lt;br /&gt;
&lt;br /&gt;
{% block content_wgreeter %}&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-sm-11&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;card border-dark mb-3&amp;quot; style=&amp;quot;max-width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card-body py-0&amp;quot;&amp;gt;&lt;br /&gt;
            {{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
            &amp;lt;div class=&amp;quot;row align-items-start pt-3&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg-2&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;{{ form.pict.id }}_imgbox&amp;quot; &lt;br /&gt;
                            style=&amp;quot;width:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_check(form, form.pict_isdel, hidden=true) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_upload(form, form.pict) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;col-lg&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        {{ CuneiForms.render_blank(form, form.id, hidden=false) }}&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.passport) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-4&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.birthday) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.saving) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, form.gender, &lt;br /&gt;
                            col=3, force_slim=true, label_width=&amp;quot;105px&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-5&amp;quot;&amp;gt;{{ CuneiForms.render_radio(form, &lt;br /&gt;
                            form.status, col=3, force_slim=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_first_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_middle_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.spouse_last_name) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;{{ CuneiForms.render_blank(form, &lt;br /&gt;
                            form.address) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;row align-items-start&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_check&lt;br /&gt;
                            (form, form.is_del, hidden=true) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.del_submit, class=&amp;quot;danger&amp;quot;) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                        &amp;lt;div class=&amp;quot;col-0 text-right&amp;quot;&amp;gt;{{ CuneiForms.render_submit&lt;br /&gt;
                            (form, form.submit) }}&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&lt;br /&gt;
{% endblock content_wgreeter %}&lt;br /&gt;
&lt;br /&gt;
{% block greeter_jvs %}&lt;br /&gt;
{% endblock greeter_jvs %}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ขยายCode&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.general_form_head(form, is_master=true) }}&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
.&lt;br /&gt;
{{ CuneiForms.general_form_tail(form, true, pack_del=true) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;เปิด/ปิดส่วนของform ทึกข่องข้อมูลของฟอร์มต้องอยู่ระหว่าง 2 บรรทัดนี้&lt;br /&gt;
**&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
{{ CuneiForms.render_upload(form, form.pict) }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rount.py ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
@cunei_pos.route(&amp;quot;/foreigner&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])&lt;br /&gt;
def foreigner():&lt;br /&gt;
    form = Foreigner_Form.init_form(prefix=&amp;quot;foreigner_form&amp;quot;, &lt;br /&gt;
                populate_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, fetch=&amp;quot;yes&amp;quot;), &lt;br /&gt;
                populate_id=[&amp;quot;passport&amp;quot;],&lt;br /&gt;
                post_route=url_for(&amp;quot;cunei_pos.foreigner_form&amp;quot;, issubmit=&amp;quot;yes&amp;quot;))&lt;br /&gt;
    if request.args.get(&amp;quot;issubmit&amp;quot;, False) == &amp;quot;yes&amp;quot;:&lt;br /&gt;
        msg = &amp;quot;&amp;quot;&lt;br /&gt;
        flashers = []&lt;br /&gt;
        if form.validate_on_submit():&lt;br /&gt;
            gender = &amp;quot;Woman&amp;quot; if new_entry.gender == &amp;quot;female&amp;quot; else &amp;quot;Man&amp;quot;&lt;br /&gt;
            msg = &amp;quot;welcome to Thailand&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;success&amp;quot;]&lt;br /&gt;
            data = &amp;quot;success&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            msg = &amp;quot;Go to jail&amp;quot;+ new_entry.first_name + gender&lt;br /&gt;
            sh = [msg, &amp;quot;danger&amp;quot;]&lt;br /&gt;
            data = &amp;quot;failure&amp;quot;&lt;br /&gt;
        flashers.append(sh)&lt;br /&gt;
        return jsonify(dict(data=data,err=form.errors,flash_messages=flashers))&lt;br /&gt;
    form.id.data = 1&lt;br /&gt;
    return render_template(&amp;quot;cunei_pos/foreigner.html, form=form&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ตัวแปร ====&lt;br /&gt;
.......&lt;br /&gt;
&lt;br /&gt;
เมื่อถึงตรงนี้ Form ที่คุณทำจะสามารถ&lt;br /&gt;
:- กรอกข้อมูลเข้าได้&lt;br /&gt;
:- จับ Error ได้&lt;br /&gt;
แต่ไม่สามารถ&lt;br /&gt;
:- บันทึกข้อมูลเข้า database ได้ เพราะไม่ได้สร้าง databaseไว้&lt;br /&gt;
:- เรียกดูข้อมูล&lt;br /&gt;
&lt;br /&gt;
== สร้าง Form - Database ==&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
	<entry>
		<id>http://wiki.cuneifox.com/index.php?title=%E0%B8%9C%E0%B8%B9%E0%B9%89%E0%B9%83%E0%B8%8A%E0%B9%89:Noina&amp;diff=2098</id>
		<title>ผู้ใช้:Noina</title>
		<link rel="alternate" type="text/html" href="http://wiki.cuneifox.com/index.php?title=%E0%B8%9C%E0%B8%B9%E0%B9%89%E0%B9%83%E0%B8%8A%E0%B9%89:Noina&amp;diff=2098"/>
		<updated>2025-05-21T07:12:38Z</updated>

		<summary type="html">&lt;p&gt;Noina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p&amp;gt;&#039;&#039;&#039;Username:&#039;&#039;&#039; NOINA&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&#039;&#039;&#039;E-mail:&#039;&#039;&#039; wisetporn.sompong@gmail.com&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&#039;&#039;&#039;Password:&#039;&#039;&#039; 一号明月光&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Noina</name></author>
	</entry>
</feed>