博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Xadmin显示视图
阅读量:6895 次
发布时间:2019-06-27

本文共 22326 字,大约阅读时间需要 74 分钟。

1.display显示要设置的字段

1. 自定义样式类,显示出要显示的字段,在这个类中,也可以设置对应函数。 list_display=[check,"title",delete] 2.在 Modelxadmin中设置:list_display=["__str__"] 设置Modelxadmin的静态属性,即当注册的对象没使用样式类时,使用Modelxadmin的样式属性 3.处理表头     display中的函数名或者变量名作为表头     1.需要判断传的列表中的内容是函数名还是字符串     2.如果是字符串,判断是"__str__"还是其他的     3.让相应的字符串表头显示对应的中文,取到字段对象,引用字段中的verbose_name 4.处理表单数据     需要判断传的列表中的内容是函数名还是字符串     1.若是函数名,去执行对应的函数,取到对应的值     2.若是变量,利用反射到相应的数据中取到值

2.设定样式类list_display

from Xadmin.service.Xadmin import site,Modelxadminfrom app01 import modelsfrom django.utils.safestring import  mark_safeclass BookConfig(Modelxadmin):    href=change/'%s/'自动在当前路径后拼接路径    def edit(self, obj=None,  is_header=False):        if is_header:  # 此时作表头处理            return "操作"        return mark_safe("编辑"%obj.pk)    def delete(self, obj=None, is_header=False):        if is_header:  # 此时作表头处理            return "删除"        return mark_safe("删除" % obj.pk)    def check(self, obj=None, is_header=False):        if is_header:  # 此时作表头处理            return "选择"        return mark_safe("")    list_display=[check,"title","price","publish","authors",edit,delete]site.register(models.Book,BookConfig)
View Code

3.显示设置

1.处理表头

处理表头 [check,'title', 'prcie',edit]         # 1.需要判断传的列表中的内容是函数名还是字符串         # 2.如果是字符串,判断是"__str__"还是其他的
head=[]        for field in self.list_display:            if isinstance(field,str):               if field=="__str__":                   val=self.model._meta.model_name.upper()  #如果没定义样式类,表头就显示操作表的名字的大写               else:                   # class Book(models.Model):                   #     title = models.CharField(max_length=32, verbose_name="书名")                   #     price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="价格")                   #如果是字段字符串,让表头显示其定义的中文表头。title是字段对象,找到title后title.verbose_name 获取这个属性值                   obj=self.model._meta.get_field(field)                   val=obj.verbose_name            else:                val = field(self,is_header=True)            head.append(val)
View Code

2.处理表单数据

使用反射        data_list=self.model.objects.all() #取出每一条数据的对象,data_list[0].字段名(title) 就能得到相应的数据        content = []        for obj in data_list:            temp=[]            for field in self.list_display:#自定义的样式类中有可能放的是自定义的函数名[check,'title', 'prcie',edit]                #需要判断传的列表中的内容是函数名还是字符串                if isinstance(field,str): #判断数据类型                   val=getattr(obj,field)  #相当于obj.title,obj.price 其中obj.__str__会自动触发这个方法                   print("结果是:",val)                else:                    val=field(self,obj,) #定义的方法,obj为这个方法执行的哪条数据对象                temp.append(val)            content.append(temp)        return render(request,"list.html",{
"content":content,"head":head,"type":type})
View Code

4.利用反向路由解析得到路径

'''#Modelxadmin中设置class Modelxadmin(object):    list_display=["__str__"] #设置Modelxadmin的静态属性,即当注册的对象没使用样式类时,使用Modelxadmin的样式属性    def __init__(self,model,site):  #如果传的是book,model就是Book 传的是publish,model就是Publiah        self.model=model        self.site=site        self.model_name = self.model._meta.model_name #得到app名        self.app_name = model._meta.app_label  #得到表名        #为路由设置别名:            def get_url_2(self):        temp = []        # print("=====",model_name )        # temp.append(url(r"^$", self.list_view))        temp.append(url(r"^$", self.list_view,name="{}/{}_list".format( self.app_name, self.model_name)))        temp.append(url(r"^add/$", self.add_view,name="{}/{}_add".format( self.app_name, self.model_name)))        # temp.append(url(r"^(\d+)/change/$", self.change_view,))        temp.append(url(r"^change/(\d+)/$", self.change_view,name="{}/{}_change".format( self.app_name, self.model_name) ))        temp.append(url(r"^del/(\d+)/$", self.del_view,name="{}/{}_del".format( self.app_name, self.model_name)))        return temp#自定以样式类中设置:from django.utils.safestring import  mark_safefrom django.urls import reverseclass BookConfig(Modelxadmin):    def edit(self, obj=None,  is_header=False):        if is_header:  # 此时作表头处理            return "操作"          #BookConfig中没有self.app_name,就去Modelxadmin找        url_name="{}/{}_change".format( self.app_name, self.model_name)        v = reverse(url_name, args=(obj.pk,))        return mark_safe("编辑" % v)'''
View Code

显示页面的html

'''

序号 {

% for foo in head %} {
{ foo }}
{
% endfor %}

{
% for foo in content %}

{

{ forloop.counter }} {
% for foo1 in foo %} {
{ foo1 }}
{
% endfor %}

{
% endfor %}'''

5.显示多对多的关系字段

多对多的字段,传过去之后在页面上显示字符串:app01.Author.None
例:作者是多对多的关系 list_display=[check,"title","price","publish","authors",edit,delete] 传过去之后在页面上显示字符串:app01.Author.None解决方法一:将ManytoMany这个字段当作函数名传过去,不再写成字符串在样式类中定义ManytoMany字段方法:    def display_authors(self,obj=None, is_header=False):        if is_header:            return "作者名称"        s=[]        for author in obj.authors.all(): #必须使用all(),得到所有的作者对象            s.append(author.name) #取出每个作者对象的name属性        val=" | ".join(s)        return mark_safe(val)    list_display = [check, "title", "price", "publish", display_authors, edit, delete]方法二:判断是不是ManytoMany类型        data_list=self.model.objects.all() #取出每一条数据的对象,data_list[0].字段名(title) 就能得到相应的数据        content = []        for obj in data_list:            temp=[]            for field in self.list_display:#自定义的样式类中有可能放的是自定义的函数名[check,'title', 'prcie',edit]                #需要判断传的列表中的内容是函数名还是字符串                if isinstance(field,str): #判断数据类型                    #处理多对多的字段方法二:判断是不是ManytoMany类型                    from django.db.models.fields.related import ManyToManyField                    many_obj = self.model._meta.get_field(field) #取到字段对象                    if isinstance(many_obj,ManyToManyField):                        t=[]                        for i in getattr(obj,field).all():                            t.append(i.name)                        val=" | ".join(t)                    else:val=getattr(obj,field)  #相当于obj.title,obj.price 其中obj.__str__会自动触发这个方法list_display=[check,"title","price","publish","authors",edit,delete]
View Code

6.将删除,编辑,选择按钮封装起来

'''app01.Xadmin 1.使用继承:但是需要在每个样式类中设定class Operation():    def edit(self, obj,is_header):        if is_header:  # 此时作表头处理            return "操作"        else:            url_name = "{}/{}_change".format(self.app_name, self.model_name)  # BookConfig中没有self.app_name,就去Modelxadmin找            v = reverse(url_name, args=(obj.pk,))            return mark_safe("编辑" % v)    def delete(self, obj, is_header):        if is_header:  # 此时作表头处理            return "操作"        return mark_safe("删除" % obj.pk)    def check(self, obj, is_header):        if is_header:  # 此时作表头处理            return "选择"        else:print(777)        return mark_safe("")class BookConfig(Modelxadmin, Operation):    def check(self,obj=None, is_header=False):return super().check(obj, is_header)    def edit(self,obj=None, is_header=False):return super().edit(obj, is_header)    def delete(self,obj=None,  is_header=False):return super().delete(obj, is_header)    list_display=[check,"title","price","publish","authors",edit,delete]#如果不在BookConfig中定义check,edit,delete函数,在list_dispaly中加函数名后,会显示未定义。在用super调用时不能传位置参数2.在Xadmin中设置,将check,edit,delete加到每个模型表的样式类中,模型表的样式类就不用再加这些函数class Modelxadmin(object):    # 选择按钮  编辑 删除    def edit(self, obj=None, is_header=False):        if is_header:  # 此时作表头处理            return "操作"        else:            v=self.get_change_url(obj)            return mark_safe("编辑" %v)    def delete(self, obj=None, is_header=False):        if is_header:  # 此时作表头处理            return "操作"        v = self.get_del_url(obj)        return mark_safe("删除" %v)    def check(self, obj=None, is_header=False):        if is_header:  # 此时作表头处理            return "选择"        v = self.get_del_url(obj)        return mark_safe("")    #构建新的list_dispaly    def new_list_display(self):        temp=[]        temp.append(Modelxadmin.check)        temp.extend(self.list_display)        temp.append(Modelxadmin.edit)        temp.append(Modelxadmin.delete)        return temp    #处理表头 [check,'title', 'prcie',edit]    for field in self.new_list_display():pass     #处理表单数据,使用反射      data_list=self.model.objects.all() #取出每一条数据的对象,data_list[0].字段名(title) 就能得到相应的数据        content = []        for obj in data_list:            temp=[]            for field in self.new_list_display():pass样式类中直接传要显示的字段 list_display = ["title", "price", "publish", "authors"]'''
View Code

7.设定样式类list_display_link

1.在循环表单数据时,如果list_display中的字段名在list_display_link,就将改字段的内容设置成编辑标签 2.如果表中数据设置成了编辑标签,那么编辑这个操作就没什么用了,应该判断如果样式中无list_display_link,就显示编辑操作, 有list_display_link则不显示编辑操作
在new_list_display中判断是否加编辑操作    def new_list_display(self):        temp=[]        temp.append(Modelxadmin.check)        temp.extend(self.list_display)        #判断是否加编辑操作        if not self.list_display_link:            temp.append(Modelxadmin.edit)        temp.append(Modelxadmin.delete)        return temp##将相应值设置成编辑标签from django.db.models.fields.related import ManyToManyField    try:        many_obj = self.model._meta.get_field(field) #取到字段对象        if isinstance(many_obj,ManyToManyField):            t=[]            for i in getattr(obj,field).all():                t.append(i.name)            val=" | ".join(t)        else:            #判断改字段是否在list_display_link,如果在,就设置成标签形式,不再就正常显示            if field in self.list_display_link:                edit_url=self.get_change_url(obj)                val=mark_safe("%s"%(edit_url,getattr(obj,field)))            else:val=getattr(obj,field)    except Exception as e:        val = getattr(obj, field)
View Code
显示页面的函数形式
''' def list_view(self, request): #self是Modelxadmin的实例对象,要么是自定义样式类的实例对象    # print("这里是:", model_name )    type=request.GET.get("name")    if not type:type=""    print(type)    print(self.model)  #用户调用的哪张表,self.model就是哪张表  
print("新的是:",self.new_list_display()) #处理表头 [check,'title', 'prcie',edit] # 1.需要判断传的列表中的内容是函数名还是字符串 # 2.如果是字符串,判断是"__str__"还是其他的 head=[] # for field in self.list_display: for field in self.new_list_display(): if isinstance(field,str): if field=="__str__": print("食物") val=self.model._meta.model_name.upper() #如果没定义样式类,表头就显示操作表的名字的大写 else: # class Book(models.Model): # title = models.CharField(max_length=32, verbose_name="书名") # price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="价格") #如果是字段字符串,让表头显示其定义的中文表头。title是字段对象,找到title后title.verbose_name 获取这个属性值 obj=self.model._meta.get_field(field) val=obj.verbose_name else: val = field(self,is_header=True) head.append(val) print(head) #处理表单数据,使用反射 data_list=self.model.objects.all() #取出每一条数据的对象,data_list[0].字段名(title) 就能得到相应的数据 content = [] for obj in data_list: temp=[] # for field in self.list_display:#自定义的样式类中有可能放的是自定义的函数名[check,'title', 'prcie',edit] for field in self.new_list_display(): #需要判断传的列表中的内容是函数名还是字符串 if isinstance(field,str): #判断数据类型 #处理多对多的字段方法二:判断是不是ManytoMany类型 from django.db.models.fields.related import ManyToManyField try: #如果是__str__ 走到这会报错,因此使用抛出异常处理 many_obj = self.model._meta.get_field(field) #取到字段对象 if isinstance(many_obj,ManyToManyField): t=[] for i in getattr(obj,field).all(): t.append(i.name) val=" | ".join(t) else: # val=getattr(obj,field) #相当于obj.title,obj.price 其中obj.__str__会自动触发这个方法 #判断改字段是否在list_display_link,如果在,就设置成标签形式,不再就正常显示 if field in self.list_display_link: edit_url=self.get_change_url(obj) val=mark_safe("
%s"%(edit_url,getattr(obj,field))) else:val=getattr(obj,field) except Exception as e: val = getattr(obj, field) print("结果是:",val) else: val=field(self,obj,) #定义的方法,obj为这个方法执行的哪条数据对象 temp.append(val) print("temp是:", temp) content.append(temp) print("content是:", content) # ##获取增加页面的url 点击增加的时候,跳到增加页面。自动拼接 # add_url="add" return render(request,"list.html",{
"content":content,"head":head,"type":type,"add_url":self.get_add_url()})'''
View Code

8.设置分页

将分页方法设置为显示类得属性,用时直接用对象调用

class ShowList(object):    def __init__(self,config,data_list,request):        self.config=config  #config是Modelxadmin的对象        self.data_list=data_list        self.request=request    ##配置分页设置:        current_page = self.request.GET.get("page")        pagination = Pagination(current_page, self.data_list.count(), "%s" % self.config.get_list_url(), self.request.GET,                                per_page_num=3)        self.pagination=pagination        self.model_list = self.data_list[pagination.start:pagination.end] def get_body(self):        content = []        for obj in self.model_list:pass #循环分完页之后数据对象
View Code
分页条: 
    {
    {show_list.pagination.page_html|safe }}

9.搜索功能

搜索时用GET请求,后端很根据收到的搜索条件进行处理,在显示全部数据的基础上,将符合搜索的内容显示出来 未使用搜索时,获得当前对象的所有内容 data_list = self.model.objects.all() 加了搜索,就在这基础上进行条件搜索,使用filter data_list = self.model.objects.filter(条件) 获取到设定的搜索字段,使用Q()进行操作,将字符串类型的字段和接受到的搜索值加到Q()中,搜索时会检测所有对象的这个字段中是否含有搜索值,如果有,就把这个 对象取出来
class Modelxadmin(object):    search_fields = []    def get_search(self, request):        search_condition = Q()        search_condition.connector = 'or'        search_value = request.GET.get("search_value")        if search_value:            for search_field in self.search_fields:                search_condition.children.append((search_field + "__icontains", search_value))        return search_condition    def list_view(self, request): #self是Modelxadmin的实例对象,要么是自定义样式类的实例对象        #print(self.model)  #用户调用的哪张表,self.model就是哪张表  
search_condition=self.get_search(request) data_list = self.model.objects.filter(search_condition) #search_condition有值,就按值搜索,无值就搜索全部
Views.py
在显示页面,设置搜索框是否显示。通过判断search_fields来判断是都设置了搜索值,如果为空,在页面上就不显示搜索 HTML
'''{% if  show_list.config.search_fields %} 
{
% endif %}'''
View Code

10.批处理功能

实现选择对应得操作后,执行对应得函数 批处理操作使用select选择的方式:value应对应函数名,显示的操作名称不应该直接再HTML中设定, 可以在后端为相应的执行函数起相应的名字 对函数做描述:foo.short_description="批量初始化"  #对这个函数作描述
class A():    def foo(self,queryset):        queryset.delete()    foo.short_description="批量删除"    def update(self,queryset):        queryset.update(price=100)    update.short_description="批量初始化"  #对这个函数作描述    action=[foo,update]b=A()for i in b.action:   #i是函数名    print(i.__name__,i.short_description)HTML中  
View Code

1.设置批处理函数

在app01 Xadmin中设置自定义处理函数:class BookConfig(Modelxadmin): def all_update(self,request,queryset): #queryset为数据对象        queryset.update(price=998)        list_url = self.get_list_url()        return redirect("%s" % list_url)    all_update.short_description="批量初始化"    actions=[all_update,]在全局中设置批量删除函数:class Modelxadmin(object):actions=[]  def all_delete(self,request,queryset):        queryset.delete()        list_url=self.get_list_url()        return redirect("%s"%list_url)    all_delete.short_description="批量删除"

2.在Modelxadmin将批量删除和样式类中的actions合到一起

def get_action(self): #将批量删除和样式类中的actions合到一起        temp=[]        temp.append(self.all_delete)        temp.extend(self.actions) #迭代添加        return temp  #将得到的temp作为ShowList的一个属性,并函数名和描述值处理后在页面显示出来class ShowList(object):self.actions=self.config.get_action()def new_actions(self):    temp=[]    for action in self.actions:        temp.append({            "name":action.__name__,            "desc":action.short_description        })    return temp
View Code

3.HTML

        

4.后台接收处理:

class Modelxadmin(object):     def list_view(self, request):          if request.method=='POST': #批量操作                action=request.POST.get("action")  #哪种操作,name="action",值为要执行操作的函数名                print("操作是",action)                selected_pk=request.POST.getlist("selected") #操作的数据                action_obj=self.model.objects.filter(pk__in=selected_pk)                action=getattr(self,action)                ret=action(request,action_obj)                return ret

完整的views.py

##批处理:得到注册对象样式类中指定的操作,并为所有的注册对象添加上删除操作def all_delete(self,request,queryset):    queryset.delete()    list_url=self.get_list_url()    return redirect("%s"%list_url)all_delete.short_description="批量删除"def get_action(self): #将批量删除和样式类中的actions合到一起    temp=[]    temp.append(self.all_delete)    temp.extend(self.actions) #迭代添加    return temp  #将得到的temp作为ShowList的一个属性def list_view(self, request): #self是Modelxadmin的实例对象,要么是自定义样式类的实例对象    if request.method=='POST': #批量操作        action=request.POST.get("action")  #哪种操作        print("操作是",action)        selected_pk=request.POST.getlist("selected") #操作的数据        action_obj=self.model.objects.filter(pk__in=selected_pk)        action=getattr(self,action)        ret=action(request,action_obj)        return ret
View Code

11.过滤功能

1.首先在页面上展示出过滤的内容

页面收到后端传来的数据进行循坏操作,收到的应该是个字典: {"publish":["a","a"],"author":["a","a"]},key值为表名,value为表中的所有对象的名字,同时将value 设置成标签,herf设为?key=obj.pk的形式,点完标签后,后台接受到操作的表名和要操作的对象进行搜索操作,从而展示出来

2.在指定的app01中注册模型表中设置过滤的字段:以Book表为例:

class BookConfig(Modelxadmin):    list_filter=["publish","authors"]在Xadimn中作后台处理操作:class Modelxadmin(object):      list_filter = []
 
首先要做的是创建出{"publish":["a","a"],"author":["a","a"]}这种类型给页面展示出来,展示出来之后,在做跳转操作,展示的处理都放在 ShowList中,在ShowList中定义处理函数。得到自定义的search_fields中,得到对应的字符串类型的字段,根据字符串,找到这个字段对象,根据字段 对象,得到关联表中的所有对象,将这个对象名做成链接返给页面
1.def get_filter_link_tags(self):    # link_tags={
"publish":["a","a"],"author":["a","a"]} link_tags={} for filter_field in self.list_filter: #["title", "price"] filter_field_obj=self.config.model._meta.get_field(filter_field) #得到Book表中的publish和authors字段 #得到字段对象关联表的所有对象。publish和authors中所有对象 related_data_list=filter_field_obj.rel.to.objects.all() temp=[] for obj in related_data_list: #对每个对象做处理 _url="%s=%s"%(filter_field,obj.pk) s="%s"%(_url,str(obj)) #在页面显示出?publish=2 temp.append(mark_safe(s)) link_tags[filter_field]=temp return link_tags

3.点击相应链接

在点击相应链接之后,点击publish中的对象显示?publish=2这种形式,点击author中的内容显示?author=2 但是要保存搜索条件,即在上次选的条件下继续搜索,达到?publish=2&?author=2的效果。使用request.GET 在第一次点击链接之后,页面刷新,会重新走到这一步,获取数据返还给页面,此时self.request.GET获取到?publish=2,在执行到循环authors的对象时 就会将参数拼接起来?publish=2&?author=2
def get_filter_link_tags(self):        # link_tags={
"publish":["a","a"],"author":["a","a"]} link_tags={} from copy import deepcopy for filter_field in self.list_filter: # /Xadmin/app01/book/?page=2 params = deepcopy(self.request.GET) #将后面的参数以字典的形式接收 {
'page':2} filter_field_obj=self.config.model._meta.get_field(filter_field) #得到字段对象关联表的所有对象 related_data_list=filter_field_obj.rel.to.objects.all() temp=[] for obj in related_data_list: params[filter_field]=obj.pk # {
"authors":2} _url=params.urlencode() # _url="%s=%s"%(filter_field,obj.pk) s="%s"%(_url,str(obj)) temp.append(mark_safe(s)) link_tags[filter_field]=temp return link_tags
View Code

4.点击完当前标签之后,当前标签添加背景色。通过判断当前的接受到的id和循环中的当前id是否相等

current_id=self.request.GET.get(filter_field)if current_id==str(obj.pk):        s = "%s" % (_url, str(obj))else:      s="%s"%(_url,str(obj))

5.链接跳转

点击相应的标签后,后台接收到?publish=2这个数据,进行过滤查询,使用Q().children
class Modelxadmin(object):    filter_condition=Q()    for filter_field,val in request.GET.items():        ##当选择分页时,页面上会把page=2传过来,仍走这一步,但是表中并没有这个字段,所以会报错        if filter_field not in ['page',"search_value"]:            filter_condition.children.append((filter_field,val))    data_list = self.model.objects.filter(filter_condition).filter(search_condition) #search_condition有值
View Code

过滤功能views.py

class BookConfig(Modelxadmin):    list_filter=["publish","authors"]    class Modelxadmin(object):      list_filter = []      def list_view(self, request):        filter_condition=Q()        for filter_field,val in request.GET.items():            ##当选择分页时,页面上会把page=2传过来,仍走这一步,但是表中并没有这个字段,所以会报错            if filter_field not in ['page',"search_value"]:                filter_condition.children.append((filter_field,val))        data_list = self.model.objects.filter(filter_condition).filter(search_condition)         #search_condition有值,就按值搜索,无值就搜索全部class ShowList(object): def get_filter_link_tags(self):        # link_tags={
"publish":["a","a"],"author":["a","a"]} link_tags={} from copy import deepcopy for filter_field in self.list_filter: # /Xadmin/app01/book/?page=2 params = deepcopy(self.request.GET)#将后面的参数以字典的形式接收 {
'page':2} current_id=self.request.GET.get(filter_field) filter_field_obj=self.config.model._meta.get_field(filter_field) #得到字段对象关联表的所有对象 related_data_list=filter_field_obj.rel.to.objects.all() temp=[] for obj in related_data_list: params[filter_field]=obj.pk # {
"authors":2} _url=params.urlencode() # _url="%s=%s"%(filter_field,obj.pk) if current_id==str(obj.pk): s = "%s" % (_url, str(obj)) else: s="%s"%(_url,str(obj)) temp.append(mark_safe(s)) link_tags[filter_field]=temp return link_tags HTML:
{
% for filter_filed,link_tag_list in show_list.get_filter_link_tags.items %}

By {

{ filter_filed.upper }}

{
% for link_tag in link_tag_list %}

{

{ link_tag }}

{
% endfor %} {
% endfor %}
View Code

转载于:https://www.cnblogs.com/zgf-666/p/9161854.html

你可能感兴趣的文章
ZOJ 1081 Points Within( 判断点在多边形内外 )
查看>>
flex模拟微信布局
查看>>
多线程测试java接口
查看>>
with 语句
查看>>
js基础知识点总结
查看>>
HTML5的新增方法
查看>>
protobuf c++例子
查看>>
eclipse中tomcat端口被占用如何解决
查看>>
通过CImageList加载图标 报错
查看>>
纯小白入手 vue3.0 CLI - 3.2 - 路由的初级使用
查看>>
安卓开发笔记——探索EventBus(转)
查看>>
Logminer实战
查看>>
桌面虚拟化之PCoIP访问协议会话统计功能
查看>>
在.NET开发中的单元测试工具之(1)——NUnit
查看>>
PostgreSQL 使用 LDAP 认证方式
查看>>
委托事件和jquery中的delegate方法
查看>>
温针灸_百度百科
查看>>
Ext.Net学习笔记23:Ext.Net TabPanel用法详解
查看>>
DNS劫持
查看>>
tomcat配置虚拟主机
查看>>