Your Name hace 2 meses
padre
commit
7bc9a6660e

+ 4 - 0
cat_app/__init__.py

@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+
+from . import controllers
+from . import models

+ 43 - 0
cat_app/__manifest__.py

@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+{
+    'name': "cat_app",
+
+    'summary': """
+        Short (1 phrase/line) summary of the module's purpose, used as
+        subtitle on modules listing or apps.openerp.com""",
+
+    'description': """
+        Long description of module's purpose
+    """,
+
+    'author': "zzry",
+    'website': "http://www.yourcompany.com",
+
+    # Categories can be used to filter modules in modules listing
+    # Check https://github.com/odoo/odoo/blob/15.0/odoo/addons/base/data/ir_module_category_data.xml
+    # for the full list
+    'category': 'Uncategorized',
+    'version': '0.1',
+
+    # any module necessary for this one to work correctly
+    'depends': ['base'],
+
+    # always loaded
+    'data': [
+        # 'security/ir.model.access.csv',
+        'views/views.xml',
+        'views/templates.xml',
+        "security/library_security.xml",
+        'security/ir.model.access.csv',
+        'views/library_menu.xml',
+    ],
+    # only loaded in demonstration mode
+    'demo': [
+        'demo/demo.xml',
+    ],
+    #是否可安装(设置为False则前端无法搜索到)
+    'installable': True,
+    #是否自动安装(在depends参数的模块都安装完成之后,自动安装本模块)
+    'auto_install': False,
+    'application': True,  # 如果是应用,设置为 True
+}

BIN
cat_app/__pycache__/__init__.cpython-38.pyc


+ 3 - 0
cat_app/controllers/__init__.py

@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import controllers

BIN
cat_app/controllers/__pycache__/__init__.cpython-38.pyc


BIN
cat_app/controllers/__pycache__/controllers.cpython-38.pyc


+ 21 - 0
cat_app/controllers/controllers.py

@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# from odoo import http
+
+
+# class CatApp(http.Controller):
+#     @http.route('/cat_app/cat_app', auth='public')
+#     def index(self, **kw):
+#         return "Hello, world"
+
+#     @http.route('/cat_app/cat_app/objects', auth='public')
+#     def list(self, **kw):
+#         return http.request.render('cat_app.listing', {
+#             'root': '/cat_app/cat_app',
+#             'objects': http.request.env['cat_app.cat_app'].search([]),
+#         })
+
+#     @http.route('/cat_app/cat_app/objects/<model("cat_app.cat_app"):obj>', auth='public')
+#     def object(self, obj, **kw):
+#         return http.request.render('cat_app.object', {
+#             'object': obj
+#         })

+ 30 - 0
cat_app/demo/demo.xml

@@ -0,0 +1,30 @@
+<odoo>
+    <data>
+<!--
+          <record id="object0" model="cat_app.cat_app">
+            <field name="name">Object 0</field>
+            <field name="value">0</field>
+          </record>
+
+          <record id="object1" model="cat_app.cat_app">
+            <field name="name">Object 1</field>
+            <field name="value">10</field>
+          </record>
+
+          <record id="object2" model="cat_app.cat_app">
+            <field name="name">Object 2</field>
+            <field name="value">20</field>
+          </record>
+
+          <record id="object3" model="cat_app.cat_app">
+            <field name="name">Object 3</field>
+            <field name="value">30</field>
+          </record>
+
+          <record id="object4" model="cat_app.cat_app">
+            <field name="name">Object 4</field>
+            <field name="value">40</field>
+          </record>
+-->
+    </data>
+</odoo>

+ 0 - 0
cat_app/master


+ 4 - 0
cat_app/models/__init__.py

@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+
+from . import models
+from . import library_book

BIN
cat_app/models/__pycache__/__init__.cpython-38.pyc


BIN
cat_app/models/__pycache__/models.cpython-38.pyc


+ 29 - 0
cat_app/models/library_book.py

@@ -0,0 +1,29 @@
+from odoo import fields, models
+
+
+"""
+odoo会自动为模型添加一些特殊字段:
+- id: 主键,自动生成
+- create_uid: 创建者的用户ID
+- create_date: 创建时间
+- write_uid: 最后修改者的用户ID
+- write_date: 最后修改时间
+- display_name: 显示名称,通常是name字段的值
+- __last_update:一个计算字段 ,不在数据库中存储,用于做并发检测
+"""
+class Book(models.Model):
+    # UID,仅模型名用点号.分隔关键词
+    _name = 'library.book'
+    # 模型记录显示名
+    _description = 'Book'
+    # 以下声明模型字段
+    # name和active均为特殊字段名。默认对Odoo有特殊用途。
+    # name默认用作记录显示名,在另一个模型引用它时显示。active字段用于在用户界面中过滤掉无效记录。
+    name = fields.Char('Title', required=True)
+    isbn = fields.Char('ISBN')
+    active = fields.Boolean('Active?', default=True)
+    date_published = fields.Date()
+    image = fields.Binary('Cover')
+    # Many2one表示一对多关系,Many2many表示多对多关系
+    publisher_id = fields.Many2one('res.partner', string='Publisher')
+    author_ids = fields.Many2many('res.partner', string='Authors')

+ 18 - 0
cat_app/models/models.py

@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+
+# from odoo import models, fields, api
+
+
+# class cat_app(models.Model):
+#     _name = 'cat_app.cat_app'
+#     _description = 'cat_app.cat_app'
+
+#     name = fields.Char()
+#     value = fields.Integer()
+#     value2 = fields.Float(compute="_value_pc", store=True)
+#     description = fields.Text()
+#
+#     @api.depends('value')
+#     def _value_pc(self):
+#         for record in self:
+#             record.value2 = float(record.value) / 100

+ 13 - 0
cat_app/models/my_model.py

@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+
+from odoo import models, fields, api#后续继承使用,或者直接调用时使用的api
+
+class My_HomePage(models.Model):
+    _name = 'cats'#类的唯一标识字段,
+    #其他类可以通过此字段引用本类,不能使用大写,
+    #在模块安装升级之后,会在数据库生成cats数据表
+    
+    _description = 'HomePage'#类似于标签,提高查询
+
+    name = fields.Char(string="名称")#模型的字段
+    code = fields.Char(string="编号")

+ 3 - 0
cat_app/security/ir.model.access.csv

@@ -0,0 +1,3 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_book_user,BookUser,model_library_book,library_group_user,1,1,1,0
+access_book_manager,BookManager,model_library_book,library_group_manager,1,1,1,1

+ 43 - 0
cat_app/security/library_security.xml

@@ -0,0 +1,43 @@
+<odoo>
+    <data>
+        <!-- Library User Group -->
+        <!--id:用户组的外部标识符。用于在代码中引用这个用户组
+        model:用户组模型。用于指定记录属于哪个模型-->
+        <record id="library_group_user" model="res.groups">
+            <!--name:用户组名称,显示在odoo用户界面中-->
+            <field name="name">User</field>
+            <!--category_id:用户组所属分类,这里引用base.module_category_services_library-->
+            <field name="category_id" ref="base.module_category_services_library" />
+            <!--implied_ids:继承的用户组列表。这里表示该用户组继承了base.group_user组-->
+            <!--ref 是一个函数,用于引用外部标识符。
+            4 是一个操作码,表示“将记录添加到关联字段中”-->
+            <field name="implied_ids" eval="[(4, ref('base.group_user'))]" />
+        </record>
+
+         <!-- Library Manager Group -->
+        <record id="library_group_manager" model="res.groups">
+            <field name="name">Manager</field>
+            <field name="category_id" ref="base.module_category_services_library" />
+            <field name="implied_ids" eval="[(4, ref('library_group_user'))]" />
+            <!--users:定义用户组的用户-->
+            <field name="users" 
+                   eval="[(4, ref('base.user_root')), 
+                   (4, ref('base.user_admin'))]" />
+        </record>
+    </data>
+
+    <!--记录规则位于<data noupdate="1">元素中,表示这些记录在安装模块时会被创建,但在模块更新时不会重写。-->
+    <data noupdate="1">
+        <!--ir.rule记录规则模型-->
+        <record id="book_user_rule" model="ir.rule">
+            <field name="name">Library Book User Access</field>
+            <field name="model_id" ref="model_library_book" />
+            <!--domain_force:定义一个域,用于指定哪些记录对用户可见-->
+            <field name="domain_force">
+                [('active','=',True)]
+            </field>
+            <!--groups:指定哪些用户组可以访问这些记录-->
+            <field name="groups" eval="[(4,ref('library_group_user'))]" />
+        </record>
+    </data>
+</odoo>

BIN
cat_app/static/description/icon.png


+ 1 - 0
cat_app/tests/__init__.py

@@ -0,0 +1 @@
+from . import test_book

+ 22 - 0
cat_app/tests/test_book.py

@@ -0,0 +1,22 @@
+from odoo.tests.common import TransactionCase
+# TransactionCase 类是 Odoo 提供的用于编写测试用例的基类。
+class TestBook(TransactionCase):
+    def setUp(self, *args, **kwargs):
+        super().setUp(*args, **kwargs)
+        
+        # 访问权限
+        user_admin = self.env.ref('base.user_admin')
+        self.env = self.env(user=user_admin)
+
+        self.Book = self.env['library.book']
+        self.book1 = self.Book.create({
+            "name": "Odoo Development Essentials",
+            "isbn": "879-1-78439-279-6"
+        })
+    def test_book_create(self):
+        "New Books are active by default"
+        self.assertEqual(self.book1.active, True)
+
+    def test_check_isbn(self):
+        "Check valid ISBN"
+        self.assertTrue(self.book1._check_isbn)

+ 89 - 0
cat_app/views/Cats_HomePage.xml

@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<odoo>
+    <data>
+    	<!--编写视图,命名规范模型+view+视图名称-->
+        <record id="my_cats_view_form" model="ir.ui.view">
+            <field name="name">管理系统</field><!--视图的名称-->
+            <field name="model">cats</field><!--视图所用的模板-->
+            <field name="arch" type="xml"><!--在此标签内,添加视图-->
+                <form><!--form视图,内容写在此标签里-->
+                    <header><!--标题-->
+                    </header>
+                    <sheet><!--页标签,可以不加,此是为了美观-->
+                        <group><!--将我们所呈现的数据放入此标签内-->
+                            <field name="name"/><!--在模行中定义的两个字段-->
+                            <field name="code"/>
+                        </group>
+                    </sheet>
+                </form>
+            </field>
+        </record>
+		
+		<!--我们发现,tree视图前面三行于from视图差别不大,
+		直到tree标签才开始有所变化,
+		相比之下的search视图也仅仅是标签的变动,
+		来告诉odoo,你需要的是那一个视图-->
+        <record id="my_cats_view_tree" model="ir.ui.view">
+            <field name="name">管理系统</field>
+            <field name="model">cats</field>
+            <field name="arch" type="xml">
+                <tree>
+                    <field name="name"/>
+                    <field name="code"/>
+                </tree>
+            </field>
+        </record>
+
+		<!--from/tree/search是最普通,也是最常见的视图-->
+        <record id="my_cats_view_search" model="ir.ui.view">
+            <field name="name">管理系统</field>
+            <field name="model">cats</field>
+            <field name="arch" type="xml">
+                <search>
+                    <field name="name"/>
+                    <field name="code"/>
+                </search>
+            </field>
+        </record>
+
+		<!---在创建完视图后,我们开始创建动作,
+		命名规范: 模型+action-->
+        <record id="my_cats_action" model="ir.actions.act_window">
+            <field name="name">管理系统</field><!--动作的名称-->
+            <field name="type">ir.actions.act_window</field><!--固定写法-->
+            <field name="res_model">cats</field><!--使用模型-->
+            <field name="view_mode">tree,form</field><!--使用的视图-->
+            <field name="domain">[]</field><!--一些限制-->
+            <field name="context">{}</field>
+            <field name="search_view_id" ref="my_cats_view_search"/>
+            <!--以上代码调用刚刚定义的search视图,
+            name值为固定写法,
+            ref值填写我们定义的search视图的ID-->
+        </record>
+
+		<!--当我们写完视图和动作后,就开始写主(父级)菜单,写法如下
+		命名规范:模型+menu_root,
+		web_icon:图标
+		sequence为菜单排序的优先级,可以改着试试效果
+		其他参数暂时不变动
+		在odoo中,代表应用菜单中的名称,可以在主菜单中找到该名称命名的模块
+		-->
+        <menuitem name="猫猫管理系统2.0" id="my_cats_menu_root" sequence="50" groups="base.group_user"
+                  web_icon="fcwz_manufacture_manage,static/description/icon.png"/>
+
+		<!--我们在父级菜单下挂一个子级菜单
+		action为动作ID
+		name为动作名称
+		parent为挂靠的父级菜单ID
+		sequence为排序的优先级
+		在odoo中,代表应用菜单下的子菜单名称,一个主菜单可以挂多个子菜单,子菜单同样也可以继续再挂其他菜单
+		-->
+        <menuitem action="my_cats_action"
+                  id="menu_my_cats"
+                  name="猫猫管理系统"
+                  parent="my_cats_menu_root"
+                  sequence="21"
+        />
+
+    </data>
+</odoo>

+ 19 - 0
cat_app/views/book_view.xml

@@ -0,0 +1,19 @@
+<odoo>
+    <record id="view_form_book" model="ir.ui.view">
+        <field name="name">Book Form</field>
+        <field name="model">library.book</field>
+        <field name="arch" type="xml">
+            <form string="Book">
+                <group>
+                    <field name="name" />
+                    <field name="author_ids" widget="many2many_tags" />
+                    <field name="publisher_id" />
+                    <field name="date_published" />
+                    <field name="isbn" />
+                    <field name="active" />
+                    <field name="image" widget="image" />
+                </group>
+            </form>
+        </field>
+    </record>
+</odoo>

+ 15 - 0
cat_app/views/library_menu.xml

@@ -0,0 +1,15 @@
+<odoo>
+    <!-- Library App Menu -->
+    <menuitem id="menu_library" name="Library" />
+    <!-- 打开图书列表的动作 -->
+    <record id="action_library_book" model="ir.actions.act_window">
+        <field name="name">Library Books</field>
+        <field name="res_model">library.book</field>
+        <field name="view_mode">tree,form</field>
+    </record>
+    <!-- 打开图书列表的菜单 -->
+    <menuitem id="menu_library_book"
+              name="Books"
+              parent="menu_library"
+              action="action_library_book" />
+</odoo>

+ 24 - 0
cat_app/views/templates.xml

@@ -0,0 +1,24 @@
+<odoo>
+    <data>
+<!--
+        <template id="listing">
+          <ul>
+            <li t-foreach="objects" t-as="object">
+              <a t-attf-href="#{ root }/objects/#{ object.id }">
+                <t t-esc="object.display_name"/>
+              </a>
+            </li>
+          </ul>
+        </template>
+        <template id="object">
+          <h1><t t-esc="object.display_name"/></h1>
+          <dl>
+            <t t-foreach="object._fields" t-as="field">
+              <dt><t t-esc="field"/></dt>
+              <dd><t t-esc="object[field]"/></dd>
+            </t>
+          </dl>
+        </template>
+-->
+    </data>
+</odoo>

+ 60 - 0
cat_app/views/views.xml

@@ -0,0 +1,60 @@
+<odoo>
+  <data>
+    <!-- explicit list view definition -->
+<!--
+    <record model="ir.ui.view" id="cat_app.list">
+      <field name="name">cat_app list</field>
+      <field name="model">cat_app.cat_app</field>
+      <field name="arch" type="xml">
+        <tree>
+          <field name="name"/>
+          <field name="value"/>
+          <field name="value2"/>
+        </tree>
+      </field>
+    </record>
+-->
+
+    <!-- actions opening views on models -->
+<!--
+    <record model="ir.actions.act_window" id="cat_app.action_window">
+      <field name="name">cat_app window</field>
+      <field name="res_model">cat_app.cat_app</field>
+      <field name="view_mode">tree,form</field>
+    </record>
+-->
+
+    <!-- server action to the one above -->
+<!--
+    <record model="ir.actions.server" id="cat_app.action_server">
+      <field name="name">cat_app server</field>
+      <field name="model_id" ref="model_cat_app_cat_app"/>
+      <field name="state">code</field>
+      <field name="code">
+        action = {
+          "type": "ir.actions.act_window",
+          "view_mode": "tree,form",
+          "res_model": model._name,
+        }
+      </field>
+    </record>
+-->
+
+    <!-- Top menu item -->
+<!--
+    <menuitem name="cat_app" id="cat_app.menu_root"/>
+-->
+    <!-- menu categories -->
+<!--
+    <menuitem name="Menu 1" id="cat_app.menu_1" parent="cat_app.menu_root"/>
+    <menuitem name="Menu 2" id="cat_app.menu_2" parent="cat_app.menu_root"/>
+-->
+    <!-- actions -->
+<!--
+    <menuitem name="List" id="cat_app.menu_1_list" parent="cat_app.menu_1"
+              action="cat_app.action_window"/>
+    <menuitem name="Server to list" id="cat_app" parent="cat_app.menu_2"
+              action="cat_app.action_server"/>
+-->
+  </data>
+</odoo>