Django项目----快速实现增删改查组件(起步阶段!!!)

一、相关知识点回顾

1、什么是反射?

    可以用字符串的方式去访问对象的属性

 2、反射有四种方法?

hasattr(object,name):判断一个对象是不是有name属性或者方法
getattr:获取对象的属性或者方法,  需要注意的是,如果返回的是对象的方法,返回出来的是对象的内存地址, 如果需要运行这个方法,可以在后面添加一对()
setattr:给对象的属性赋值,如果属性不存在,先创建后赋值
delattr:删除该对象指定的一个属性

3、创建ModelForm的两种方式

# 方式一定义ModelForm
   class TestModelForm(ModelForm):
         class Meta:
             model = self.model_class
             fields = "__all__"

   方式二定义
  Meta = type("Meta", (object,), {"model": self.model_class, "fields": "__all__"})
  TestModelForm = type("TestModelForm", (ModelForm,), {"Meta": Meta})

二、具体流程以及相关知识点

1、路由系统

让url对应视图,这时的视图可以是一个元组,元组的里面放三个参数,第一个是个列表,这两种表示方式都是一样的,用那种都行

namespace的用法如下

v =>  ([],None,None)  namespace(是第三个参数),用于区分相同name的url,通过namespace为url添加一个前缀

如图:

namespace

2.流程:

1、一旦运行的时候都会去执行admin.py ,现在我们让你开始执行stark.py 文件,加上下面的这些(参考的是admin的源码,在每一个admin文件的里面点击进入)

from django.utils.module_loading import autodiscover_modules

    class StarkConfig(AppConfig):
        name = ‘stark‘ #应用名称

        def ready(self):
            autodiscover_modules(‘stark‘)   #在应用中创建的py文件和这个名字一样

切记一定要在sessings中配置一下:

‘app02.apps.App02Config‘,
‘stark.apps.StarkConfig‘,

2、然后再每个应用下面也创建一个stark.py的文件
       这样就像admin一样了,就开始执行site.redister了

3、这时候还没有site呢,需要自己实例化一个site
       在应用下创建一个service的文件夹,再创建一个v1.py文件,在里面写代码

4、在stark里面注册

需要注意的是:

v1.site.register(models.UserInfo)
->  执行 StackConfig的 changelist_view方法/add_view....

class UserInfoConfig(v1.StarkConfig):
        def changelist_view(self,request,*args,**kwargs):
            return HttpResponse(‘你猜我是谁?‘)

v1.site.register(models.UserInfo,UserInfoConfig)

---> 优先查看自己config中是否存在方法,不存在则执行基类 StackConfig的 changelist_view方法/add_view....

如图:

5、注册完成之后走urls。仿照admin的urls.。。。v1.site.urls
6、完了在v1.py中写代码

class StarkSite(object):
    def __init__(self):
        self._registry ={}  #放置处理请求对应关系
        ‘‘‘
        _registry = {
                    models.Role: StarkConfig(models.Role,v1.site),
                    models.UserInfo: StarkConfig(models.UserInfo,v1.site)
                    models.UserType: StarkConfig(models.UserType,v1.site)
                    models.Article: StarkConfig(models.Article,v1.site)
                }
        ‘‘‘
    def register(self,model_class,stark_config_class=None):
        if not stark_config_class:
            ‘‘‘stark_config_class是类对象,如果没有这个类就重新赋值,去执行StarkConfig‘‘‘
            stark_config_class = StarkConfig
        self._registry[model_class] = stark_config_class(model_class,self)
        #如果用户自己传进去类了,就用自己的,自己的需要继承StarkConfig。如果自己没有就找基类的,自己有就用自己的

    def get_urls(self):
        url_list = []
        for model_calss,stark_config_obj in self._registry.items():
            app_name = model_calss._meta.app_label#应用名称
            model_name = model_calss._meta.model_name#表的名称
            cur_url = url(r‘^{0}/{1}/‘.format(app_name,model_name),(stark_config_obj.urls,None,None))
            #这是的stark_config_obj是上面StarkConfig的实例对象。stark_config_obj.urls就会去找上面类的urls
            url_list.append(cur_url)
        return url_list
    @property #吧方法当属性来用
    def urls(self):
        return (self.get_urls(),None,‘stark‘)  #第三个参数是namesapce

动态生成类名和应用名图示:

在v1里面有两个类

- StarkConfig,用于为每一个类生成URL对应关系,并编写视图函数处理用户请求。
            [
                ^$  -> self.changelist_view
                ^add/$  -> self.add_view
                ^delete/$  -> self.delete_view
                ^change/$  -> self.dchange_view
            ]

        - StarkSite
        是一个容器,用于放置处理请求对应关系。
                    {
                        model.UserInfo: UserInfoConfig(model.UserInfo,self),
                        model.UserType: StarkConfig(model.UserType,self),
                    }    

具体来写:当然前面的StarkSite类已经写过了,那我们来看看StarkConfig这个类

以下的功能实现都是在StarkConfig这个类里面的

功能实现一:展示页面,让页面上动态显示表格

class StarkConfig(object):
    list_display = []
    def __init__(self, model_class, site):
        self.model_class = model_class
        self.site = site
    def change_list_views(self,request,*args,**kwargs):
        data_list = self.model_class.objects.all()
        ‘‘‘展示th的信息‘‘‘
        head_list = []
        for field_name in self.list_display:
            if isinstance(field_name,str):
                verbose_name = self.model_class._meta.get_field(field_name).verbose_name
            else:
                verbose_name = field_name(self,is_header=True)
            # yield {"verbose_name":verbose_name}
            head_list.append(verbose_name)

        ‘‘‘展示td的信息‘‘‘

        # [["id","name"],["id","name"],["id","name"],]
        new_data_list = []
        for row in data_list:
            temp = []
            for field_name in self.list_display:
                if isinstance(field_name,str):
                    #如果是字符串类型的就是用getattr的方式,因为对象不能.字符串
                    val = getattr(row,field_name)
                else:
                    val = field_name(self,row)
                temp.append(val)
                # yield {"val":val}
            new_data_list.append(temp)
        return render(request, "stark/change_list_views.html", {"data_list":new_data_list,"head_list":head_list})

在stark.py 中

strak.py
    print("sssss6666666")
    from app01 import models
    from stark.service import v1
    from django.utils.safestring import mark_safe
    class UserInfoConfig(v1.StarkConfig):
        def checkbox(self,obj=None,is_header=False):
            if is_header:
                return "选择"
            return mark_safe("<input type=‘checkbox‘ name=‘zzzz‘ value=‘%s‘/>"%obj.id)

        def edit(self,obj=None,is_header=False):
            if is_header:
                return "操作"
            return mark_safe("<a href=‘edit/%s‘>编辑</a>"%obj.id)
        list_display = [checkbox,"id","name",edit]

    v1.site.register(models.UserInfo,UserInfoConfig)
    v1.site.register(models.Role,UserInfoConfig)
    v1.site.register(models.UserType)

 功能二:当然我们现在把按钮是自己定制的,有与编辑,删除等都是我们很常用的,所以我们可以搞成默认的。在StarkConfig类里写

 # ===============吧删除,编辑,复选框设置默认按钮==================

    def checkbox(self,obj=None,is_header=False):
        if is_header:
            return "选择"
        return mark_safe("<input type=‘checkbox‘ name=‘zzzz‘ value=‘%s‘/>"%obj.id)

    def edit(self,obj=None,is_header=False):
        if is_header:
            return "操作"
        return mark_safe("<a href=‘%s‘>编辑</a>"%(self.get_change_url(obj.id),))

    def delete(self,obj=None,is_header=False):
        if is_header:
            return "删除"
        #动态跳转路径,反向解析,因为每次都要用到,我们可以吧它封装到一个函数
        return mark_safe("<a href=‘%s‘>删除</a>"%self.get_delete_url(obj.id))

    #做默认的删除和编辑。对这个方法重写的时候可以吧权限管理加进去,
    # 当它都什么权限的时候显示什么按钮。
    def get_list_display(self):
        data = []
        if self.list_display:
            data.extend(self.list_display) #在新的列表里面吧list_display扩展进来
            data.append(StarkConfig.edit)  #因为是默认的,直接在类里面去调用edit
            data.append(StarkConfig.delete)
            data.insert(0,StarkConfig.checkbox)
        return data

 功能三:默认显示添加按钮

 show_add_btn = True
    # ======这个方法可自定制(如果把show_add_btn设置为False就不会显示添加按钮)=====
    def get_show_add_btn(self):
        return self.show_add_btn

 功能四:当点击编辑,删除,添加按钮的时候的跳转路径,动态生成

return render(request, "stark/change_list_views.html",{"add_url":self.get_add_url(),"show_add_btn":self.get_show_add_btn()})

利用反向解析reverse

 # =================url相关,reverse反向解析=============
    def get_change_url(self,nid):
        name = "stark:%s_%s_change"%(self.model_class._meta.app_label,self.model_class._meta.model_name)
        edit_url = reverse(name,args=(nid,))  #反向解析只要找到他的name属性,就会找到他对应的路径
        return edit_url

    def get_add_url(self):
        name = "stark:%s_%s_add" % (self.model_class._meta.app_label, self.model_class._meta.model_name)
        edit_url = reverse(name)
        return edit_url

    def get_delete_url(self, nid):
        name = "stark:%s_%s_delete" % (self.model_class._meta.app_label, self.model_class._meta.model_name)
        edit_url = reverse(name,args=(nid,))
        return edit_url

    def get_list_url(self):
        name = "stark:%s_%s_changelist" % (self.model_class._meta.app_label, self.model_class._meta.model_name)
        edit_url = reverse(name)
        return edit_url

 功能五:添加,删除,编辑功能(利用MOdelForm)

  model_form_class=None
    def get_model_form_class(self):
        if self.model_form_class:   #如果自己定制了就用自己的,在这就什么也不返回了,如果没有自己定义就返回默认的这个Form
            return self.model_form_class
        # 方式一定义ModelForm
        # class TestModelForm(ModelForm):
        #     class Meta:
        #         model = self.model_class
        #         fields = "__all__"
        # return TestModelForm
        # 方式二定义
        Meta = type("Meta", (object,), {"model": self.model_class, "fields": "__all__"})
        TestModelForm = type("TestModelForm", (ModelForm,), {"Meta": Meta})
        return TestModelForm
    def add_views(self,request,*args,**kwargs):
        model_form_class = self.get_model_form_class()
        if request.method=="GET":
            form = model_form_class()
            return render(request,"stark/add_view.html",{"form":form})
        else:
            form = model_form_class(request.POST)
            if form.is_valid():
                form.save()
                return redirect(self.get_list_url())
            else:
                return render(request, "stark/add_view.html", {"form": form})

    def delete_view(self, request,nid, *args, **kwargs):
        self.model_class.objects.filter(pk=nid).delete()
        return redirect(self.get_list_url())

    def change_views(self, request,nid, *args, **kwargs):
        model_form_class = self.get_model_form_class()
        obj = self.model_class.objects.filter(pk=nid).first()
        if not obj:
            return redirect(self.get_list_url())
        if request.method == "GET":
            form = model_form_class(instance=obj)
            return render(request, "stark/edit_view.html", {"form": form})
        else:
            form = model_form_class(data=request.POST,instance=obj)
            if form.is_valid():
                form.save()
                return redirect(self.get_list_url())
            else:
                return render(request, "stark/edit_view.html", {"form": form})

 功能六:额外扩展url

  # =============路由系统,对应相应的视图函数=====================
    def get_urls(self):
        app_model_name = (self.model_class._meta.app_label,self.model_class._meta.model_name)
        all_url = [
            url(r‘^$‘, self.change_list_views,name="%s_%s_changelist"%app_model_name),
            url(r‘^add/$‘, self.add_views,name="%s_%s_add"%app_model_name),
            url(r‘^(\d+)/delete/$‘, self.delete_view,name="%s_%s_delete"%app_model_name),
            url(r‘^(\d+)/change/$‘, self.change_views,name="%s_%s_change"%app_model_name),
        ]
        all_url.extend(self.extra_urls())
        return all_url

    # ===========额外扩展url(用户可以进行随意扩展)==========
    def extra_urls(self):
        return []

    @property
    def urls(self):
        return self.get_urls()

三、使用

#!usr/bin/env python
# -*- coding:utf-8 -*-
print("sssss6666666")
from app01 import models
from django.conf.urls import url
from stark.service import v1
from django.shortcuts import render,HttpResponse,redirect
from django.forms import ModelForm
class UserInfoConfig(v1.StarkConfig):
    # 1、
    list_display = ["id","name","email"]
    # list_display = []
   # 2、
    def extra_urls(self):
        url_list =[
            url(r‘^xxxx/$‘,self.func),
        ]
        return url_list

    def func(self,request):
        return HttpResponse("我是额外添加的路径哦....")
    # 3、
    # show_add_btn=False   #默认是True的,如果不让显示添加按钮可以自定制

    # 4、
    def get_model_form_class(self):
        class MyModelForm(ModelForm):
            class Meta:
                model = self.model_class
                fields = "__all__"
                error_messages={
                    "name":{"required":"用户名不能为空"},
                    "email":{"invalid":"邮箱格式不正确"}
                }
        return MyModelForm
    # 5、
    def delete_view(self, request,nid, *args, **kwargs):
        if request.method=="GET":
            return render(request,"stark/delete_view.html",{"quxiao_url":self.get_list_url()})
        else:
            self.model_class.objects.filter(pk=nid).delete()
            return redirect(self.get_list_url())
v1.site.register(models.UserInfo,UserInfoConfig)
===================================================
class RoleConfig(v1.StarkConfig):

    list_display = ["id","name"]
    # list_display = []
    def extra_urls(self):
        url_list =[
            url(r‘^aaaa/$‘,self.func),
        ]
        return url_list

    def func(self,request):
        return HttpResponse("我是额外添加的路径哦....")

    # show_add_btn=False   #默认是True的,如果不让显示添加按钮可以自定制

    def get_model_form_class(self):
        class MyModelForm(ModelForm):
            class Meta:
                model = self.model_class
                fields = "__all__"
                error_messages={
                    "name":{"required":"用户名不能为空"},
                }
        return MyModelForm
v1.site.register(models.Role,RoleConfig)
v1.site.register(models.UserType)
======================================================
class HostConfig(v1.StarkConfig):
    def ip_port(self, obj= None,is_header=False):
        if is_header:  #如果是True就返回的是th的,默认就是True
            return "自定义列"
        return "%s_%s"%(obj.id,obj.port,)  #当是False的时候就返回的是td的
    list_display = ["id","name","ip","port",ip_port]

    # =====扩展一个url路径======
    def extra_urls(self):
        url_list = [
            url(r‘^report/$‘, self.report_view),
        ]
        return url_list
    def report_view(self,request):
        return HttpResponse("<h3>这是我给报表另外添加的一个路径</h3>")
v1.site.register(models.Host,HostConfig)

四、总结:

注意:如果是在应用里面建的static文件,是不用再settings里面配置的,就可以用
    需要知道的知识点
     1、for model_calss,stark_config_obj in self._registry.items():
            app_name = model_calss._meta.app_label#应用名称
            model_name = model_calss._meta.model_name#表的名称
            self.model_class._meta.get_field(field_name).verbose_name  #得到字段的verbose_name

    2、   if isinstance(field_name,str):
                    #如果是字符串类型的就是用getattr的方式,因为对象不能.字符串
                    val = getattr(row,field_name)

    3、   for field_name in self.list_display:
                if isinstance(field_name,str):
                    #如果是字符串类型的就是用getattr的方式,因为对象不能.字符串
                    val = getattr(row,field_name)
                else:  #如果不是字符串传进来的就是函数,所以得加括号调用函数
                    val = field_name(field_name,row)
                temp.append(val)
            new_data_list.append(temp)  

    4、吧方法当属性来用
    @property
    def urls(self):
        return self.get_urls()

一个小知识:
    1、什么时候加括号,什么时候不加括号
       当需要一个返回值的时候,就去执行函数,加括号
       当你不需要返回什么,直接告诉它函数名,让他去找这个函数名。就不用加括号

五、知识点补充

补充:用bootstrap修改样式

1、include:用include直接把单独的标签可以引入到html中。目的是减少代码的冗余

{% include "stark/form.html" %}
stark/form.html
<form method="post"  class="form-horizontal" novalidate>
    {% csrf_token %}
    {% for field in form %}
        <div class="col-sm-6">
            <div class="form-group">
                <label for="inputEmail3" class="col-sm-2 control-label">{{ field.label }}</label>
                <div class="col-sm-10">
                    {{ field }}
                    {{ field.errors.0 }}
                </div>
            </div>
        </div>
    {% endfor %}
    <div class="col-sm-offset-11 col-sm-1">
        <input type="submit" class="btn btn-primary" value="提交">
    </div>
</form>

css样式

.form-horizontal input[type="text"],input[type=‘email‘],input[type=‘password‘],input[type=‘checkbox‘],input[type=‘number‘],select,textarea{
            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;
        }

补充二:需要优化的导入静态文件的方式

{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width">
    <title>Title</title>
    <link rel="stylesheet" href="{% static ‘/bootstrap-3.3.7-dist/css/bootstrap.css‘%} ">
    <link rel="stylesheet" href="{% static ‘/css/stark_form.css‘ %}">
</head>
<body>
<h3>添加页面</h3>
{% include "stark/form.html" %}
</body>
</html>

原文地址:https://www.cnblogs.com/jiangshanduojiao/p/9034511.html

时间: 2024-10-11 04:26:05

Django项目----快速实现增删改查组件(起步阶段!!!)的相关文章

django之创建第8-1个项目-数据库之增删改查/数据库数据显示在html页面

1.为test.DB数据库预先创建下面数据 1    张三    16    2015-01-02    12    李四    17    2015-01-04    13    王五    14    2015-04-24    0 2.配置C:\djangoweb\helloworld\blog\urls.py文件 # -*- coding: UTF-8 -*- from django.conf.urls import patterns, include, url urlpatterns

popup的简单应用举例(具体在增删改查组件中用到)以及补充的知识点

popup的简单应用举例(具体在增删改查组件中用到)以及补充的知识点 一.首先说一下自执行函数 1. 立即执行函数是什么?也就是匿名函数 立即执行函数就是 声明一个匿名函数 马上调用这个匿名函数 2.popup的举例 点击,弹出一个新的窗口.保存完事,页面不刷新数据就返回了.(点击admin的+,弹出的框就是用popup来做的) 具体操作步骤: 1.urls.py urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/',

BootstrapTable+KnockoutJS自定义T4模板快速生成增删改查页面

前言:上篇介绍了下ko增删改查的封装,确实节省了大量的js代码.博主是一个喜欢偷懒的人,总觉得这些基础的增删改查效果能不能通过一个什么工具直接生成页面效果,啥代码都不用写了,那该多爽.于是研究了下T4的语法,虽然没有完全掌握,但是算是有了一个大致的了解.于是乎有了今天的这篇文章:通过T4模板快速生成页面. KnockoutJS系列文章: JS组件系列——BootstrapTable+KnockoutJS实现增删改查解决方案(一) JS组件系列——BootstrapTable+KnockoutJS

Python学习---django之ORM的增删改查180125

模型常用的字段类型参数 <1> CharField        #字符串字段, 用于较短的字符串.        #CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.<2> IntegerField       #用于保存一个整数.<3> FloatField        # 一个浮点数. 必须 提供两个参数:    参数    描述        # max_digits    总位数(不

【greenDAO3】 项目搭建与增删改查操作

最近需要开始一个新的项目了,考虑到既然是新项目了,那么一些常用的框架肯定也要用当下最火的!这次的新项目中涉及到了本地数据存储,很早前有个项目的本地数据库框架用的是ActiveAndroid,github找了下这个框架,发现已经两年多已经没有更新了.然后就想到了一直没有时间去涉及到的greenDAO,github一搜索,哦呦?star有5000+,并且依然保持着很高的更新频率,并且性能远远的高于activeAndroid(见下图),果断选用. 刚开始想偷偷懒,大致浏览了下greenDAO官网后就开

ASP.NET WebAPI 项目示例(增删改查)

1.WebApi是什么 ASP.NET Web API 是一种框架,用于轻松构建可以由多种客户端(包括浏览器和移动设备)访问的 HTTP 服务.ASP.NET Web API 是一种用于在 .NET Framework 上构建 RESTful 应用程序的理想平台. 可以把WebApi看成Asp.Net项目类型中的一种,其他项目类型诸如我们熟知的WebForm项目,Windows窗体项目,控制台应用程序等. WebApi类型项目的最大优势就是,开发者再也不用担心客户端和服务器之间传输的数据的序列化

框架 day39-42 SSH整合练习项目CRM(配置文件,增删改查,ajax,上传/下载,分页,BaseDao/Action)

1     配置文件 1.1   spring配置 1.1.1       介绍     加载properties     配置数据源DataSource     配置SessionFactory , 加载所有hbm.xml     hibernate事务管理     使用 <import > 所有的模块都使用单独配置文件 1.1.2       使用源码包     使用config源码,将源码和配置文件分开存放,方便程序的维护. 1.1.3       spring核心 1.1.

django orm 单表增删改查

一 简单增删改查 1.增 User.objects.create(name='Alan', age=10, birthday='2018-08-08') user = User(name='Alan', age=10, birthday='2018-08-08') user.save() 2.查询 # 操作的结果拥有是一个list users = User.objects.filter(name='Owen') # 只能操作有且只有一条数据记录 user = User.object.set(id

django -- ORM实现图书增删改查

表结构设计 上篇我们实现了出版社的增删改查,出版社数据表有两个字段id和name,那图书的表结构怎么设计呢?图书也要有一个主键id,还要有一个名称title,是哪个出版社的,要有个字段press和Press表里的id对应,这样图书就需要三个字段,id,title,press 创建表 # 图书表 class Book(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=