仿照admin写一个startk组件

settings.py

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',
]
View Code

 urls.py

from stark.sites import site
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^stark/', site.urls),
]
View Code

 

stark/apps.py

from django.utils.module_loading import autodiscover_modules




class StarkConfig(AppConfig):
    name = 'stark'

    def ready(self):
        autodiscover_modules('stark')
View Code

 

stark/sites.py

from django.utils.safestring import mark_safe
from django.shortcuts import HttpResponse,render,redirect
from django.core.urlresolvers import reverse
from django.forms import ModelForm
class DataList:
    def __init__(self,config,obj_list):
        self.config=config
        self.obj_list=obj_list
    def get_header_list(self):
        header_list = []
        for i in self.config.new_list_display():
            if isinstance(i, str):
                if i == "__str__":
                    val = self.config.model._meta.model_name.upper()
                else:
                    filed_obj = self.config.model._meta.get_field(i)
                    val = filed_obj.verbose_name
            else:
                val = i(is_header=True)
            header_list.append(val)
        return header_list
    def get_body_list(self):
        new_data_list = []
        for obj in self.obj_list:
            tmp = []
            for filed in self.config.new_list_display():
                if isinstance(filed, str):
                    try:
                        from django.db.models.fields.related import ManyToManyField
                        filed_obj = self.config.model._meta.get_field(filed)
                        if isinstance(filed_obj, ManyToManyField):
                            li = []
                            for i in getattr(obj, filed).all():
                                li.append(str(i))
                            val = ",".join(li)
                        else:
                            val = getattr(obj, filed)
                    except Exception as e:
                        val = getattr(obj, filed)
                else:
                    val = filed(obj=obj)
                tmp.append(val)
            new_data_list.append(tmp)
        return new_data_list




class ModelStark:

    list_display = ('__str__',)
    search_fields=[]
    actions=[]
    def __init__(self,model,site):
        self.model=model
        self.site=site


    def edit(self,is_header=False,obj=None):
        if is_header:
            return "操作"
        info = self.model._meta.app_label, self.model._meta.model_name
        return mark_safe('<a class="btn btn-warning" href="%s">编辑</a>'%reverse('%s_%s_change'%info,args=(obj.pk,)))

    def delete(self,is_header=False,obj=None):
        if is_header:
            return "操作"
        info = self.model._meta.app_label, self.model._meta.model_name
        return mark_safe('<a class="btn btn-danger" href="%s">删除</a>'%reverse('%s_%s_delete'%info,args=(obj.pk,)))

    def checkbox(self, obj=None, is_header=False):
        if is_header:
            return "选择"
        return mark_safe("<input type='checkbox' name=checked_data value=%s>" % obj.pk)

    def new_list_display(self):
        tmp=[]
        tmp.append(self.checkbox)
        tmp.extend(self.list_display)
        tmp.append(self.edit)
        tmp.append(self.delete)
        return tmp

    def get_search_condition(self,request):
        from django.db.models import Q
        search_condition=Q()
        search_condition.connector="or"
        val=request.GET.get("q")
        if val:
            for field in self.search_fields:
                search_condition.children.append((field+"__contains",val))
        return search_condition


    def get_actions_list(self):
        li=[]
        for func in self.actions:
            dic={}
            dic["name"]=func.__name__
            dic["desc"]=func.desc
            li.append(dic)
        return li

    def get_list_url(self):
        info = self.model._meta.app_label, self.model._meta.model_name
        return reverse('%s_%s_list'%info)


    def list_view(self,request):
        if request.method=="POST":
            print(request.POST)
            action=request.POST.get("action")
            checked_data=request.POST.getlist("checked_data")
            action=getattr(self,action)
            action(checked_data)
        search_condition=self.get_search_condition(request)
        from django.db.models import Q
        filter_condition = Q()
        for key, value in request.GET.items():
            filter_condition.children.append((key, value))
        obj_list = self.model.objects.all().filter(search_condition).filter(filter_condition)
        data_list=DataList(self,obj_list)
        return render(request, "list.html", locals())

    def get_modelform(self):
        from django.forms import ModelForm
        class StarkModelForm(ModelForm):
            class Meta:
                model=self.model
                fields="__all__"
        return StarkModelForm

    def add_view(self,request):

        if request.method=="POST":
            form= self.get_modelform()(request.POST)

            if form.is_valid():
                form.save()

                return redirect(self.get_list_url())
            else:
                return render(request, "add.html", locals())

        form=self.get_modelform()()


        return render(request, "add.html", locals())
    def delete_view(self,request,nid):
        if request.method == "POST":
            self.model.objects.get(pk=nid).delete()

            return redirect(self.get_list_url())
        url = self.get_list_url()
        return render(request, "delete.html", locals())

    def extra_url(self):
        return []


    def change_view(self,request,nid):
        obj = self.model.objects.filter(pk=nid).first()

        if request.method == "POST":
            form = self.get_modelform()(request.POST, instance=obj)

            if form.is_valid():
                form.save()

                return redirect(self.get_list_url())

        form = self.get_modelform()(instance=obj)

        return render(request, "change.html", locals())

    @property
    def get_url2(self):
        from django.conf.urls import url
        info = self.model._meta.app_label, self.model._meta.model_name
        urlpatterns = [
            url(r'^$', self.list_view, name='%s_%s_list' % info),
            url(r'^add/$', self.add_view, name='%s_%s_add' % info),
            url(r'^(\d+)/delete/$', self.delete_view, name='%s_%s_delete' % info),
            url(r'^(\d+)/change/$', self.change_view, name='%s_%s_change' % info),
        ]
        return urlpatterns


class StarkSite(object):
    def __init__(self, name='stark'):
        self._registry = {}  # model_class class -> admin_class instance
        self.name = name

    def register(self, model, admin_class=None, **options):
        if not admin_class:
            admin_class = ModelStark
        self._registry[model] = admin_class(model, self)

    def get_url(self):
        from django.conf.urls import url
        urlpatterns=[]
        for model,model_stark in self._registry.items():
            urlpatterns+=[
                url(r'^%s/%s/'%(model._meta.app_label, model._meta.model_name),(model_stark.get_url2,None,None)),
                          ]


        return urlpatterns
    @property
    def urls(self):
        return self.get_url(),None,None
site = StarkSite()
View Code

 

app01/models.py

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,verbose_name="姓名")
    age = models.IntegerField(verbose_name="年龄")

    # 与AuthorDetail建立一对一的关系
    authorDetail = models.OneToOneField(to="AuthorDetail")

    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.addr

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,verbose_name="书名")
    publishDate = models.DateField(verbose_name="发行日期")
    price = models.DecimalField(max_digits=5, decimal_places=2,verbose_name="价格")
    keepNum = models.IntegerField()
    commentNum = models.IntegerField()

    # 与Publish建立一对多的关系,外键字段建立在多的一方
    publish = models.ForeignKey(to="Publish", to_field="nid",verbose_name="出版社")

    # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
    authors = models.ManyToManyField(to='Author',verbose_name="作者")

    def __str__(self):
        return self.title
View Code

 

app01/stark.py

from stark.sites import site,ModelStark
from .models import *
# Register your models here.


class BookStark(ModelStark):
    list_display = ("title","publishDate","price","publish","authors")
    search_fields = ["title"]

    def patch_delete(self,selected_pk):
        self.model.objects.filter(pk__in=selected_pk).delete()
    patch_delete.desc="批量删除"




    actions=[patch_delete]



site.register(Author)
site.register(AuthorDetail)
site.register(Publish)
site.register(Book,BookStark)
View Code

 

templates/list.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<h3>查看数据</h3>

<div class="container">
    <div class="row">
        <div class="col-md-8">


            {% if self.search_fields %}
                <form class="form-inline pull-right" method="get" action="" style="margin-bottom: 10px">
            {% else %}
                <form class="form-inline pull-right hidden" method="get" action="" style="margin-bottom: 10px">
            {% endif %}

            {% csrf_token %}
            <div class="form-group">
                <input type="text" class="form-control" name="q">
            </div>
            <button type="submit" class="btn btn-default">搜索</button>
            </form>
            <form action="" method="post">
            {% csrf_token %}
                <select class="form-control pull-left" name="action" style="width: auto">

            {% for action in  self.get_actions_list %}
                <option value="{{ action.name }}">{{ action.desc }}</option>
            {% endfor %}
            </select>
                <input type="submit" class="btn btn-default" value="执行">
            <table class="table table-bordered table-hover table-striped">
                <thead>
                <tr>
                    {% for foo in data_list.get_header_list %}
                        <th>{{ foo }}</th>
                    {% endfor %}

                </tr>
                </thead>
                <tbody>
                {% for new_data in data_list.get_body_list %}
                    <tr>
                        {% for foo in new_data %}
                            <td>{{ foo }}</td>
                        {% endfor %}

                    </tr>
                {% endfor %}

                </tbody>
            </table>
            </form>

        </div>
    </div>
</div>


</body>
</html>
View Code

 

templates/add.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <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>
View Code

 

templates/change.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <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>
View Code

 

templates/form.html

<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-1">

            <form action="" method="post" novalidate>
                {% csrf_token %}

                {% for field in form %}
                    <div class="form-group">
                        <label for="">{{ field.label }}</label>
                        {{ field }} <span class="pull-right" style="color: red">{{ field.errors.0 }}</span>
                    </div>
                {% endfor %}

                <input type="submit" class="btn btn-default">
            </form>

        </div>
    </div>
</div>
View Code

 

templates/delete.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
     <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

</head>
<body>

<h3>删除页面</h3>


<form action="" method="post">
    {% csrf_token %}
    <input type="submit" value="确认删除">
    <a href="{{ url }}">取消</a>
</form>


</body>
</html>
View Code

 

posted @ 2018-06-29 03:51  guoyunlong666  阅读(243)  评论(0编辑  收藏  举报