[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-d38a14fd-86cc-4367-b493-5f0b7944fc6a":3,"$fD_o7lclddpfE6CWTIELDrwDiYLomClJU0lURp1ZG3bo":43},{"id":4,"title":5,"description":6,"categoryId":7,"moduleId":8,"tags":9,"prompt":10,"icon":11,"source":12,"sourceUrl":13,"authorId":14,"authorName":15,"isPublic":16,"stars":17,"runs":18,"createdAt":19,"updatedAt":19,"module":20,"category":27,"packages":34},"d38a14fd-86cc-4367-b493-5f0b7944fc6a","odoo-orm-expert","精通Odoo ORM模式：搜索、浏览、创建、写入、域过滤器、计算字段以及性能安全的查询技术。","cat_life_career","mod_other","sickn33,other","---\nname: odoo-orm-expert\ndescription: \"Master Odoo ORM patterns: search, browse, create, write, domain filters, computed fields, and performance-safe query techniques.\"\nrisk: safe\nsource: \"self\"\n---\n\n# Odoo ORM Expert\n\n## Overview\n\nThis skill teaches you Odoo's Object Relational Mapper (ORM) in depth. It covers reading\u002Fwriting records, building domain filters, working with relational fields, and avoiding common performance pitfalls like N+1 queries.\n\n## When to Use This Skill\n\n- Writing `search()`, `browse()`, `create()`, `write()`, or `unlink()` calls.\n- Building complex domain filters for views or server actions.\n- Implementing computed, stored, and related fields.\n- Debugging slow queries or optimizing bulk operations.\n\n## How It Works\n\n1. **Activate**: Mention `@odoo-orm-expert` and describe what data operation you need.\n2. **Get Code**: Receive correct, idiomatic Odoo ORM code with explanations.\n3. **Optimize**: Ask for performance review on existing ORM code.\n\n## Examples\n\n### Example 1: Search with Domain Filters\n\n```python\n# Find all confirmed sale orders for a specific customer, created this year\nimport datetime\n\nstart_of_year = datetime.date.today().replace(month=1, day=1).strftime('%Y-%m-%d')\n\norders = self.env['sale.order'].search([\n    ('partner_id', '=', partner_id),\n    ('state', '=', 'sale'),\n    ('date_order', '>=', start_of_year),\n], order='date_order desc', limit=50)\n\n# Note: pass dates as 'YYYY-MM-DD' strings in domains,\n# NOT as fields.Date objects — the ORM serializes them correctly.\n```\n\n### Example 2: Computed Field\n\n```python\ntotal_order_count = fields.Integer(\n    string='Total Orders',\n    compute='_compute_total_order_count',\n    store=True\n)\n\n@api.depends('sale_order_ids')\ndef _compute_total_order_count(self):\n    for record in self:\n        record.total_order_count = len(record.sale_order_ids)\n```\n\n### Example 3: Safe Bulk Write (avoid N+1)\n\n```python\n# ✅ GOOD: One query for all records\npartners = self.env['res.partner'].search([('country_id', '=', False)])\npartners.write({'country_id': self.env.ref('base.us').id})\n\n# ❌ BAD: Triggers a separate query per record\nfor partner in partners:\n    partner.country_id = self.env.ref('base.us').id\n```\n\n## Best Practices\n\n- ✅ **Do:** Use `mapped()`, `filtered()`, and `sorted()` on recordsets instead of Python loops.\n- ✅ **Do:** Use `sudo()` sparingly and only when you understand the security implications.\n- ✅ **Do:** Prefer `search_count()` over `len(search(...))` when you only need a count.\n- ✅ **Do:** Use `with_context(...)` to pass context values cleanly rather than modifying `self.env.context` directly.\n- ❌ **Don't:** Call `search()` inside a loop — this is the #1 Odoo performance killer.\n- ❌ **Don't:** Use raw SQL unless absolutely necessary; use ORM for all standard operations.\n- ❌ **Don't:** Pass Python `datetime`\u002F`date` objects directly into domain tuples — always stringify them as `'YYYY-MM-DD'`.\n\n## Limitations\n\n- Does not cover **`cr.execute()` raw SQL** patterns in depth — use the Odoo performance tuner skill for SQL-level optimization.\n- **Stored computed fields** can cause significant write overhead at scale; this skill does not cover partitioning strategies.\n- Does not cover **transient models** (`models.TransientModel`) or wizard patterns.\n- ORM behavior can differ slightly between Odoo SaaS and On-Premise due to config overrides.\n","","imported","https:\u002F\u002Fgithub.com\u002Fsickn33\u002Fantigravity-awesome-skills","user_system_seed","SkillOPIC",true,51,889,"2026-05-16 13:32:14",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"其他","other","mdi-page-next-outline","其他类型Skill",5,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":32,"skillCount":33,"createdAt":26},"职场发展","career","mdi-briefcase-outline","面试准备、简历优化、职业规划",4,575,[35],{"id":36,"skillId":4,"version":37,"fileName":38,"fileSize":39,"filePath":40,"fileHash":41,"manifest":42,"createdAt":19},"664ff089-dbb0-4da0-9bf3-44f471c23db9","1.0.0","odoo-orm-expert.zip",1768,"uploads\u002Fskills\u002Fd38a14fd-86cc-4367-b493-5f0b7944fc6a\u002Fodoo-orm-expert.zip","1117a50d2973b2e68b994a065aa58d8035359afa85390eb1bb9d660745cefb8b","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":3403}]",{"code":44,"message":45,"data":46},200,"success",{"items":47,"stats":48,"page":51},[],{"averageRating":49,"totalRatings":49,"ratingCounts":50},0,[49,49,49,49,49],{"limit":52,"offset":49,"hasMore":53,"nextOffset":52,"ratedOnly":16},15,false]