stark——增删改页面
一、制作添加页面
1、前置准备
(1)修改增删改的视图函数名
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")
(2)调整路由对应的视图函数
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
(3)在查看页面添加add按钮
首先在list_view中获取add_url:
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中添加“添加数据”按钮:
<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>
(4)重构模型
由于之前的表结构过于简单,在进行添加操作时很多问题无法发现,在这里重新构造模型(一对一、一对多、多对多都有)。
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中的内容清空重新进行构建。
(5)删除数据重新进行数据库迁移
1)删除app01/migrations/下的文件
2)删除db.sqlite3
3)数据迁移
manage.py@stark_demo > makemigrations manage.py@stark_demo > migrate
(6)在stark中注册表:
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)
到此页面已经可以正常访问:
2、自定制配置modelform来构建添加页面
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())
3、构建add_view.html模板
<!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的样式。
显示效果如下所示:
4、给所有字段更换为中文
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)显示效果:
5、添加信息提交
(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)提交显示效果如下所示:
二、制作编辑页面
编辑页面视图和模板都与添加页面非常相似。
1、change_view视图编写
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,修改效果如下所示:
2、{% include 'form.html' %}优化代码重复
创建一个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>
执行效果:
确认后显示效果如下: