如何在Odoo中使用Domain和Context?含OpenEduCat具体场景需求
Hey there! Let's tackle your two Odoo/OpenEduCat questions step by step—they’re both common customization needs, so I’ll break them down clearly.
First, let’s cover the basics of these two core Odoo concepts, since they’re key to solving your second problem too.
Domain: Filtering Records
Domain is Odoo’s built-in way to filter which records are displayed or retrieved. It’s structured as a list of tuples, where each tuple follows the format (field_name, operator, value).
Key Examples of Domain Syntax
- Simple filter: Show only active courses
[('active', '=', True)] - Multiple conditions (use
&for AND,|for OR,!for NOT):
Show draft courses with an enrollment count over 10[('state', '=', 'draft'), '&', ('enrollment_count', '>', 10)]
Where to Use Domain
- In Views: Add a
domainattribute to fields or filters in XML views. For example, restrict a course dropdown to active courses in the student form:<field name="course_id" domain="[('active', '=', True)]"/> - In Actions: Define a menu action that opens a pre-filtered list. For example, a menu item for English students:
<act_window id="action_english_students" name="English Students" res_model="student.student" view_mode="tree,form" domain="[('course_id.name', '=', 'English')]"/> - In Python Code: Use domain when searching for records programmatically:
english_students = self.env['student.student'].search([('course_id.name', '=', 'English')])
Context: Passing Extra Contextual Data
Context is a dictionary that lets you pass additional parameters between views, actions, and models. It’s perfect for setting defaults, controlling view behavior, or dynamically filtering fields.
Common Context Use Cases
- Set Default Values: When creating a new student from a course page, auto-select the current course:
<button name="%(action_create_student)d" string="Add Student" type="action" context="{'default_course_id': active_id}"/> - Control View Behavior: Pass a context to auto-apply a filter in the student list:
return { 'type': 'ir.actions.act_window', 'res_model': 'student.student', 'context': {'search_default_course_id': self.id} } - Access Context in Python: Retrieve context values in your model methods:
current_course_id = self.env.context.get('active_id')
Now, let’s solve your business scenario: clicking a course (from students.course) to open a list of students enrolled in that course. I’ll assume your student model is student.student with a course_id field linking to students.course (adjust names if your setup uses many2many, like course_ids).
Step 1: Add a "View Students" Button to the Course Form
First, edit the students.course form view to add a button that triggers the action. In your module’s XML file:
<record id="inherit_course_form" model="ir.ui.view"> <field name="name">students.course.form.inherit</field> <field name="model">students.course</field> <field name="inherit_id" ref="openeducat_core.students_course_form_view"/> <!-- Use the base OpenEduCat view ID --> <field name="arch" type="xml"> <!-- Insert the button after existing action buttons --> <xpath expr="//div[@class='oe_button_box']" position="inside"> <button name="action_view_enrolled_students" string="View Enrolled Students" type="object" class="oe_highlight"/> </xpath> </field> </record>
Step 2: Define the Python Method for the Button
Next, add a method to the students.course model that returns the filtered student list action. In your module’s Python file:
from odoo import models, api class StudentsCourse(models.Model): _inherit = 'students.course' def action_view_enrolled_students(self): self.ensure_one() # Make sure we're working with a single course record # Filter students enrolled in this course domain = [('course_id', '=', self.id)] # If using many2many, use: domain = [('course_ids', 'in', self.id)] # Prepare the action with context to pre-filter and set defaults return { 'type': 'ir.actions.act_window', 'name': f'Students in {self.name}', 'res_model': 'student.student', 'view_mode': 'tree,form', 'domain': domain, 'context': { 'search_default_course_id': self.id, 'default_course_id': self.id }, 'target': 'current' # Open in the same window; use 'new' for a popup }
Step 3: Optional: Add a Quick Filter for Students
If you want users to quickly filter students by course directly in the student list, add a filter to the student tree view:
<record id="inherit_student_tree" model="ir.ui.view"> <field name="name">student.student.tree.inherit</field> <field name="model">student.student</field> <field name="inherit_id" ref="openeducat_core.student_student_tree_view"/> <field name="arch" type="xml"> <xpath expr="//search" position="inside"> <filter name="filter_by_course" string="Filter by Course" domain="[]" context="{'group_by': 'course_id'}"/> <!-- Add a specific filter for English if needed --> <filter name="filter_english_students" string="English Students" domain="[('course_id.name', '=', 'English')]"/> </xpath> </field> </record>
That’s it! Now when you click the "View Enrolled Students" button on any course, it’ll open a pre-filtered list of students registered for that course.
内容的提问来源于stack exchange,提问作者majid

