stark组件(11):组合搜索
效果图:
新增函数和类
Option 获取字段的对象或元组 SearchGroupRow 封装数据,展示到前端 get_search_group 获取组合搜索的字段 get_search_group_condition 获取组合搜索的筛选条件
一、stark组件
import functools
from types import FunctionType from django import forms
from django.db.models import Q
from django.db.models import ForeignKey, ManyToManyField
from django.http import QueryDict
from django.urls import path
from django.utils.safestring import mark_safe
from django.shortcuts import HttpResponse, render, reverse, redirect from stark.utils.pagination import Pagination class StarkModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(StarkModelForm, self).__init__(*args, **kwargs)
# 统一给ModelForm生成字段添加样式
for name, field in self.fields.items():
field.widget.attrs['class'] = 'form-control' class SearchGroupRow(object):
def __init__(self, title, queryset_or_tutple, option, query_dict):
"""
:param title: 组合搜索的列名称
:param queryset_or_tutple:组合搜索关联获取到的数据
:param 配置,Option的对象
:param query_dict : request.GET
"""
self.title = title
self.queryset_or_tutple = queryset_or_tutple
self.option = option
self.query_dict = query_dict def __iter__(self):
yield '<div class="whole">'
yield self.title + ':'
yield '</div>'
yield '<div class="others">'
total_query_dict = self.query_dict.copy()
total_query_dict._mutable = True
origin_value_list = self.query_dict.getlist(self.option.field)
if not origin_value_list:
# 比如说:没有传递gender,那么就还是当前的url。不能写成井号,因为如果传递了department,gender的全部的url应该是?department=x
yield f'<a class="active" href="?{total_query_dict.urlencode()}">全部</a>'
else:
# 如果全部没有被选中,那么全部的url就是移除掉被选中字段后的url
total_query_dict.pop(self.option.field)
yield f'<a href="?{total_query_dict.urlencode()}">全部</a>' for item in self.queryset_or_tutple:
text = self.option.get_text(item)
value = str(self.option.get_values(item)) # 需要request.GET
# 获取组合搜索按钮文本背后对应的值
# QueryDict = {gender: ['1', ], depart: ['2', ]} gender=1&depart=2
# print(self.query_dict)
query_dict = self.query_dict.copy()
query_dict._mutable = True
# 如果url有参数,比如?gender=1,query_dict就会带着这个参数。下面给query_dict赋值的时候,如果字段是gender会把gender覆盖掉。
# 如果字段不是gender,就会变成加上这个字段,那部门来举例就会变成?gender=1&department=1
if not self.option.is_multi:
query_dict[self.option.field] = value if value in origin_value_list:
query_dict.pop(self.option.field) # gender=x移除,此url就会编程href="?",当再次点击的时候就等于取消选择了
yield f'<a class="active" href="?{query_dict.urlencode()}">{text}</a>'
else:
yield f'<a href="?{query_dict.urlencode()}">{text}</a>'
else:
multi_value_list = query_dict.getlist(self.option.field)
if value in multi_value_list:
multi_value_list.remove(value)
# 我们操作的是multi_value_list,query_dict并没有被修改,所以要把multi_value_dict的值赋给query_dict
query_dict.setlist(self.option.field, multi_value_list)
yield f'<a class="active" href="?{query_dict.urlencode()}">{text}</a>'
else:
multi_value_list.append(value)
query_dict.setlist(self.option.field, multi_value_list)
yield f'<a href="?{query_dict.urlencode()}">{text}</a>'
yield '</div>' class Option(object):
def __init__(self, field, is_multi=False, db_condition=None, text_func=None, value_func=None):
"""
:param field: 组合搜索关联的字段
:param is_multi: 是否支持多选
:param db_condition: 数据库关联查询时的条件
:param text_func: 此函数用于显示组合搜索的按钮页面文本
:param value_func: 此函数用于显示组合搜索的按钮值
"""
self.field = field
self.is_multi = is_multi
if not db_condition:
db_condition = {}
self.db_condition = db_condition
self.text_func = text_func
self.value_func = value_func
self.is_choice = False def get_db_condition(self, request, *args, **kwargs):
"""
获取筛选条件
:param request:
:param args:
:param kwargs:
:return:
"""
return self.db_condition def get_queryset_or_tuple(self, model_class, request, *args, **kwargs):
"""
根据字段去获取数据库关联的数据
:param model_class:
:param request:
:param args:
:param kwargs:
:return:
""" # 去自己对应的Model类中找到字段对象,例:web.UserInfo.department,web.UserInfo.gender
filed_object_or_tuple = model_class._meta.get_field(self.field)
title = filed_object_or_tuple.verbose_name
if isinstance(filed_object_or_tuple, ForeignKey) or isinstance(filed_object_or_tuple, ManyToManyField):
# FK和M2M,应该去获取其关联表中的数据
# django2用field_obj.related_model来获取model
# django1用field_obj.rel.model来获取model
db_condition = self.get_db_condition(request, *args, **kwargs)
return SearchGroupRow(title, filed_object_or_tuple.related_model.objects.filter(**db_condition), self,
request.GET)
else:
# 获取choice中的数据
self.is_choice = True
return SearchGroupRow(title, filed_object_or_tuple.choices, self, request.GET) def get_text(self, filed_object_or_tuple):
"""
获取文本函数
:param filed_object:
:return:
"""
if self.text_func:
return self.text_func(filed_object_or_tuple)
if self.is_choice:
return filed_object_or_tuple[1]
return str(filed_object_or_tuple) def get_values(self, filed_object_or_tuple):
"""
获取文本的值
:param filed_object_or_tuple:
:return:
"""
if self.value_func:
return self.value_func(filed_object_or_tuple)
if self.is_choice:
return filed_object_or_tuple[0]
return filed_object_or_tuple.pk def get_choice_text(title, field):
"""
对于Stark组件中定义列时,choice如果想要显示中文信息,调用此方法即可。
:param title: 希望页面显示的表头
:param field: 字段名称
:return:
""" def inner(self, obj=None, is_header=None, *args, **kwargs):
if is_header:
return title
method = f"get_{field}_display"
return getattr(obj, method)()
# GENDER_CHOICES = ((MALE, '男'),(FEMALE, '女'),)
# 对于choice字段,如果想获取获取第二个值,可以通过:对象.get_字段名_display() return inner class StarkHandler(object):
list_display = []
order_list = []
search_list = []
search_group = []
per_page_data = 10
has_add_btn = True
model_form_class = None
list_template = None
add_template = None
edit_template = None
delete_template = None
action_list = [] def __init__(self, site, model_class, prev):
self.site = site
self.model_class = model_class
self.prev = prev
self.request = None def display_checkbox(self, obj=None, is_header=None, *args, **kwargs):
"""
复选框
:param obj:
:param is_header:
:param args:
:param kwargs:
:return:
"""
if is_header:
return '选择'
return mark_safe(f'<input type="checkbox" name="pk" value="{obj.pk}" />') def display_edit(self, obj=None, is_header=None, *args, **kwargs):
"""
自定义页面显示的列(表头和内容)
:param obj:
:param is_header:
:return:
"""
if is_header:
return '编辑'
name = f'{self.site.namespace}:{self.get_edit_url_name}'
return mark_safe(f'<a href="{reverse(name, args=(obj.pk,))}">编辑</a>') def display_delete(self, obj=None, is_header=None, *args, **kwargs):
if is_header:
return '删除'
name = f'{self.site.namespace}:{self.get_delete_url_name}'
return mark_safe(f'<a href="{reverse(name, args=(obj.pk,))}">删除</a>') def get_list_display(self, request, *args, **kwargs):
"""
获取页面上应该显示的列,预留的自定义扩展,例如:以后根据用户的不同显示不同的列
:return:
"""
value = []
value.extend(self.list_display)
return value def get_search_list(self):
return self.search_list def get_add_btn(self, *args, **kwargs):
if self.has_add_btn:
return f'<a class="btn btn-primary" href="{self.reverse_add_url(*args, **kwargs)}">添加</a>' def get_model_form_class(self, request, *args, **kwargs):
if self.model_form_class:
return self.model_form_class class DynamicModelForm(StarkModelForm):
class Meta:
model = self.model_class
fields = '__all__' return DynamicModelForm def get_order_list(self):
return self.order_list or ['-id', ] def get_action_list(self):
return self.action_list def action_multi_delete(self, request, *args, **kwargs):
"""
批量删除(如果想要定制执行成功后的返回值,那么就为action函数设置返回值即可)
:param request:
:param args:
:param kwargs:
:return:
"""
pk_list = request.POST.getlist('pk')
self.model_class.objects.filter(id__in=pk_list).delete() action_multi_delete.text = '批量删除' def get_search_group(self):
return self.search_group def get_search_group_condition(self, request):
"""
获取组合搜索的条件
:param request:
:return:
"""
condition = {}
for option in self.get_search_group():
if option.is_multi:
values_list = request.GET.getlist(option.field)
if not values_list:
continue
condition[f'{option.field}__in'] = values_list
else:
values = request.GET.get(option.field)
if not values:
continue
condition[f'{option.field}'] = values
return condition def list_view(self, request, *args, **kwargs):
"""
列表页面
:param request:
:return:
""" # 1. 处理Action
action_list = self.get_action_list()
action_dict = {func.__name__: func.text for func in action_list}
if request.method == 'POST':
action_func_name = request.POST.get('action')
if action_func_name and action_func_name in action_dict:
action_response = getattr(self, action_func_name)(request, *args, **kwargs)
if action_response:
return action_response
# 2. 处理搜索
# 搜索列表写ORM语句,如:['name__contains','email__contains','id__gt','gender']
search_list = self.get_search_list()
search_value = request.GET.get('q', '')
conn = Q()
conn.connector = 'OR' # 通过or链接
if search_value:
for item in search_list:
conn.children.append((item, search_value)) # conn.children.append('name__contains','张三') # 3. 获取排序
order_list = self.get_order_list()
search_group_condition = self.get_search_group_condition(request) # 获取组合搜索的条件
queryset = self.model_class.objects.filter(conn).filter(**search_group_condition).order_by(*order_list) # 4. 分页处理
all_count = queryset.count()
query_params = request.GET.copy() # 深copy
query_params._mutable = True # query_params默认不可修改 pager = Pagination(
current_page=request.GET.get('page'),
all_count=all_count,
base_url=request.path_info,
query_params=query_params,
per_page_data=self.per_page_data,
)
data_list = queryset[pager.start:pager.end] # 5. 处理表格
list_display = self.get_list_display(request, *args, **kwargs) # 会优先调用UserInfoHandler里的get_list_display()方法。
# 5.1 处理表格的表头
header_list = []
if list_display:
for field_or_func in list_display:
if isinstance(field_or_func, FunctionType):
verbose_name = field_or_func(self, obj=None, is_header=True, *args, **kwargs)
else:
verbose_name = self.model_class._meta.get_field(field_or_func).verbose_name
header_list.append(verbose_name)
else:
header_list.append(self.model_class._meta.model_name) # 如果用户没有填写list_display,就显示表名 # 5.2 处理表的内容
body_list = []
for obj in data_list:
tr_list = []
if list_display:
for field_or_func in list_display:
if isinstance(field_or_func, FunctionType):
tr_list.append(field_or_func(self, obj, is_header=False, *args, **kwargs))
else:
tr_list.append(getattr(obj, field_or_func))
else:
tr_list.append(obj) # 如果用户没有填写list_display,就显示表对象,所以表类要定义__str__方法
body_list.append(tr_list) # 6. 添加按钮
add_btn = self.get_add_btn(*args, **kwargs) # 7. 组合搜索
search_group_row_list = [] # 放的是SearchGroupRow的对象
search_group = self.get_search_group()
for option_object in search_group:
queryset_or_tuple = option_object.get_queryset_or_tuple(self.model_class, request, *args, **kwargs)
search_group_row_list.append(queryset_or_tuple) context = {
'data_list': data_list,
'header_list': header_list,
'body_list': body_list,
'pager': pager,
'add_btn': add_btn,
'search_list': search_list,
'search_value': search_value,
'action_dict': action_dict,
'search_group_row_list': search_group_row_list,
} return render(request, self.list_template or 'stark/data_list.html', context) def save(self, form, is_update=False, *args, **kwargs):
"""
在使用ModelForm保存数据之前预留的钩子方法
:param form:
:param is_update:
:return:
"""
form.save() def add_view(self, request, *args, **kwargs):
"""
添加页面
:param request:
:return:
"""
model_form_class = self.get_model_form_class(request, *args, **kwargs)
if request.method == 'GET':
form = model_form_class()
return render(request, 'stark/change.html', {'form': form})
form = model_form_class(data=request.POST)
if form.is_valid():
self.save(form, False, *args, **kwargs)
# 在数据库保存成功后,跳转回列表页面(携带原来的参数)。
return redirect(self.reverse_list_url(*args, **kwargs))
return render(request, self.add_template or 'stark/change.html', {'form': form}) def edit_view(self, request, pk, *args, **kwargs):
"""
编辑页面
:param request:
:return:
"""
current_edit_object = self.model_class.objects.filter(pk=pk).first()
if not current_edit_object:
return HttpResponse('要修改的数据不存在,请重新选择')
model_form_class = self.get_model_form_class(request, *args, **kwargs)
if request.method == 'GET':
form = model_form_class(instance=current_edit_object)
return render(request, 'stark/change.html', {'form': form})
form = self.model_form_class(data=request.POST, instance=current_edit_object)
if form.is_valid:
self.save(form, True, *args, **kwargs)
# 在数据库保存成功后,跳转回列表页面(携带原来的参数)
return redirect(self.reverse_list_url(*args, **kwargs))
return render(request, 'stark/change.html', {'form': form}) def delete_view(self, request, pk, *args, **kwargs):
"""
删除页面
:param request:
:param pk:
:return:
"""
original_list_url = self.reverse_list_url(*args, **kwargs)
if request.method == 'GET':
return render(request, 'stark/delete.html', {'cancel': original_list_url})
self.model_class.objects.filter(pk=pk).delete()
return redirect(original_list_url) def get_url_name(self, params):
app_label, model_name = self.model_class._meta.app_label, self.model_class._meta.model_name
if self.prev:
return f'{app_label}_{model_name}_{self.prev}_{params}'
return f'{app_label}_{model_name}__{params}' @property
def get_list_url_name(self):
"""
获取列表页面URL的name
:return:
"""
return self.get_url_name('list') @property
def get_add_url_name(self):
"""
获取添加页面URL的name
:return:
"""
return self.get_url_name('add') @property
def get_edit_url_name(self):
"""
获取编辑页面URL的name
:return:
"""
return self.get_url_name('edit') @property
def get_delete_url_name(self):
"""
获取删除页面URL的name
:return:
"""
return self.get_url_name('delete') def reverse_common_url(self, name, *args, **kwargs):
"""
生成带有原搜索条件的URL
:param name: url
:param args:
:param kwargs:
:return:
"""
name = f'{self.site.namespace}:{name}'
base_url = reverse(name, args=args, kwargs=kwargs)
if not self.request.GET:
reverse_url = base_url
else:
params = self.request.GET.urlencode()
new_query_dict = QueryDict(mutable=True)
new_query_dict['_filter'] = params
reverse_url = f'{base_url}?{new_query_dict.urlencode()}'
return reverse_url def reverse_add_url(self, *args, **kwargs):
"""
带有原搜索条件的增加URL
:param args:
:param kwargs:
:return:
"""
return self.reverse_common_url(self.get_add_url_name, *args, **kwargs) def reverse_edit_url(self, *args, **kwargs):
"""
带有原搜索条件的编辑URL
:param args:
:param kwargs:
:return:
"""
return self.reverse_common_url(self.get_edit_url_name, *args, **kwargs) def reverse_delete_url(self, *args, **kwargs):
"""
带有原搜索条件的删除URL
:param args:
:param kwargs:
:return:
"""
return self.reverse_common_url(self.get_delete_url_name, *args, **kwargs) def reverse_list_url(self, *args, **kwargs):
name = f'{self.site.namespace}:{self.get_list_url_name}'
base_url = reverse(name, args=args, kwargs=kwargs)
params = self.request.GET.get('_filter')
if not params:
return base_url
return f'{base_url}?{params}' def wrapper(self, func):
"""
当每一个request请求进来的时候,把request赋值给类的数据属性self.request
:param func: request请求对应的视图函数
:return:
""" @functools.wraps(func) # 保留原函数的原信息,写装饰器建议写上这个。
def inner(request, *args, **kwargs):
self.request = request
return func(request, *args, **kwargs) return inner def get_urls(self):
patterns = [
path('list/', self.wrapper(self.list_view), name=self.get_list_url_name),
path('add/', self.wrapper(self.add_view), name=self.get_add_url_name),
path('edit/<int:pk>/', self.wrapper(self.edit_view), name=self.get_edit_url_name),
path('delete/<int:pk>/', self.wrapper(self.delete_view), name=self.get_delete_url_name),
] patterns.extend(self.extra_urls())
return patterns def extra_urls(self):
return [] class StarkSite(object):
def __init__(self):
self._registry = []
self.app_name = 'stark'
self.namespace = 'stark' def register(self, model_class, handler_class=None, prev=None):
"""
:param model_class: 是models中的数据库表对应的类。
:param handler_class: 处理请求的视图函数所在的类
:param prev: 生成URL的前缀
:return:
""" if not handler_class:
handler_class = StarkHandler
self._registry.append(
{'model_class': model_class, 'handler': handler_class(self, model_class, prev), 'prev': prev}) def get_urls(self):
patterns = []
for item in self._registry:
model_class = item['model_class']
handler = item['handler']
prev = item['prev']
app_name, model_name = model_class._meta.app_label, model_class._meta.model_name
if prev:
patterns.append(
path(f'{app_name}/{model_name}/{prev}/', (handler.get_urls(), None, None)))
else:
patterns.append(
path(f'{app_name}/{model_name}/', (handler.get_urls(), None, None))) return patterns @property
def urls(self):
return self.get_urls(), self.app_name, self.namespace site = StarkSite()
二、业务代码
from stark.bin.core import (site, StarkHandler, StarkModelForm,
get_choice_text, Option) from web import models class UserInfoModelForm(StarkModelForm):
class Meta:
model = models.UserInfo
fields = ['name', 'gender', 'classes', 'age', 'email'] class DepartmentHandler(StarkHandler):
list_display = ['title'] class UserInfoHandler(StarkHandler):
per_page_data = 5
order_list = ['gender']
model_form_class = UserInfoModelForm
search_list = ['name__contains', 'email__contains', ]
action_list = [StarkHandler.action_multi_delete, ]
search_group = [Option('gender', is_multi=True, ), Option('department', text_func=lambda x: x.title ), ]
list_display = [
StarkHandler.display_checkbox,
'name',
get_choice_text('性别', 'gender', ),
get_choice_text('班级', 'classes'),
'age', 'email', 'department',
StarkHandler.display_edit,
StarkHandler.display_delete,
] def save(self, form, is_update=False, *args, **kwargs):
form.instance.department_id = 1
form.save() site.register(models.Department, DepartmentHandler)
site.register(models.UserInfo, UserInfoHandler)
三、模板渲染
{% extends 'layout.html' %} {% block css %}
<link rel="stylesheet" href="">
{% endblock css %} {% block content %}
<div class="custom-container"> <!-- 组合搜索 -->
{% if search_group_row_list %}
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-filter" aria-hidden="true"></i> 快速筛选
</div>
<div class="panel-body">
<div class="search-group">
{% for row in search_group_row_list %}
<div class="row">
{% for obj in row %}
{{ obj|safe }}
{% endfor %}
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}
<!-- 组合搜搜结束 --> <!-- 搜索 -->
{% if search_list %}
<div class="up-down-space right">
<form method="get" class="form-inline">
<div class="form-group">
<input class="form-control" type="text" name="q" value="{{ search_value }}"
placeholder="关键字搜搜">
<button class="btn btn-primary" type="submit">
<i class="fa fa-search" aria-hidden="true"></i>
</button>
</div>
</form>
</div>
{% endif %}
<!-- 搜索结束 --> <!-- 批量操作 -->
<form method="post" class="form-inline">
{% csrf_token %}
{% if action_dict %}
<div class="left up-down-space">
<div class="form-group">
<select class="form-control" name="action">
<option value="">请选择操作</option>
{% for func_name,func_text in action_dict.items %}
<option value="{{ func_name }}">{{ func_text }}</option>
{% endfor %}
</select>
<input class="btn btn-primary" type="submit" value="执行"/>
</div>
</div>
{% endif %}
<!-- 批量操作结束 --> <!-- 添加按钮开始 -->
{% if add_btn %}
<div class="up-down-space left add_btn">
{{ add_btn|safe }}
</div>
{% endif %}
<!-- 添加按钮结束 --> <table class="table table-bordered">
<thead>
<tr>
{% for item in header_list %}
<th>{{ item }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in body_list %}
<tr>
{% for ele in row %}
<td>{{ ele }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</form>
<nav>
<ul class="pagination">
{{ pager.page_html|safe }}
</ul>
</nav>
</div>
{% endblock content %}
四、css
.search-group {
padding: 5px 10px;
} .search-group .row .whole {
min-width: 40px;
float: left;
display: inline-block;
padding: 5px 0 5px 8px;
margin: 3px;
font-weight: bold; } .search-group .row .others {
padding-left: 60px;
} .search-group .row a {
display: inline-block;
padding: 5px 8px;
margin: 3px;
border: 1px solid #d4d4d4; } .search-group .row a {
display: inline-block;
padding: 5px 8px;
margin: 3px;
border: 1px solid #d4d4d4;
} .search-group a.active {
color: #fff;
background-color: #337ab7;
border-color: #2e6da4;
}
stark组件(11):组合搜索的更多相关文章
- stark组件开发之组合搜索页面效果和 URL
页面效果,只是样式.这个好解决!yield 的时候. 返回几个样式出去就好了! 并且前端写上一些样式的css {% if search_group_row_list %} <div class= ...
- stark组件开发之组合搜索基本显示
数据的获取,上一篇,已经有了!然后就是,如何进行展示的问题.到了展示这里,又有了新的问题, 因为从数据库,取得的数据. 分为 queryset 和 tuple 两种数据结构.tuple 中,只是字符串 ...
- stark组件开发之组合搜索实现思路
- 关键字搜索. 可以做到的效果是, 输入20. 后太通过 Q() 函数. 来实现. 搜索是一个大的问题点. - 要想实现组合搜索, 首先要 明确的一点是. 在我当前的页面上, 正在进行展示的是 ...
- stark组件开发之组合搜索高级显示和扩展
上一篇,我只是做了. 默认的显示. def __iter__(self): '''默认显示. 用户可以自定制''' if isinstance(self.queryset_or_tuple, list ...
- stark组件之搜索【模仿Django的admin】
一.先看下django的admin是如何做搜索功能的 配置一个search_fields的列表就可以实现搜索的功能 class testbook(admin.ModelAdmin): # 第一步,定义 ...
- Django学习---组合搜索组件
组合搜索组件 我们都会写博客,写文章之后我们要给文章设置目录,设置类型.之后我们在浏览文章的时候就能够按类别进行精确定位到文章,那这个组合搜索我们应该怎么做呢? 首先我们先创建3张表,分别存放文章,文 ...
- Django之组合搜索组件(二)--另附simple_tag的创建使用方法
这次的代码为Django之组合搜索组件(一)的改版,实现的结果和(一)相同,不同的是,这次运用simple_tag方式,使.html程序简化 所以现在就开始编程吧! 首先想使用simple_tag方法 ...
- Django之组合搜索组件(一)
什么是组合搜索呢? 比如你想买车,但手里只有10万块!所以你只能在10万块的车里挑选,但你喜欢黑色,因为觉得很高端大气上档次,说白了就是装逼杠杠的!之后售车姐给你拿了个表表,你看到了低于10万块且颜色 ...
- 轮播组件/瀑布流/组合搜索/KindEditor插件
一.企业官网 ### 瀑布流 Models.Student.objects.all() #获取所有学员信息 通过div进行循环图片和字幕 1.以template模板方法实现瀑布流以列为单位 ...
随机推荐
- Java中的阻塞队列-ArrayBlockingQueue(一)
最近在看一些java基础的东西,看到了队列这章,打算对复习的一些知识点做一个笔记,也算是对自己思路的一个整理,本章先聊聊java中的阻塞队列 参考文章: http://ifeve.com/java-b ...
- Hibernate课程 初探一对多映射4-1 inverse属性
1 <Set>节点的inverse属性默认由one方来维护(默认值为false).将inverse属性修改为true则由多方来维护.
- 【转】带你正确的使用List的retainAll方法求交集
一. retainAll 方法 public boolean retainAll(Collection<?> c) { //调用自己的私有方法 return batchRemove(c, ...
- Android大牛
张鸿洋 http://blog.csdn.net/lmj623565791/article/category/2680597 CSDN 鸿洋:http://blog.csdn.net/lmj62356 ...
- 认识less和webstrom的less配置
认识less和webstrom的less配置 今天完成的事情: 首先第一件事情是,整理一下常用的颜色摄取 #F1F1F1 google的设置页面的body的背景颜色 #FFF 为google的内容块的 ...
- WorkFlow 的 Xaml 中找不到引用类型
原来还是需要两步走. 1. 在refernece里面应用project或dll. 2. 在xaml的命名空间里面手动添加.
- Android Studio快捷键【Android学习入门】
Studio快捷键[Android学习入门]" title="Android Studio快捷键[Android学习入门]"> 提示 Ctrl+P方法参数提示 Ct ...
- iOS 谓词(NSPredicate)的应用
Cocoa中谓词(Predicate)提供了一个通用的查询方式处理数据,可以获取和指定数据的过滤形式,Cocoa实际开发中可以是使用NSPredicate及其父类NSComparisonPredica ...
- 百万级数据库SQL优化大总结
网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...
- 利用ASP.NET里自带的站点地图工具制作网站站点地图
站点地图很方便能快速给我们导航我们要去访问的地址,能按层级关系分门别类,给用户一个很好的用户体验,很好的看到自己当前所在的网站位置 站点地图,又称网站地图,它就是一个页面,上面放置了网站上所有页面的链 ...