Define module data

مهم

This tutorial is an extension of the Server framework 101 tutorial. Make sure you have completed it and use the estate module you have built as a base for the exercises in this tutorial.

انواع داده

دادهٔ اصلی (Master Data)

Master data is usually part of the technical or business requirements for the module. In other words, such data is often necessary for the module to work properly. This data will always be installed when installing the module.

We already met technical data previously since we have defined views and actions. Those are one kind of master data.

On top of technical data, business data can be defined, e.g. countries, currencies, units of measure, as well as complete country localization (legal reports, tax definitions, chart of account), and much more...

دادهٔ نمایشی

In addition to master data, which is required for a module to work properly, we can also provide data for demonstration purposes:

  • به نمایندگان فروش کمک کنید تا دموهای خود را سریعاً انجام دهند.

  • Have a set of working data for developers to test new features and see how these new features look with data they might not have added themselves.

  • آزمایش کنید که داده‌ها به‌درستی، بدون ایجاد خطا، بارگذاری می‌شوند.

  • بیشتر ویژگی‌ها را برای استفادهٔ سریع هنگام ایجاد یک پایگاه‌دادهٔ جدید پیکربندی کنید.

The database manager let you create databases with demo data. The same can be achieved via the command line with --with-demo.

$ ./odoo-bin -h
Usage: odoo-bin [options]

Options:
--version             show program's version number and exit
-h, --help            show this help message and exit

Common options:
  [...]
  --with-demo         install demo data in new databases
[...]

$ ./odoo-bin --addons-path=... -d new-db -i base --with-demo

اعلان داده

manifest

Reference: the documentation related to this topic can be found in Module Manifests.

Data is declared either in CSV or in XML. Each file containing data must be added in the manifest for them to be loaded.

The keys to use in the manifest to add new data are data for the master data and demo for the demo data. Both values should be a list of strings representing the relative paths to the files declaring the data.

Usually, demo data is in a demo folder, views and actions are in a views folder, security related data is in a security folder, and other data is in a data folder.

اگر درخت کاری شما به این شکل است:

estate
├── data
│   └── master_data.xml
├── demo
│   └── demo_data.xml
├── models
│   ├── *.py
│   └── __init__.py
├── security
│   └── ir.model.access.csv
├── views
│   └── estate_property_offer_views.xml
├── __init__.py
└── __manifest__.py

manifest شما باید به این شکل باشد:

# -*- coding: utf-8 -*-

{
    "name": "Real Estate",
    "depends": [
        ...
    ],
    "data": [
        "security/ir.model.access.csv",  # CSV and XML files are loaded at the same place
        "views/estate_property_offer_views.xml",  # Views are data too
        "data/master_data.xml",  # Split the data in multiple files depending on the model
    ],
    "demo": [
        "demo/demo_data.xml",
    ]
    "application": True,
}

CSV

Reference: the documentation related to this topic can be found in CSV data files.

The easiest way to declare simple data is by using the CSV format. This is however limited in terms of features: use it for long lists of simple models, but prefer XML otherwise.

id,field_a,field_b,related_id:id
id1,valueA1,valueB1,module.relatedid
id2,valueA2,valueB2,module.relatedid

نکته

Your IDE has probably an extension to have a syntax highlighting of the CSV files

Exercise

Add some standard Real Estate Property Types for the estate module: Residential, Commercial, Industrial and Land. These should always be installed.

XML

Reference: the documentation related to this topic can be found in Data Files.

When the data to create is more complex it can be useful, or even necessary, to do it in XML.

<odoo>
  <record id="id1" model="tutorial.example">
    <field name="field_a">valueA1</field>
    <field name="field_b">valueB1</field>
  </record>

  <record id="id2" model="tutorial.example">
    <field name="field_a">valueA2</field>
    <field name="field_b">valueB2</field>
  </record>
</odoo>

Exercise

مقداری دادهٔ نمایشی برای ماژول estate ایجاد کنید.

فیلد

مقادیر

مقادیر

name

Big Villa

Trailer home

state

جدید

لغو شده

description

یک ویلای زیبا و بزرگ

خانه در یک پارک تریلر

postcode

12345

54321

date_availability

2020-02-02

1970-01-01

expected_price

۱٬۶۰۰٬۰۰۰

100,000

selling_price

120,000

bedrooms

6

۱

living_area

100

10

facades

۴

۴

garage

True

False

garden

True

garden_area

100000

garden_orientation

جنوب

گسترش داده

During the Core Training, we saw in the Chapter 12: Inheritance chapter we could inherit (extend) an existing view. This was a special case of data extension: any data can be extended in a module.

When you are adding new fields to an existing model in a new module, you might want to populate those fields on the records created in the modules you are depending on. This is done by giving the xml_id of the record you want to extend. It won't replace it, in this case we will set the field_c to the given value for both records.

<odoo>
  <record id="id1" model="tutorial.example">
    <field name="field_c">valueC1</field>
  </record>

  <record id="id2" model="tutorial.example">
    <field name="field_c">valueC2</field>
  </record>
</odoo>

ref

Related fields can be set using the ref key. The value of that key is the xml_id of the record you want to link. Remember the xml_id is composed of the name of the module where the data is first declared, followed by a dot, followed by the id of the record (just the id works too if you are in the module declaring it).

<odoo>
  <record id="id1" model="tutorial.example">
    <field name="related_id" ref="module.relatedid"/>
  </record>
</odoo>

Exercise

مقداری پیشنهاد دادهٔ نمایشی برای املاکی که ایجاد کرده‌اید بسازید.

پیشنهادها را با استفاده از شرکای تعریف‌شده در base ایجاد کنید

شریک

Estate

قیمت

اعتبار

Azure Interior

Big Villa

10000

14

Azure Interior

Big Villa

1500000

14

Deco Addict

Big Villa

1500001

14

Exercise

Ensure both of your demo properties are created with their Property Type set to Residential.

eval

The value to assign to a field is not always a simple string and you might need to compute it. It can also be used to optimize the insertion of related values, or because a constraint forces you to add the related values in batch. See :Add X2many fields.

<odoo>
  <record id="id1" model="tutorial.example">
    <field name="year" eval="datetime.now().year+1"/>
  </record>
</odoo>

Exercise

The offers you added should always be in a date relative to the installation of the module.

function

ممکن است هنگام بارگذاری داده‌ها نیاز به اجرای کد python نیز داشته باشید.

<function model="tutorial.example" name="action_validate">
    <value eval="[ref('demo_invoice_1')]"/>
</function>

Exercise

یکی از پیشنهادهای دادهٔ نمایشی را با استفاده از دکمهٔ "Accept Offer" تأیید کنید. سایر پیشنهادها را رد کنید.

افزودن فیلدهای X2many

مرجع: مستندات مربوط به این موضوع را می‌توانید در Command بیابید.

اگر می‌خواهید دادهٔ مرتبط را در یک فیلد One2many یا Many2many اضافه کنید، می‌توانید این کار را با استفاده از متدهای Command انجام دهید.

<odoo>
  <record id="id1" model="tutorial.example">
    <field name="related_ids" eval="[
        Command.create({
            'name': 'My name',
        }),
        Command.create({
            'name': 'Your name',
        }),
        Command.link(ref('model.xml_id')),
    ]"/>
  </record>
</odoo>

Exercise

یک Property جدید ایجاد کنید، اما این بار با چند پیشنهاد که مستقیماً در فیلد One2many متصل به Offers ایجاد شده‌اند.

دسترسی به داده

هشدار

هرگز نباید به دادهٔ نمایشی خارج از اعلان دادهٔ نمایشی دسترسی پیدا کنید، حتی در تست‌ها.

روش‌های متعددی برای دسترسی به دادهٔ اصلی/نمایشی وجود دارد.

در کد python، می‌توانید از متد env.ref(self, xml_id, raise_if_not_found=True) استفاده کنید. این متد، recordset متصل به xml_id مشخص‌شده را برمی‌گرداند.

در XML، می‌توانید از کلید ref به این صورت استفاده کنید

<odoo>
  <record id="id1" model="tutorial.example">
    <field name="related_id" ref="module.relatedid"/>
  </record>
</odoo>

این متد ref را فراخوانی می‌کند و id رکورد بازگشتی را در فیلد related_id رکوردی از نوع tutorial.example با id id1 ذخیره می‌کند.

در CSV، عنوان ستون باید با :id یا /id پسوند بگیرد.

id,parent_id:id,name
"child1","module.parent","Name1"
"child2","module.parent","Name2"
"child3","module.parent","Name3"

In SQL, it is more complicated, see the advanced section.

هشدار

Data can always be deleted by the user. Always code defensively, taking this into account.

پیشرفته

XML id چیست؟

Because we don't want a column xml_id in every single SQL table of the database, we need a mechanism to store it. This is done with the ir.model.data model.

It contains the name of the record (the xml_id) along with the module in which it is defined, the model defining it, and the id of it.

بدون به‌روزرسانی

The records created with the noupdate flag won't be updated when upgrading the module that created them, but it will be created if it didn't exist yet.

توجه

odoo-bin -i module will bypass this setting and always load the data. But normally one shouldn't do this on a production database.

<odoo noupdate="1">
  <record id="id1" model="model">
    <field name="fieldA" eval="True"/>
  </record>
</odoo>

وارد کردن به‌عنوان SQL

In some cases, it makes sense to do the import directly in SQL. This is however discouraged as it bypasses all the features of the ORM, computed fields (including metadata) and python constraints.

توجه

Generally using raw SQL also bypasses ACLs and increases the risks of injections.

مرجع: Security in Odoo