1、url的分發練習css
from django.conf.urls import url from django.contrib import admin from django.shortcuts import HttpResponse def index(request): return HttpResponse("首頁") def add(request): #add視圖函數 return HttpResponse("add") def list_view(request): #list_view視圖函數 return HttpResponse("list_view") def change(request,id): #change視圖函數 return HttpResponse("change") def delete(request,id): #delete視圖函數 return HttpResponse("delete") def get_urls2(): #url的二級分發函數 temp=[ url("^add/$",add), url("^$",list_view), url("^(\d+)/change/$",change), url("^(\d+)/delete/$",delete), ] return temp def get_urls(): temp=[] for model,model_class_obj in admin.site._registry.items(): # 模型類:該模型類的配置類對象 {Book:ModelAdmin(Book),Publish:ModelAdmn(Publish),....} app_name=model._meta.app_label #獲得應用名 model_name=model._meta.model_name temp.append(url(r"%s/%s/"%(app_name,model_name),(get_urls2(),None,None))) #url作分發,後面跟元組,元組第一項爲一個列表 return temp from stark.service.sites import site urlpatterns = [ url(r'^admin/', admin.site.urls), url(r"^stark",(get_urls(),None,None)) ]
2、實現stark組件html
app01應用的models.py文件:python
from django.db import models class Author(models.Model): nid = models.AutoField(primary_key=True) name=models.CharField( max_length=32) age=models.IntegerField() def __str__(self): return self.name class Publish(models.Model): nid = models.AutoField(primary_key=True) name=models.CharField( max_length=32) city=models.CharField( max_length=32) email=models.EmailField() def __str__(self): return self.name class Book(models.Model): nid = models.AutoField(primary_key=True,verbose_name="編號") title = models.CharField( max_length=32,verbose_name="名稱") publishDate=models.DateField() price=models.DecimalField(max_digits=5,decimal_places=2,verbose_name="價格") # 與Publish創建一對多的關係,外鍵字段創建在多的一方 publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE) # 與Author表創建多對多的關係,ManyToManyField能夠建在兩個模型中的任意一個,自動建立第三張表 authors=models.ManyToManyField(to='Author',) def __str__(self): return self.title #執行下面python語句生成相關表(數據遷移) # python3 manage.py makemigrations # python3 manage.py migrate
項目下的settings.py文件設置:git
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', "app02.apps.App02Config", "stark.apps.StarkConfig", ] STATIC_URL = '/static/' STATICFILES_DIRS=[ os.path.join(BASE_DIR,"static") ]
項目的urls.py文件:web
from django.conf.urls import url from django.contrib import admin from stark.service.sites import site urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^stark/', site.urls), #模擬admin的實現方式,在stark目錄後面進行分發 ]
app01應用的stark.py文件對app01的應用表進行註冊:django
from stark.service.sites import site,ModelStark from app01.models import Book from app01.models import Publish from app01.models import Author class BookConfig(ModelStark): # def display_authors(self, obj=None,is_header=False): #顯示多對多字段,單獨定義函數實現方式 # # if is_header: # return "做者" # s=[] # for author in obj.authors.all(): # s.append(author.name) # # return " ".join(s) list_display = ["nid","title","price","publish","authors",] # list_display = ["nid","title","price","publish",display_authors] site.register(Book,BookConfig) site.register(Publish) site.register(Author)
項目下的stark目錄下apps.py定義執行各個應用的stark.py:bootstrap
from django.apps import AppConfig from django.utils.module_loading import autodiscover_modules class StarkConfig(AppConfig): name = 'stark' def ready(self): autodiscover_modules('stark') # 執行每個app下的stark.py
項目下的stark目錄下service目錄下sites.py定義對用戶訪問url的分發:session
from django.conf.urls import url from django.shortcuts import HttpResponse, render from django.utils.safestring import mark_safe class ModelStark(): #將增,刪,改,查寫到ModelStark類中,這樣誰調用類中的功能,self.model就是用戶訪問的表 list_display = ["__str__", ] def __init__(self, model, site): self.model = model self.site = site def edit(self, obj=None, is_header=False): if is_header: return "操做" #表頭返回 "操做" return mark_safe("<a href='%s/change'>編輯</a>" % obj.pk) #mark_safe會識別返回的html標籤 def delete(self, obj=None, is_header=False): if is_header: return "操做" return mark_safe("<a href='%s/delete'>刪除</a>" % obj.pk) def checkbox(self, obj=None, is_header=False): if is_header: return "選擇" return mark_safe("<input type='checkbox' pk=%s>" % obj.pk) #在對應位置顯示多選框 def add(self, request): return HttpResponse("add") def new_list_display(self): #新的顯示樣式,這樣全部表的顯示都有多選框,編輯和刪除操做 temp = [] temp.append(ModelStark.checkbox) temp.extend(self.list_display) temp.append(ModelStark.edit) temp.append(ModelStark.delete) return temp def list_view(self, request): print(self.model) data_list = self.model.objects.all() print("list_display", self.list_display) # ["nid","title","price",edit] # 處理表頭 header_list = [] for field in self.new_list_display(): if isinstance(field, str): #判斷field是字符串類型 if field == "__str__": #字段是__str__ val = self.model._meta.model_name.upper() #表頭顯示錶名的大寫字母 else: field_obj = self.model._meta.get_field(field) val = field_obj.verbose_name #獲得字段的verbose_name,定義後能夠顯示中文 else: val = field(self, is_header=True) #field是函數,執行函數 header_list.append(val) # 處理表單數據 new_data_list = [] for obj in data_list: temp = [] for field in self.new_list_display(): # ["nid","title","price","authors",edit] ['__str__'] ["title","price"] if isinstance(field, str): try: from django.db.models.fields.related import ManyToManyField field_obj = self.model._meta.get_field(field) #獲得field的字段對象 if isinstance(field_obj, ManyToManyField): #判斷是多對多關係的字段 l = [] for i in getattr(obj, field).all(): #.all()獲得全部的對象,不然none l.append(str(i)) val = ",".join(l) else: val = getattr(obj, field) print("val", val) except Exception as e: val = getattr(obj, field) #反射,取到字段名 else: val = field(self, obj) temp.append(val) new_data_list.append(temp) return render(request, "list_view.html", locals()) def change(self, request, id): return HttpResponse("change") def delete_view(self, request, id): return HttpResponse("delete_view") def get_urls2(self): temp = [ url("^add/$", self.add), url("^$", self.list_view), url("^(\d+)/change/$", self.change), url("^(\d+)/delete/$", self.delete_view), ] return temp @property def urls2(self): return self.get_urls2(), None, None class StarkSite(): def __init__(self, ): self._registry = {} # 一級分發 def get_urls(self): temp = [] for model, model_class_obj in self._registry.items(): # {Book:ModelAdmin(Book),Publish:ModelAdmn(Publish),....} app_name = model._meta.app_label model_name = model._meta.model_name temp.append(url(r"%s/%s/" % (app_name, model_name), model_class_obj.urls2)) #接着二級分發 return temp @property def urls(self): return self.get_urls(), None, None def register(self, model, admin_class=None, **options): if not admin_class: admin_class = ModelStark self._registry[model] = admin_class(model, self) site = StarkSite()
list_view.html頁面:app
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bs/css/bootstrap.css"> </head> <body> <h3>查看數據</h3> <div> <div> <div> <table class="table table-bordered table-hover table-striped"> <thead> <tr> {% for foo in header_list %} <th>{{ foo }}</th> {% endfor %} </tr> </thead> <tbody> {% for new_data in new_data_list %} <tr> {% for foo in new_data %} <td>{{ foo }}</td> {% endfor %} </tr> {% endfor %} </tbody> </table> </div> </div> </div> </body> </html>
3、顯示多對多字段的另外一種方法ide
stark.py註冊表時自定義函數:
class BookConfig(ModelStark): def display_authors(self, obj=None,is_header=False): #顯示多對多字段 if is_header: return "做者" s=[] for author in obj.authors.all(): s.append(author.name) return " ".join(s) list_display = ["nid","title","price","publish",display_authors]
sites.py裏面的ModelStark類定義的list_view
def list_view(self, request): print(self.model) data_list = self.model.objects.all() print("list_display", self.list_display) # ["nid","title","price",edit] # 處理表頭 # header_list=["ID","名稱","價格"] header_list=[] for field in self.new_list_display(): if isinstance(field,str): if field=="__str__": val=self.model._meta.model_name.upper() else: field_obj=self.model._meta.get_field(field) val=field_obj.verbose_name else: val=field(self,is_header=True) header_list.append(val) # 處理表單數據 new_data_list = [] for obj in data_list: temp = [] for field in self.new_list_display(): # ["nid","title","price","authors",edit] ['__str__'] ["title","price"] if isinstance(field,str): val = getattr(obj, field) else: val=field(self,obj) temp.append(val) new_data_list.append(temp)
頁面顯示效果圖:
4、stark組件自定義功能設置
app01應用下的stark.py文件:
from stark.service.sites import site,ModelStark from app01.models import Book from app01.models import Publish from app01.models import Author class BookConfig(ModelStark): def display_authors(self, obj=None,is_header=False): if is_header: return "做者" s=[] for author in obj.authors.all(): s.append(author.name) return " ".join(s) list_display = ["nid","title","price","publish","authors",] #自定義顯示的字段 search_fields=["title","price"] #搜索依據的字段 def patch_init(self,selected_pk): print("selected_pk",selected_pk) ret=self.model.objects.filter(pk__in=selected_pk).update(price=0) print("====>",ret) patch_init.desc="批量初始化" def patch_delete(self,selected_pk): print("selected_pk",selected_pk) ret=self.model.objects.filter(pk__in=selected_pk).delete() print("====>",ret) patch_delete.desc="批量刪除" actions=[patch_init,patch_delete] #定義批量操做 site.register(Book,BookConfig) site.register(Publish) site.register(Author)
stark組件下service目錄sites.py文件進行完善:
from django.conf.urls import url from django.shortcuts import HttpResponse, render, redirect from django.utils.safestring import mark_safe from django.urls import reverse class Show_List(object): def __init__(self, config, data_list): self.config = config self.data_list = data_list def get_header(self): # 處理表頭 # header_list=["ID","名稱","價格"] header_list = [] for field in self.config.new_list_display(): if isinstance(field, str): if field == "__str__": val = self.config.model._meta.model_name.upper() else: field_obj = self.config.model._meta.get_field(field) val = field_obj.verbose_name else: val = field(self.config, is_header=True) header_list.append(val) return header_list def get_body(self): # 處理表單數據 new_data_list = [] for obj in self.data_list: temp = [] for field in self.config.new_list_display(): # ["nid","title","price","authors",edit] ['__str__'] ["title","price"] if isinstance(field, str): try: from django.db.models.fields.related import ManyToManyField field_obj = self.config.model._meta.get_field(field) if isinstance(field_obj, ManyToManyField): l = [] for i in getattr(obj, field).all(): l.append(str(i)) val = ",".join(l) else: val = getattr(obj, field) print("val", val) except Exception as e: val = getattr(obj, field) else: val = field(self.config, obj) temp.append(val) new_data_list.append(temp) return new_data_list def get_new_actions(self): action_list = [] for i in self.config.actions: # [patch_init,] action_list.append({ "desc": i.desc, "name": i.__name__, }) return action_list class ModelStark(): # 功能的樣式顯示類 list_display = ["__str__", ] search_fields = [] actions = [] def __init__(self, model, site): self.model = model self.site = site def edit(self, obj=None, is_header=False): if is_header: return "操做" return mark_safe("<a href='%s/change'>編輯</a>" % obj.pk) def delete(self, obj=None, is_header=False): if is_header: return "操做" return mark_safe("<a href='%s/delete'>刪除</a>" % obj.pk) def checkbox(self, obj=None, is_header=False): if is_header: return "選擇" return mark_safe("<input type='checkbox' name='selected_pk' value=%s>" % obj.pk) def get_list_url(self): model_name = self.model._meta.model_name app_label = self.model._meta.app_label _url = reverse("%s_%s_list" % (app_label, model_name)) return _url def new_list_display(self): temp = [] temp.append(ModelStark.checkbox) temp.extend(self.list_display) temp.append(ModelStark.edit) temp.append(ModelStark.delete) return temp def get_search_condition(self, request): #定義搜索查找函數 from django.db.models import Q search_condition = Q() val = request.GET.get("q") if val: search_condition.connector = "or" #設置搜索依據的字段是或者的關係,即知足一個字段的查找結果就能夠 for field in self.search_fields: search_condition.children.append((field + "__contains", val)) #搜索的字符串進行模糊匹配 return search_condition def list_view(self, request): if request.method == "POST": action = request.POST.get("action") selected_pk = request.POST.getlist("selected_pk") action = getattr(self, action) action(selected_pk) search_condition = self.get_search_condition(request) data_list = self.model.objects.all().filter(search_condition) print("list_display", self.list_display) # ["nid","title","price",edit] sl = Show_List(self, data_list) return render(request, "list_view.html", locals()) def get_mdoelForm(self): from django.forms import ModelForm class DemoModelForm(ModelForm): class Meta: model = self.model fields = "__all__" return DemoModelForm def add(self, request): #定義添加頁面的函數 if request.method == "POST": form = self.get_mdoelForm()(request.POST) if form.is_valid(): form.save() return redirect(self.get_list_url()) else: return render(request, "add.html", locals()) form = form = self.get_mdoelForm()() return render(request, "add.html", locals()) def change(self, request, id): #定義編輯函數 obj = self.model.objects.filter(pk=id).first() if request.method == "POST": form = self.get_mdoelForm()(request.POST, instance=obj) if form.is_valid(): form.save() return redirect(self.get_list_url()) form = self.get_mdoelForm()(instance=obj) return render(request, "change.html", locals()) def delete_view(self, request, id): if request.method == "POST": self.model.objects.get(pk=id).delete() return redirect(self.get_list_url()) url = self.get_list_url() return render(request, "delete.html", locals()) def get_urls2(self): model_name = self.model._meta.model_name app_label = self.model._meta.app_label temp = [ url("^add/$", self.add, name="%s_%s_add" % (app_label, model_name)), url("^$", self.list_view, name="%s_%s_list" % (app_label, model_name)), url("^(\d+)/change/$", self.change, name="%s_%s_change" % (app_label, model_name)), url("^(\d+)/delete/$", self.delete_view, name="%s_%s_delete" % (app_label, model_name)), ] return temp @property def urls2(self): return self.get_urls2(), None, None class StarkSite(): def __init__(self, ): self._registry = {} # 一級分發 def get_urls(self): temp = [] for model, model_class_obj in self._registry.items(): app_name = model._meta.app_label model_name = model._meta.model_name temp.append(url(r"%s/%s/" % (app_name, model_name), model_class_obj.urls2)) return temp @property def urls(self): return self.get_urls(), None, None def register(self, model, admin_class=None, **options): if not admin_class: admin_class = ModelStark self._registry[model] = admin_class(model, self) site = StarkSite()
templates模板
form.html頁面:
<div> <div> <div class="col-md-8 col-md-offset-1"> <form action="" method="post" novalidate> {% csrf_token %} {% for field in form %} <div> <label for="">{{ field.label }}</label> {{ field }} <span style="color: red">{{ field.errors.0 }}</span> </div> {% endfor %} <input type="submit" class="btn btn-default"> </form> </div> </div> </div>
add.html添加頁面:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bs/css/bootstrap.css"> <style> input[id], select { display: block; width: 100%; height: 34px; padding: 6px 12px; font-size: 14px; line-height: 1.42857143; color: #555; background-color: #fff; background-image: none; border: 1px solid #ccc; border-radius: 4px; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; } </style> </head> <body> <h3>添加頁面</h3> {% include 'form.html' %} </body> </html>
change.html修改頁面:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bs/css/bootstrap.css"> <style> input[id], select { display: block; width: 100%; height: 34px; padding: 6px 12px; font-size: 14px; line-height: 1.42857143; color: #555; background-color: #fff; background-image: none; border: 1px solid #ccc; border-radius: 4px; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; } </style> </head> <body> <h3>編輯頁面</h3> {% include 'form.html' %} </body> </html>
delete.html刪除頁面:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bs/css/bootstrap.css"> </head> <body> <h3>刪除頁面</h3> <form action="" method="post"> {% csrf_token %} <input type="submit" value="確認刪除"> <a href="{{ url }}">取消</a> </form> </body> </html>
list_view.html顯示頁面:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bs/css/bootstrap.css"> <style> .search { margin: 20px; } </style> </head> <body> <h3>查看數據</h3> <a href="add/" class="btn btn-primary">添加數據</a> <div> <div> <div> <form action="" class="search pull-right" method="get"> <input type="text" name="q" style="width: 300px;display: inline-block"> <button class="btn btn-danger">search</button> </form> <form action="" method="post"> {% csrf_token %} <select name="action" id="" style="width: 200px;display: inline-block"> {% for action_dict in sl.get_new_actions %} <option value="{{ action_dict.name }}">{{ action_dict.desc }}</option> {% endfor %} </select> <button type="submit" class="btn btn-success">Go</button> <table class="table table-bordered table-hover table-striped"> <thead> <tr> {% for foo in sl.get_header %} <th>{{ foo }}</th> {% endfor %} </tr> </thead> <tbody> {% for new_data in sl.get_body %} <tr> {% for foo in new_data %} <td>{{ foo }}</td> {% endfor %} </tr> {% endfor %} </tbody> </table> </form> </div> </div> </div> </body> </html>
頁面效果圖: