class ModelStark(object): def add_view(self, request): return HttpResponse("add") def delete_view(self, request, id): return HttpResponse("delete") def change_view(self, request, id): return HttpResponse("change")
class ModelStark(object): def get_urls_2(self): temp = [] # 用name取別名app名+model名+操做名能夠保證別名不會重複 model_name = self.model._meta.model_name app_label = self.model._meta.app_label temp.append(url(r"^add/", self.add_view, name="%s_%s_add" % (app_label, model_name))) temp.append(url(r"^(\d+)/delete/", self.delete_view, name="%s_%s_delete" % (app_label, model_name))) temp.append(url(r"^(\d+)/change/", self.change_view, name="%s_%s_change" % (app_label, model_name))) temp.append(url(r"^$", self.list_view, name="%s_%s_list" % (app_label, model_name))) return temp
首先在list_view中獲取add_url:css
class ModelStark(object): '''代碼省略''' def get_add_url(self): model_name = self.model._meta.model_name app_label = self.model._meta.app_label _url = reverse("%s_%s_add" % (app_label, model_name)) return _url def list_view(self, request): '''代碼省略''' # 構建一個查看url add_url = self.get_add_url() return render(request, "list_view.html", locals())
在list_view.html中添加「添加數據」按鈕:html
<body> <h4>數據列表</h4> <div class="container"> <div class="row"> <div class="col-md-9"> {# <a href="add/" class="btn btn-primary">添加數據</a> #} <a href="{{ add_url }}" class="btn btn-primary">添加數據</a> """代碼省略""" </body> </html>
因爲以前的表結構過於簡單,在進行添加操做時不少問題沒法發現,在這裏從新構造模型(一對1、一對多、多對多都有)。python
from django.db import models # Create your models here. class Author(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) age = models.IntegerField() # 與AuthorDetail創建一對一的關係 authorDetail = models.OneToOneField(to="AuthorDetail", on_delete=models.CASCADE) def __str__(self): return self.name class AuthorDetail(models.Model): nid = models.AutoField(primary_key=True) birthday = models.DateField() telephone = models.BigIntegerField() addr = models.CharField(max_length=64) def __str__(self): return self.telephone 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) title = models.CharField(max_length=32) publishDate = models.DateField() price = models.DecimalField(max_digits=5, decimal_places=2) # 與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
同時將app01/admin.py和app01/stark.py中的內容清空從新進行構建。jquery
1)刪除app01/migrations/下的文件git
2)刪除db.sqlite3web
3)數據遷移sql
manage.py@stark_demo > makemigrations manage.py@stark_demo > migrate
app01/stark.py:數據庫
from stark.service.stark import site, ModelStark from django.utils.safestring import mark_safe from django.urls import reverse from .models import * site.register(Book) site.register(Publish) site.register(Author) site.register(AuthorDetail)
到此頁面已經能夠正常訪問:django
class ModelStark(object): def add_view(self, request): from django.forms import ModelForm from django.forms import widgets as wid class ModelFormDemo(ModelForm): class Meta: model = self.model fields = "__all__" # 不能使用這種方法,由於每一個表的字段是不一樣的 # widgets = { # "title": wid.TextInput(attrs={"class": "form-control"}) # } form = ModelFormDemo() # 實例化 return render(request, "add_view.html", locals())
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css"> <script src="/static/js/jquery-1.12.4.min.js"></script> <style> input,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> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <form action="" method="post"> {% for field in form %} <div> <label for="">{{ field.label }}</label> {{ field }} </div> {% endfor %} <button type="submit" class="btn btn-default">提交</button> </form> </div> </div> </div> </body> </html>
因爲每一個表字段不一樣,所以不能使用wigets來給全部標籤添加form-control樣式,直接在頁面用css給input\select構建form-control的樣式。bootstrap
顯示效果以下所示:
class ModelStark(object): """默認類,定製配置類""" list_display = ["__str__",] list_display_links = [] modelform_class = [] '''代碼省略''' def get_modelform_class(self): """用來獲取modelform類""" if not self.modelform_class: # 若是沒有值 from django.forms import ModelForm from django.forms import widgets as wid class ModelFormDemo(ModelForm): class Meta: model = self.model fields = "__all__" return ModelFormDemo else: # 若是有值說明在用戶已經本身定製過了,直接取值 return self.modelform_class def add_view(self, request): ModelFormDemo = self.get_modelform_class() form = ModelFormDemo() # 實例化 return render(request, "add_view.html", locals())
(1)定義get_modelform_class方法來獲取modelform類。若是在app01/stark.py中自定義配置類沒有modelform_class,則默認爲空,經過這個方法來獲取modelform。
(2)自定義配置Book類,並將字段顯示中文
from stark.service.stark import site, ModelStark from .models import * from django.forms import ModelForm class BookModelForm(ModelForm): class Meta: model = Book fields = "__all__" labels = { "title": "書籍名稱", "publishDate": "出版日期", "price": "價格", "publish": "出版社", "authors": "做者" } class BookConfig(ModelStark): list_display = ["title", "price", "publishDate"] modelform_class = BookModelForm site.register(Book, BookConfig)
(3)顯示效果:
(1)add_view視圖函數中處理post請求:
class ModelStark(object): def add_view(self, request): ModelFormDemo = self.get_modelform_class() if request.method == "POST": form = ModelFormDemo(request.POST) if form.is_valid(): # 校驗字段所有合格 form.save() return redirect(self.get_list_url()) # 跳轉到當前訪問表的查看頁面 # (精髓)校驗有錯誤返回頁面,且包含了錯誤信息 return render(request, "add_view.html", locals()) form = ModelFormDemo() # 實例化 return render(request, "add_view.html", locals())
注意校驗經過跳轉到當前訪問表的查看頁面;校驗不經過返回添加頁面,且包含錯誤信息。
(2)add_view.html在提交報錯時顯示錯誤信息
<style> input,select { /*代碼省略*/ } .error { color: red; } </style> <body> <h3>添加頁面</h3> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <form action="" method="post" novalidate> {% csrf_token %} {% for field in form %} <div> <label for="">{{ field.label }}</label> {{ field }} <span class="error pull-right">{{ field.errors.0 }}</span> </div> {% endfor %} <button type="submit" class="btn btn-default pull-right">提交</button> </form> </div> </div> </div> </body>
(3)提交顯示效果以下所示:
編輯頁面視圖和模板都與添加頁面很是類似。
class ModelStark(object): def change_view(self, request, id): """編輯視圖""" ModelFormDemo = self.get_modelform_class() # 編輯對象 edit_obj = self.model.objects.filter(pk=id).first() if request.method == "POST": form = ModelFormDemo(request.POST, instance=edit_obj) # instance就是給這個記錄更改成最新的數據 if form.is_valid(): # 校驗字段所有合格 form.save() return redirect(self.get_list_url()) # 跳轉到當前訪問表的查看頁面 # (精髓)校驗有錯誤返回頁面,且包含了錯誤信息 return render(request, "add_view.html", locals()) form = ModelFormDemo(instance=edit_obj) # 用instance放入編輯對象就有了編輯數據 return render(request, "change_view.html", locals())
這裏最大的區別就是獲取了當前的編輯對象,使用instance放入編輯對象獲取編輯數據;同時在post請求中將記錄更新爲最新的數據。
這裏是直接把add_view.html複製了一份作成了change_view.py,修改效果以下所示:
建立一個form.html:
<div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <form action="" method="post" novalidate> {% csrf_token %} {% for field in form %} <div> <label for="">{{ field.label }}</label> {{ field }} <span class="error pull-right">{{ field.errors.0 }}</span> </div> {% endfor %} <button type="submit" class="btn btn-default pull-right">提交</button> </form> </div> </div> </div>
add_view.html和change_view.html的body部分修改以下:
<body> <h3>編輯頁面</h3> {% include 'form.html' %} </body>
刪除時不要直接刪除,須要提示確認。
class ModelStark(object): def delete_view(self, request, id): url = self.get_list_url() if request.method == "POST": self.model.objects.filter(pk=id).delete() return redirect(url) # self.model.objects.filter(pk=id).delete() return render(request, "delete_view.html", locals())
一個form表單裏面只能有一個請求按鈕,所以確認刪除是按鈕,取消是一個a標籤跳轉到查看頁面。
delete_view.html:
<body> <h3>刪除頁面</h3> <form action="" method="post"> {% csrf_token %} <button>確認刪除?</button> <a href="{{ url }}">取消</a> </form> </body>
執行效果:
確認後顯示效果以下: