# filter_horizontal 水平过滤 # 下拉框下的数据变多时,我们在多选的时候,就会麻烦; # 做一个与django-admin中的将选中的数据,移至右侧框中的功能; # ManyToManyField自动生成的是多选框;Select; # 前端获取filter_horizontal属性下的值,判断后生成对应的Select框; # 1.获取左侧选框内容,字段对应的所有数据; # 根据外键concult_courses字段名获取表名; # >> c1 = models.objects.last() # 单个查询对象|记录 # >> c1_field_obj = c1._meta.get_field(‘consult_courses‘) # 对象的指定外键字段 # >> c1_field_obj.rel.to # 获取到外键字段对应的表的类 # <class ‘crm.models.Course‘> # >> c1_field_obj.rel.to.objects.all() # 获取外键字段对应表的所有对象查询集 # # >> 或者:cc1_field_obj.related_model # <QuerySet [<Course:python全栈>,<Course:运维自动化>]> # 在页面展示m2m外键对应表的所有数据 # table_obj_common.html <div class="col-sm-10"> {% if field.name in admin_class.filter_horizontal %} <!-- 如果在filter_horizontal内,自定义输出框,两个水平的select框 --> <div class="col-lg-5"> <select multiple> <!-- as 起别名,赋给变量 --> {% get_available_m2m_data field.name admin_class as available_obj%} {% for obj in available_obj %} <option value="{{ obj.id }}">{{ obj }}</option> {% endfor %} </select> </div> {% else %} {{ field }} {% endif %} <span style="color:red">{{ field.errors.0 }}</span> </div> # kingadmin_tag.py # m2m多选框左侧选项 @register.simple_tag def get_available_m2m_data(field_name,admin_class): """获取多对多字段关联表的所有数据""" field_obj = admin_class.model._meta.get_field(field_name) obj_list = field_obj.related_model.objects.all() return obj_list # 注意:在django 1.8版本中自定义标签赋值,是通过@register.assignment_tag这个装饰器来完成的; # 在django 1.9版本中自定义标签simple_tag直接将assignment_tag的功能合并了; # 2.获取右侧选框内容,即当前所选字段; # table_obj_common.html <div class="col-lg-4"> <select multiple> {% get_selected_m2m_data field.name form_obj admin_class as get_selected_m2m_data %} {% for obj in get_selected_m2m_data %} <option value="{{ obj.id }}">{{ obj }}</option> {% endfor %} </select> </div> # kingadmin_tag.py @register.simple_tag def get_selected_m2m_data(field_name,form_obj,admin_class): """返回m2m已选数据""" selected_data = getattr(form_obj.instance,field_name).all() return selected_data # 问题:怎么去掉左侧已经被选到右侧的字段; # 措施:通过集合的差集操作; # >> c1 = models.objects.last() # 单个查询对象|记录 # >> s1 = set(getattr(c1,‘consult_courses‘).all()) # >> s2 = set(models.Course.objects.all()) # >> s2-s1 # 取得差集 # kingadmin_tag.py # m2m多选框左侧选项 @register.simple_tag def get_available_m2m_data(field_name,form_obj,admin_class): """获取多对多字段关联表的所有数据""" field_obj = admin_class.model._meta.get_field(field_name) # 左侧数据 obj_list = set(field_obj.related_model.objects.all()) # 右侧显示数据 selected_data = set(getattr(form_obj.instance,field_name).all()) return obj_list-selected_data # 3.左侧双击事件,点击之后展示上面的状态; 通过js来做; # 略!