• django 1


     1. Django的命令:

    1. 下载安装
    pip install django==1.11.16 -i 源

    2. 创建项目
    django-admin startproject 项目名称

    3. 启动项目
    cd 项目根目录下
    python manage.py runserver # 127.0.0.1:8000
    python manage.py runserver 80 # 127.0.0.1:80
    python manage.py runserver 0.0.0.0:80 # 0.0.0.0:80 

    4. 创建APP
    python manage.py startapp app名称

    注册
    5. 数据库相关
    python manage.py makemigrations # 记录model的变更情况
    python manage.py migrate # 将变更记录同步到数据库中

    Django 的路由系统 

    URL配置(URLconf)就像Django所支撑网站的目录。它的本质是URL与要为该URL调用的视图函 数之间的映射表。

    我们就是以这种方式告诉Django,遇到哪个URL的时候,要对应执行哪个函数。

    基本格式

    from django.conf.urls import url
    from app1 import views as aap1vw
    from app2 import views as aap2vw
    urlpatterns
    = [ url(正则表达式, app1vw,参数,别名),
       url(正则表达式, app2vw, 参数, 别名), ]

    示例:

    from django.conf.urls import url
    from . import views
    
    urlpatterns = [
        url(r'^articles/2003/$', views.special_case_2003),
        url(r'^articles/([0-9]{4})/$', views.year_archive),
        url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
        url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
    ]

    Django 2.0版本中的路由系统是下面的写法(官方文档):

    复制代码
    from django.urls import path,re_path
    
    urlpatterns = [
        path('articles/2003/', views.special_case_2003),         #与1的区别一个是url 一个是path
        path('articles/<int:year>/', views.year_archive),
        path('articles/<int:year>/<int:month>/', views.month_archive),
        path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
    ]
    复制代码

    正则匹配url

    from django.conf.urls import url
    
    from . import views
    
    urlpatterns = [
        url(r'^articles/2003/$', views.special_case_2003),
        url(r'^articles/([0-9]{4})/$', views.year_archive),
        url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
        url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
    ]

    注意事项 

    1. urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。 
    2. 若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
    3. 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
    4. 每个正则表达式前面的'r' 是可选的但是建议加上。
    # 是否开启URL访问地址后面不为/跳转至带有/的路径的配置项
    APPEND_SLASH=True

    Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其作用就是自动在网址结尾加'/'。

    其效果就是:

    我们定义了urls.py:

    from django.conf.urls import url
    from app01 import views
    
    urlpatterns = [
        url(r'^blog/$', views.blog),
    ]

    访问 http://www.example.com/blog 时,默认将网址自动转换为 http://www.example/com/blog/ 。

    如果在settings.py中设置了 APPEND_SLASH=False,此时我们再请求 http://www.example.com/blog 时就会提示找不到页面。

     分组命名匹配

    上面的示例使用简单的正则表达式分组匹配(通过圆括号)来捕获URL中的值并以位置参数形式传递给视图。

    在更高级的用法中,可以使用分组命名匹配的正则表达式组来捕获URL中的值并以关键字参数形式传递给视图。

    在Python的正则表达式中,分组命名正则表达式组的语法是(?P<name>pattern),其中name是组的名称,pattern是要匹配的模式。

    下面是以上URLconf 使用命名组的重写:

    复制代码
    from django.conf.urls import url
    
    from . import views
    #将匹配到括号里的url内容传给views,views必须的写形参接收
    urlpatterns = [
        url(r'^articles/2003/$', views.special_case_2003),
        url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),  
        url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), 
        url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
    ]
    复制代码

    这个实现与前面的示例完全相同,只有一个细微的差别:捕获的值作为关键字参数而不是位置参数传递给视图函数。

    例如,针对URL /articles/2017/12/相当于按以下方式调用视图函数:

    views.month_archive(request, year="2017", month="12")        #viewa必须的带接收的参数

    在实际应用中,使用分组命名匹配的方式可以让你的URLconf 更加明晰且不容易产生参数顺序问题的错误,但是有些开发人员则认为分组命名组语法太丑陋、繁琐。

    至于究竟应该使用哪一种,你可以根据自己的喜好来决定。

    视图函数中指定默认值

    # urls.py中
    from django.conf.urls import url
    
    from . import views
    
    urlpatterns = [                        #不同的url找同一个视图函数
        url(r'^blog/$', views.page),
        url(r'^blog/page(?P<num>[0-9]+)/$', views.page),  
    ]
    
    # views.py中,可以为num指定默认值
    def page(request, num="1"):
        pass

    在上面的例子中,两个URL模式指向相同的view - views.page - 但是第一个模式并没有从URL中捕获任何东西。

    如果第一个模式匹配上了,page()函数将使用其默认参数num=“1”,如果第二个模式匹配,page()将使用正则表达式捕获到的num值。

    include使urls.py 文件放在自己app目录里

    将django项目里的urls.py 文件复制到app1 和app2里

    项目里的urls.py文件

    from django.conf.urls import url, include  #引用include
    
    urlpatterns = [
        url(r'app1/', include('app1.urls')),      #r''可以为空,也可以匹配1级url,include 找到app1里的urls文件
        url(r'app1/', include('app1.urls')),
        url(r'app2/', include('app2.urls')),
        url(r'app2/', include('app2.urls')),
        url(r'app2/', include('app2.urls')),
        ]

    app1里的urls.py文件

    from django.conf.urls import url
    from app1 import views as aap1vw
    
    urlpatterns = [
        #此时的url前边要加上/app1/ 即127.0.0.1/app1/zzzz/       
        url(r'zzzz/',aap1vw.zzzz),

    app2里的urls.py文件

    from django.conf.urls import url
    
    from app2 import views as aap2vw
    
    urlpatterns = [
        url(r'xxxx/',aap2vw.xxxx),
        url(r'dddd/',aap2vw.dddd),
        url(r'cccc/',aap2vw.cccc),
    ]

     使用上述方法会导致 html页面里的和views里写死的url不能使用,解决办法:给url命名和反向解析:

    url命名和反向解析

      给url起一个别名   通过反向解析,通过别名动态拿到url地址

    在app1里的urls.py文件里给url地址起别名

    from django.conf.urls import url
    from app1 import views as aap1vw
    
    urlpatterns = [
        url(r'zhanshi/',aap1vw.Zhan_shi,name='zhanshi'),      #增加别名
        url(r'add/', aap1vw.Add,name='add'), 
        url(r'update/', aap1vw.Update,name='update'),
        url(r'del/', aap1vw.Del,name='del'),
    ]

    修改html展示页里的url,使用url别名   模板:  {% url '别名' %}

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/css/bootstrap.min.css">
        <link rel="stylesheet" href="/static/css/das.css">
    </head>
    <body>
    
    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container-fluid">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
                        aria-expanded="false" aria-controls="navbar">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#">出版社管理</a>
            </div>
            <div id="navbar" class="navbar-collapse collapse">
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="#">Dashboard</a></li>
                    <li><a href="#">Settings</a></li>
                    <li><a href="#">Profile</a></li>
                    <li><a href="#">Help</a></li>
                </ul>
                <form class="navbar-form navbar-right">
                    <input type="text" class="form-control" placeholder="Search...">
                </form>
            </div>
        </div>
    </nav>
    
    <div class="container-fluid">
        <div class="row">
            <div class="col-sm-3 col-md-2 sidebar">
                <ul class="nav nav-sidebar"> 
                    <li class="active"><a href="{% url 'zhanshi' %}">出版社列表 <span class="sr-only">(current)</span></a></li>       {#将 之前的/展示/ 改为 {% url 'zhanshi' %}#} 动态或其url别名对应的url路径
                </ul>
            </div>
            <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
                <h2 class="sub-header">出版社信息</h2>
                <div class="table-responsive">
                <a href="{% url 'add' %}" class="btn btn-primary">添加</a>
                    <table class="table table-striped table-hover">
                        <thead>
                        <tr>
                            <th>序号<th>
                            <th>ID</th>
                            <th>出版社名称</th>
                            <th>操作</th>
                        </tr>
                        </thead>
                        <tbody>
                        {% for foo in all %}
                            <tr>
                                <td>{{ forloop.counter }}</td>
                                <td>{{ foo.pk }}</td>
                                <td>{{ foo.mane }}</td>
                                <td>
                                    <a href="{% url 'del' %}?sh={{ foo.pk }}" class="btn btn-danger btn-sm">删除</a>
                                    <a href="{% url 'update' %}?zj={{ foo.pk }}" class="btn btn-primary btn-sm">编辑</a>
                                </td>
                            </tr>
                        {% endfor %}
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
    
    </body>
    </html>

    修改views.py 里写死的redirect 跳转的url .(需要在引用reverse方法)   模板   reverse('别名')

    from django.shortcuts import render,redirect,reverse     #引用reverse方法
    from app1 import models
    
    def Zhan_shi(request):
        all_tusu = models.tusu.objects.all()
        return render(request,'zhanshi.html',{'all': all_tusu})
    def Add(request):
        if request.method == 'POST':
            newname = request.POST.get('newname')
            models.tusu.objects.create(mane=newname)
            return redirect(reverse('zhanshi'))                     #将之前写的跳转写死的redirect('/zhanshi/') 修改为获取别名的redirect(reverse('zhanshi'))
        return render(request,'add.html')
    def Update(request):
        pk = request.GET.get('zj')
        obj = models.tusu.objects.filter(pk=pk).first()
        if request.method == 'POST':
            newname = request.POST.get('newname')
            obj.mane = newname
            obj.save()
            return redirect(reverse('zhanshi'))
        return render(request,'update.html', {'obj' : obj} )
    def Del(request):
        pk = request.GET.get('sh')
        obj = models.tusu.objects.filter(pk=pk).first()
        if request.method == 'POST':
            dname = request.POST.get('dname')
            models.tusu.objects.get(mane = dname).delete()
            return redirect(reverse('zhanshi'))
        return render(request,'del.html',{'obj':obj})

    命名空间模式

    用来解决 不同app中,url名相同路由找错的问题

    即使不同的APP使用相同的URL名称,URL的命名空间模式也可以让你唯一反转命名的URL。

    设置项目里的urls.py

    from django.conf.urls import url, include
    
    urlpatterns = [
        url(r'app1/', include('app1.urls',namespace='app1')),     #namespace 相当于增加一个别名,用来让模板和views来识别出唯一的url路径
        url(r'app2/', include('app2.urls',namespace='app2'))
        ]

     app1中的urls.py

    from django.conf.urls import url
    from app01 import views
     
    app_name = 'app01'
    urlpatterns = [
        url(r'^zhanshi', views.yemian1, name='zhanshi'),
        url(r'^add', views.yemian2, name='add'),       
    ]

     app2中的urls.py

    from django.conf.urls import url
    from app01 import views
     
    app_name = 'app01'
    urlpatterns = [
        url(r'^zhanshi', views.yemian1, name='zhanshi'),
        url(r'^add', views.yemian2, name='add'),       
    ]

    此时app1和app2里的别名相同,要想确认唯一页面,就要把namespace对应的值加入到前后端代码里

    前端使用方法

    {% url 'app1:zhanshi' %}    #在app里的url的别名前加上 views里的url别名

    后端使用方法

    return redirect(reverse('app1:zhanshi')        #和前端一样也是前面加views里的url别名

    MVC框架和MTV框架

    详细介绍:http://www.ruanyifeng.com/blog/2007/11/mvc.html

    MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller),具有耦合性低、重用性高、生命周期成本低等优点。

     

    Django框架的设计模式借鉴了MVC框架的思想,也是分成三部分,来降低各个部分之间的耦合性。

    Django框架的不同之处在于它拆分的三部分为:Model(模型)、Template(模板)和View(视图),也就是MTV框架。

    Django的MTV模式

    Model(模型):负责业务对象与数据库的对象(ORM)

    Template(模版):负责如何把页面展示给用户

    View(视图):负责业务逻辑,并在适当的时候调用Model和Template

     此外,Django还有一个urls分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template

    Django框架图示

    Django的View(视图)

    一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。

    响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。

    无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你当前项目目录下面。除此之外没有更多的要求了——可以说“没有什么神奇的地方”。为了将代码放在某处,大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中。

    CBV和FBV

    我们之前写过的都是基于函数的view,就叫FBV。还可以把view写成基于类CBV的。

    FBV (之前写的添加出版舍)

    def Add(request):               #此处定义的是函数 是FBV  F是function
        if request.method == 'POST':
            newname = request.POST.get('newname')
            models.tusu.objects.create(mane=newname)
            return redirect(reverse('app1:zhanshi'))
        return render(request,'add.html')

    CBV(C为类,把FBV改为CBV)

    先修改 对应的url

    from django.conf.urls import url
    from app1 import views as aap1vw
    
    urlpatterns = [
        url(r'zhanshi/',aap1vw.Zhan_shi,name='zhanshi'),
        url(r'add1/', aap1vw.Add,name='add'),                #这是FBV的url
        url(r'add2/', aap1vw.AddC.as_view(),name='add'),     #这是CBV的url 区别在于后边多了.as_view()
        url(r'update/', aap1vw.Update, name='update'),
        url(r'del/', aap1vw.Del,name='del'),

    写CBF方法

    from django.views import View      #在VBV的基础上增加引用View方法
    
    class AddC(View):                  #定义类名并继承View
        def get(self,request):               #与FBV的区别在于直接把get和post请求处理的逻辑区分开了 逻辑更清晰
            return render(request, 'add.html')
        def post(self,request):
            newname = request.POST.get('newname')
            models.tusu.objects.create(mane=newname)
            return redirect(reverse('app1:zhanshi'))

    给视图加装饰器

    装饰器计算程序执行时间

    import time
    def Time(func):
        def inner(*args, **kwargs):
            cc = time.time()
            ret = func(*args,**kwargs)
            print(cc - time.time())
            return ret
        return inner

    装饰FBV

    FBV本身就是一个函数,所以和给普通的函数加装饰器无差

    @Time
    def Add(request):
        if request.method == 'POST':
            newname = request.POST.get('newname')
            models.tusu.objects.create(mane=newname)
            return redirect(reverse('app1:zhanshi'))
        return render(request,'add.html')
    
    

    装饰CBV

    类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,我们需要先将其转换为方法装饰器。

    Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器。

    第一种 low版直接在函数上加

    class AddC(View):
        @Time
        def get(self,request):
            return render(request, 'add.html')
        @Time
        def post(self,request):
            newname = request.POST.get('newname')
            models.tusu.objects.create(mane=newname)
            return redirect(reverse('app1:zhanshi'))

    第二种引用method_decorator

    from django.utils.decorators import method_decorator      #引用method_decorator方法, 
    
    class AddC(View): 
        @method_decorator(Time)             #在每个函数上加装饰器
        def get(self,request):
            return render(request, 'add.html')
        @method_decorator(Time)
        def post(self,request):
            newname = request.POST.get('newname')
            models.tusu.objects.create(mane=newname)
            return redirect(reverse('app1:zhanshi'))
     

    第三种 引用上级的dispatch

    from django.utils.decorators import method_decorator
    #不管走post还是gat都走dispatch函数,装饰dispatch函数就是装饰了他俩
    class AddC(View): 
        @method_decorator(Time)     #装饰当前的dispatch函数
        def dispatch(self, request, *args, **kwargs):     #定义函数dispatch
            ret = super().dispatch(request, *args, **kwargs)  引用上级的dispatch
            return ret            #把上级的调用结果返回给当前的dispatch函数
        def get(self,request):
            return render(request, 'add.html')
        def post(self,request):
            newname = request.POST.get('newname')
            models.tusu.objects.create(mane=newname)
            return redirect(reverse('app1:zhanshi'))

    第四种在类上加并指定使用装饰器的函数

    from django.utils.decorators import method_decorator
    @ method_decorator(Time,name='get')
    @ method_decorator(Time,name='post')
    class AddC(View):
        def get(self,request):
            return render(request, 'add.html')
        def post(self,request):
            newname = request.POST.get('newname')
            models.tusu.objects.create(mane=newname)
            return redirect(reverse('app1:zhanshi'))

    第五种 最终版直接装饰上级的dispatch 一句搞定

    from django.utils.decorators import method_decorator
    @ method_decorator(Time,name='dispatch')
    class AddC(View):
        def get(self,request):
            return render(request, 'add.html')
        def post(self,request):
            newname = request.POST.get('newname')
            models.tusu.objects.create(mane=newname)
            return redirect(reverse('app1:zhanshi'))

    拓展 直接在函数上加装饰器和引用method_decorator家装饰器的区别

    区别在于在装饰器里接受的args

    def Time(func):
        def inner(*args, **kwargs):
            cc = time.time()
            ret = func(*args,**kwargs)
            print(cc - time.time())
            return ret
        return inner

    如果直接加 args接受俩参数,第一个是func对象,第二个是request请求对象

    如果用method_decorator  args 只接受一个参数就是request对象

    from django.utils.decorators import method_decorator
    # @ method_decorator(Time,name='dispatch')
    class AddC(View):
        @Time                           #get方式直接装饰
        def get(self,request):
            return render(request, 'add.html')
        @method_decorator(Time)         #post方式method_decorator方式
        def post(self,request):       
            newname = request.POST.get('newname')
            models.tusu.objects.create(mane=newname)
            return redirect(reverse('app1:zhanshi'))

    结果

    (<app1.views.AddC object at 0x00000241089604A8>, <WSGIRequest: GET '/app1/add2/'>)      #get方式 args俩参数
    -0.0019369125366210938
    [22/Feb/2019 22:44:11] "GET /app1/add2/ HTTP/1.1" 200 2628
    
    
    (<WSGIRequest: POST '/app1/add2/'>,)                           #post方式 args一个参数
    -0.01776266098022461
    [22/Feb/2019 22:44:15] "POST /app1/add2/ HTTP/1.1" 302 0

     请求和响应request和response

    请求新手必备三件套

    HttpResponse('字符串')                  #给请求返回一个字符串   
    redirect(request,'html文件')           #给请求返回一个html文件               
    rende(重定向地址)                        #重定向

    requset对象

    request属性

        request.method        请求方法 GET POST PUT

        request.GET             URL上携带的参数

        request.POST           POST请求提交的数据

        request.path    返回用户访问url路径,不包括域名和参数信息   (和request.path_info一样)

        request.body              请求体,byte类型,即 POST请求传过来的参数

    class AddC(View):
        @Time
        def get(self,request):
            print(request.GET)
            return render(request, 'add.html')
        @method_decorator(Time)
        def post(self,request):
            print(request.method)
            print(request.path_info)
            print(request.body)
            print(request.POST)
            newname = request.POST.get('newname')
            models.tusu.objects.create(mane=newname)
            return redirect(reverse('app1:zhanshi'))
    # 打印出的参数
    (<WSGIRequest: POST '/app1/add2/'>,) #url上带的参数 request.GET 由于没有在get上传参 所以这个例子没有参数 POST    #请求方式 request.method /app1/add2/ #url路径 request.path_info b'newname=%E4%BA%BA%E6%B0%91%E5%87%BA%E7%89%88%E7%A4%BE' #请求主体 byte请求体 request.body <QueryDict: {'newname': ['人民出版社']}> #post请求出来的键值, request.POST

        request. scheme      表示请求方案的字符串 (通常为http或https)

    def Zhan_shi(request):
        all_tusu = models.tusu.objects.all()
        print(request.scheme)
        return render(request,'zhanshi.html',{'all': all_tusu})
    
    http

         request.FILES

    一个类似于字典的对象,包含所有的上传文件信息。 FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。   注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会 包含数据。否则,FILES 将为一个空的类似于字典的对象。

        request.META

    一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器

    def Zhan_shi(request):
        all_tusu = models.tusu.objects.all()
        print(request.scheme)
        print(request.META)
        return render(request,'zhanshi.html',{'all': all_tusu})
    
    {'ALLUSERSPROFILE': 'C:\ProgramData', 'APPDATA': 'C:\Users\22490\AppData\Roaming', 'COMMONPROGRAMFILES': 'C:\Program Files\Common Files', 'COMMONPROGRAMFILES(X86)': 'C:\Program Files (x86)\Common Files', 'COMMONPROGRAMW6432': 'C:\Program Files\Common Files', 'COMPUTERNAME': 'DESKTOP-G8I5SER', 'COMSPEC': 'C:\WINDOWS\system32\cmd.exe', 'CONFIGSETROOT': 'C:\WINDOWS\ConfigSetRoot', 'DJANGO_SETTINGS_MODULE': 'tushu.settings', 'DRIVERDATA': 'C:\Windows\System32\Drivers\DriverData', 'FPS_BROWSER_APP_PROFILE_STRING': 'Internet Explorer', 'FPS_BROWSER_USER_PROFILE_STRING': 'Default', 'HOMEDRIVE': 'C:', 'HOMEPATH': '\Users\22490', 'LOCALAPPDATA': 'C:\Users\22490\AppData\Local', 'LOGONSERVER': '\\DESKTOP-G8I5SER', 'MOZ_PLUGIN_PATH': 'D:\福喜\Foxit Reader\plugins\', 'NUMBER_OF_PROCESSORS': '4', 'ONEDRIVE': 'C:\Users\22490\OneDrive', 'OS': 'Windows_NT', 'PATH': 'C:\Python27\;C:\Python27\Scripts;C:\Python36\Scripts\;C:\Python36\;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;D:\shexiangt\3rdparty\lib\Win32\;D:\shexiangt\Redist\Win32\;C:\Users\22490\AppData\Local\Microsoft\WindowsApps;;D:\pycharm\PyCharm 2018.3.2\bin;;C:\Python36\lib\site-packages\numpy\.libs;C:\Python36\lib\site-packages\numpy\.libs', 'PATHEXT': '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY;.PYW', 'PROCESSOR_ARCHITECTURE': 'AMD64', 'PROCESSOR_IDENTIFIER': 'Intel64 Family 6 Model 142 Stepping 9, GenuineIntel', 'PROCESSOR_LEVEL': '6', 'PROCESSOR_REVISION': '8e09', 'PROGRAMDATA': 'C:\ProgramData', 'PROGRAMFILES': 'C:\Program Files', 'PROGRAMFILES(X86)': 'C:\Program Files (x86)', 'PROGRAMW6432': 'C:\Program Files', 'PSMODULEPATH': 'C:\Program Files\WindowsPowerShell\Modules;C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules', 'PT5HOME': 'D:\思科交换机模拟器\Cisco Packet Tracer 6.0', 'PT6HOME': 'D:\思科交换机模拟器\Cisco Packet Tracer 6.0', 'PUBLIC': 'C:\Users\Public', 'PYCHARM': 'D:\pycharm\PyCharm 2018.3.2\bin;', 'PYCHARM_HOSTED': '1', 'PYCHARM_MATPLOTLIB_PORT': '55621', 'PYTHON36': 'C:\Python36', 'PYTHONIOENCODING': 'UTF-8', 'PYTHONPATH': 'D:\django\tushu;D:\pycharm\PyCharm 2018.3.2\helpers\pycharm_matplotlib_backend', 'PYTHONUNBUFFERED': '1', 'SESSIONNAME': 'Console', 'SYSTEMDRIVE': 'C:', 'SYSTEMROOT': 'C:\WINDOWS', 'TEMP': 'C:\Users\22490\AppData\Local\Temp', 'TMP': 'C:\Users\22490\AppData\Local\Temp', 'USERDOMAIN': 'DESKTOP-G8I5SER', 'USERDOMAIN_ROAMINGPROFILE': 'DESKTOP-G8I5SER', 'USERNAME': '22490', 'USERPROFILE': 'C:\Users\22490', 'WINDIR': 'C:\WINDOWS', 'RUN_MAIN': 'true', 'SERVER_NAME': 'DESKTOP-G8I5SER', 'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_PORT': '8000', 'REMOTE_HOST': '', 'CONTENT_LENGTH': '', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'WSGIServer/0.2', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/app1/zhanshi/', 'QUERY_STRING': '', 'REMOTE_ADDR': '127.0.0.1', 'CONTENT_TYPE': 'text/plain', 'HTTP_HOST': '127.0.0.1:8000', 'HTTP_CONNECTION': 'keep-alive', 'HTTP_CACHE_CONTROL': 'max-age=0', 'HTTP_UPGRADE_INSECURE_REQUESTS': '1', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36', 'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9', 'wsgi.input': <_io.BufferedReader name=464>, 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>}

     简单的上传服务

    def upload(request):
        """
        保存上传文件前,数据需要存放在某个位置。默认当上传文件小于2.5M时,django会将上传文件的全部内容读进内存。从内存读取一次,写磁盘一次。
        但当上传文件很大时,django会把上传文件写到临时文件中,然后存放到系统临时文件夹中。
        :param request: 
        :return: 
        """
        if request.method == "POST":
            # 从请求的FILES中获取上传文件的文件名,file为页面上type=files类型input的name属性值
            filename = request.FILES["file"].name
            # 在项目目录下新建一个文件
            with open(filename, "wb") as f:
                # 从上传的文件对象中一点一点读
                for chunk in request.FILES["file"].chunks():
                    # 写入本地文件
                    f.write(chunk)
            return HttpResponse("上传OK")

    request方法

    request.get_full_path()         获取全路径 即路径和参数

    print(request.get_full_path())
    
    /app1/update/?zj=16    

    request.is_secure()                 如果请求时是https,则返回True;反之False

    response对象

    JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应。

    from django.http import JsonResponse     #引用JsonResponse
    def json_text(request):
        data = {'name':'wk','age':18}
        return JsonResponse(data)            #这样前端就能接收到json格式的数据 
    
    默认只能传递字典类型,如果要传递非字典类型需要设置一下safe关键字参数。
    JsonResponse([1, 2, 3], safe=False)

    Django模板系统

    Django模板中只需要记两种特殊符号:

    {{  }}和 {% %}

    {{ }}表示变量,在模板渲染的时候替换成值,{% %}表示逻辑相关的操作。

    变量

    {{ 变量名 }}

    变量名由字母数字和下划线组成。

    点(.)在模板语言中有特殊的含义,用来获取对象的相应属性值。

    def test(request):
        l = [1, 2, 3]
        d = {'name':'wk'}
    
        class dd_a():
            def __init__(self, name, age):
                self.name = name
                self.age = age
            def dream(self):
                return "%s 1111" %(self.name)
    
        Wk = dd_a('wk',15)
        wc = dd_a('wc',13)
        ww = dd_a('ww',18)
        pp = [Wk,wc,ww]
        return render(request, "test.html",{'l':l,'d':d, 'pp':pp} )

     在html 取变量

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {{ l.0 }}            #根据索引取列表的值
    <br> 
    {{ l.1 }}             #取列表的第一个值
    <br>
    {{ d.name }}         #根据key取字典的值
    <br> 
    {{ d.keys }}           #取字典的所有key   values 取字典所有的值     items取字典的键值
    <br>
    {{ pp.0.name }}        #取列表pp第一个对象的 name属性
    <br>
    {{ pp.0.age }}           
    <br>
    {{ pp.0.dream }}        #使用pp列表第一个对象的dream方法
    </body>
    </html>

    注:当模板系统遇到一个   .(点)时,会按照如下的顺序去查询:

    1. 在字典中查询
    2. 属性或者方法
    3. 数字索引

    Filters   过滤器

    翻译为过滤器,用来修改变量的显示结果。

    语法: {{ value|filter_name:参数 }}

    '|'左右没有空格没有空格没有空格

    default  

    {{ value|default:"nothing"}}

    如果value值没传的话就显示nothing

    注:TEMPLATES的OPTIONS可以增加一个选项:string_if_invalid:'找不到',可以替代default的的作用。

    filesizeformat

    将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:

    {{ value|filesizeformat }}

    如果 value 是 123456789,输出将会是 117.7 MB。

    add

    给变量加参数

    {{ value|add:"2" }}

    value是数字4,则输出结果为6。

    {{ first|add:second }}

    如果first是 [1,.2,3] ,second是 [4,5,6] ,那输出结果是 [1,2,3,4,5,6] 。

    lower

    小写

    {{ value|lower }}

    upper

    大写

    {{ value|upper}}

    title

    标题

    {{ value|title }}

    ljust

    左对齐

    "{{ value|ljust:"10" }}"

    rjust

    右对齐

    "{{ value|rjust:"10" }}"

    center

    居中

    "{{ value|center:"15" }}"

    length

    {{ value|length }}

    返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.

    slice  

    切片

    {{value|slice:"2:-1"}}

    first

    取第一个元素

    {{ value|first }}

    last

    取最后一个元素

    {{ value|last }}

    join

    使用字符串拼接列表。同python的str.join(list)。

    {{ value|join:" // " }}

    truncatechars

    如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。

    参数:截断的字符数

    {{ value|truncatechars:9}}

    date

    views视图添加时间

    import datetime
    
    def test(request):
        Date = datetime.datetime.now()
        return render(request, "test.html",{'date':Date})

    日期格式化

    {{ value|date:"Y-m-d H:i:s"}}

    可格式化输出的字符:点击查看

    日期也可以改配置文件显示

    修改settings.py文件

    USE_L10N = False 
    DATETIME_FORMAT = 'Y-m-d H:i:s'

     此时html只需要写   {{ date }}

    就显示格式化的日期

    safe (转译,把传进来的字符串转译为html可识别的语言)

    Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。

    比如:

    value = "<a href='#'>点我</a>"

    {{ value|safe}}

    Tags

    for循环

    <ul>
    {% for user in user_list %}
        <li>{{ user.name }}</li>
    {% endfor %}
    </ul>

    for循环可用的一些参数:

    VariableDescription
    forloop.counter 当前循环的索引值(从1开始)
    forloop.counter0 当前循环的索引值(从0开始)
    forloop.revcounter 当前循环的倒序索引值(从1开始)
    forloop.revcounter0 当前循环的倒序索引值(从0开始)
    forloop.first 当前循环是不是第一次循环(布尔值)如果是第一次显示True  后边的每次循环显示Flase
    forloop.last 当前循环是不是最后一次循环(布尔值)
    forloop.parentloop 本层循环的外层循环
    def test(request):
        class dd_a():
            def __init__(self, name, age):
                self.name = name
                self.age = age
            def dream(self):
                return "%s 1111" %(self.name)
        Wk = dd_a('wk',15)
        wc = dd_a('wc',13)
        ww = dd_a('ww',18)
        pp = [Wk,wc,ww]
        return render(request, "test.html",{'pp':pp} )
    
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <ul>
            {% for ps in pp %}
                <li>{{ forloop.counter }} = {{ ps.name }}</li>
            {% endfor %} 
        </ul>
    </body>
    </html>

    for ... empty   当循环为空时走empty

      {% for foo in all %}
                            <tr>
                                <td>{{ forloop.counter }}</td>
                                <td>{{ foo.pk }}</td>
                                <td>{{ foo.mane }}</td>
                                <td>
                                    <a href="{% url 'app1:del' %}?sh={{ foo.pk }}" class="btn btn-danger btn-sm">删除</a>
                                    <a href="{% url 'app1:update' %}?zj={{ foo.pk }}" class="btn btn-primary btn-sm">编辑</a>
                                </td>
                                <td>
                                    {% empty %}             {# 当for循环为空时,显示empty的内容 #}
                                    <td>空的</td>
                                </td>
                            </tr>
                        {% endfor %}

    if,elif和else

      {% for foo in all %}
                            <tr {% if forloop.first %} style="color: red" {% endif %}>       #如果是第一次循环得出的结果则显示红色
                                <td>{{ forloop.counter }}</td>
                                <td>{{ foo.pk }}</td>
                                <td>{{ foo.mane }}</td>
                                <td>
                                    <a href="{% url 'app1:del' %}?sh={{ foo.pk }}" class="btn btn-danger btn-sm">删除</a> 
                                    <a href="{% url 'app1:update' %}?zj={{ foo.pk }}" class="btn btn-primary btn-sm">编辑</a>
                                </td>
                                <td>
                                    {% empty %}
                                    <td>空的</td>
                                </td>
                            </tr>
                        {% endfor %}
    复制代码
    {% if user_list %}
      用户人数:{{ user_list|length }}
    {% elif black_list %}
      黑名单数:{{ black_list|length }}
    {% else %}
      没有用户
    {% endif %}
    复制代码

    当然也可以只有if和else

    {% if user_list|length > 5 %}
      七座豪华SUV
    {% else %}
        黄包车
    {% endif %}

    if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。

     with 给变量起别名

    {% with oldname as newname %}
        {{ newname }}
    {% endwith %}

    csrf_token

    这个标签用于跨站请求伪造保护。

    在页面的form表单里面写上{% csrf_token %} ,这样不用注释中间件 也可以提交post请求

       <form class="form-horizontal" action="" method="post">  
                        {% csrf_token %}           {# 加在form表单下 #}

    母板

     母版就是一个普通的页面,存放所有页面公共的代码,定义好block块,让子页面进行重写

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/css/bootstrap.min.css">
        <link rel="stylesheet" href="/static/css/das.css">
    </head>
    <body>
    
    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container-fluid">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
                        aria-expanded="false" aria-controls="navbar">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#">出版社管理</a>
            </div>
            <div id="navbar" class="navbar-collapse collapse">
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="#">Dashboard</a></li>
                    <li><a href="#">Settings</a></li>
                    <li><a href="#">Profile</a></li>
                    <li><a href="#">Help</a></li>
                </ul>
                <form class="navbar-form navbar-right">
                    <input type="text" class="form-control" placeholder="Search...">
                </form>
            </div>
        </div>
    </nav>
    
    <div class="container-fluid">
        <div class="row">
            <div class="col-sm-3 col-md-2 sidebar">
                <ul class="nav nav-sidebar">
                    <li class="active"><a href="{% url 'app1:zhanshi' %}">出版社列表 <span class="sr-only">(current)</span></a></li>
                </ul>
            </div>
            <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
                {% block main %}
                {% endblock %}                 {# 母版只保留公共部分,并且定义block来定位不同的部分#}
            </div>
        </div>
    </div>

    继承{% extends 'layouts.html' %}    子页面继承母版,并且在block块里加上不同的东西

    {% extends 'muban.html' %}              {# 继承母版 #}
    
    {% block main %}           {# 在blick 定位的地方加上不通的部分#}
                <h2 class="sub-header">出版社信息</h2>
                <div class="table-responsive">
                <a href="{% url 'app1:add2' %}" class="btn btn-primary">添加</a>
                    <table class="table table-striped table-hover">
                        <thead>
                        <tr>
                            <th>序号<th>
                            <th>ID</th>
                            <th>出版社名称</th>
                            <th>操作</th>
                        </tr>
                        </thead>
                        <tbody>
                        {% for foo in all %}
                            <tr {% if forloop.first %} style="color: red" {% endif %}>
                                <td>{{ forloop.counter }}</td>
                                <td>{{ foo.pk }}</td>
                                <td>{{ foo.mane }}</td>
                                <td>
                                    <a href="{% url 'app1:del' %}?sh={{ foo.pk }}" class="btn btn-danger btn-sm">删除</a>
                                    <a href="{% url 'app1:update' %}?zj={{ foo.pk }}" class="btn btn-primary btn-sm">编辑</a>
                                </td>
                                <td>
                                    {% empty %}
                                    <td>空的</td>
                                </td>
                            </tr>
                        {% endfor %}
                        </tbody>
                    </table>
                </div>
    {% endblock %}

    注意点:

      1.  {% extends 'muban.html' %} 写在第一行

      2.   不同的内容写在这中间{% block main %}

       3.子页面和主页面不同的静态css js也可以通过block 添加

    组件

    一小段公用的html代码 很多页面要用的  把这段代码保存到html文件里

    可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方按如下语法导入即可。

    {% include 'toubuxinxi.html' %}

     公共头部文件代码 toubuxinxi.html

    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container-fluid">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
                        aria-expanded="false" aria-controls="navbar">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#">出版社管理</a>
            </div>
            <div id="navbar" class="navbar-collapse collapse">
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="#">Dashboard</a></li>
                    <li><a href="#">Settings</a></li>
                    <li><a href="#">Profile</a></li>
                    <li><a href="#">Help</a></li>
                </ul>
                <form class="navbar-form navbar-right">
                    <input type="text" class="form-control" placeholder="Search...">
                </form>
            </div>
        </div>
    </nav>

    在修改页面添加头部

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/css/bootstrap.min.css">
        <link rel="stylesheet" href="/static/css/das.css">
    </head>
    <body>
        {% include 'toubuxinxi.html' %}
        <br>
    <form class="form-horizontal" action="" method="post">
        {% csrf_token %}
        <div class="form-group">
            <label for="inputEmail3" class="col-sm-2 control-label">出版社名称</label>
            <div class="col-sm-10">
                <input type="text" class="form-control" id="inputEmail3" placeholder="出版社名称" name="newname"
                       value="{{ obj.mane }}">
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <button type="submit" class="btn btn-default">修改</button>
            </div>
    
    </body>
    </html>

    静态文件相关

    {% load static %}

    head里得引用静态文件的static是写死了

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/css/bootstrap.min.css">
        <link rel="stylesheet" href="/static/css/das.css">
    </head>

    如果settings.py文件里的static修改了则每个引用都要改

    STATIC_URL = '/static/'
    STATICFILES_DIRS = [
        os.path.join(BASE_DIR,'static')

    因此使用{% load static %}来解决

    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        {% load static %}             
    {#    <link rel="stylesheet" href="/static/css/bootstrap.min.css">#}
          <link rel="stylesheet" href={% static "css/bootstrap.min.css"%}>   {#变量名拼接相对路径#}
    {#    <link rel="stylesheet" href="/static/css/das.css">#}
         <link rel="stylesheet" href={% static "css/das.css"%}>
    </head>

    此时改变STATIC_URL = 的值页面也照常访问

    STATIC_URL = '/11111/'
    STATICFILES_DIRS = [
        os.path.join(BASE_DIR,'static')

    {% load static %}的使用

    {% load static %}
    <img src="{% static "images/hi.jpg" %}" alt="Hi!" />

    引用JS文件时使用:

    {% load static %}
    <script src="{% static "mytest.js" %}"></script>

    某个文件多处被用到可以存为一个变量

    {% load static %}
    {% static "images/hi.jpg" as myphoto %}
    <img src="{{ myphoto }}"></img>

    使用get_static_prefix   取的是settings.py里STATIC_URL 的值

    这种用法相当于使用绝对路径

    {% load static %}
    <img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />

    或者

    {% load static %}
    {% get_static_prefix as STATIC_PREFIX %}
    
    <img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" />
    <img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />

     外键的操作

     在数据库增加关联表

    from django.db import models
    
    # Create your models here.
    class tusu(models.Model):
        pid = models.AutoField(primary_key=True)
        mane = models.CharField(max_length=32)
    class Book(models.Model):                 #新增表Book title = models.CharField(max_length=32) #定义书名 tusu = models.ForeignKey('tusu',on_delete=models.CASCADE) #定义外键连接 连接的的表是tusu, on_delete=models.CASCADE 即如果出版社删除了对应的书也删除

    变更数据库

     python3 manage.py makemigrations
     python3 manage.py migrate

    新建的book表

    加入数据后

      

    做展示页

    url略

    views.py

    def newzs(request):
        books = models.Book.objects.all()       #查出book表的信息
        return render(request,'newzs.html',{'books':books})  #传到前端

    前端 用母版  拿外键的值直接点外键名(不要加_id)得到外键表的对象再点对应的key拿值

    {% extends 'muban.html' %}
    {% block main %}
                <h2 class="sub-header">书籍信息</h2>
                <div class="table-responsive">
    {#            <a href="{% url 'app1:add2' %}" class="btn btn-primary">添加</a>#}
                    <table class="table table-striped table-hover">
                        <thead>
                        <tr>
                            <th>序号<th>
                            <th>ID</th>
                            <th>出版社名称</th>
                            <th>书名 </th>
                            <th>操作</th>
                        </tr>
                        </thead>
                        <tbody>
                        {% for book in books %}
                            <tr {% if forloop.first %} style="color: red" {% endif %}>
                                <td>{{ forloop.counter }}</td>
                                <td>{{ book.pk }}</td>
                                <td>{{ book.tusu.mane }}</td> {# book.tusu点出来的不是外键的值而是对应的tusu表的对象,通过对象.key拿对应的值 #}
                                <td>{{ book.title }}</td>
                                <td>
                                    <a href="{% url 'app1:del' %}?sh={{ foo.pk }}" class="btn btn-danger btn-sm">删除</a>
                                    <a href="{% url 'app1:update' %}?zj={{ foo.pk }}" class="btn btn-primary btn-sm">编辑</a>
                                </td>
                                <td>
                                    {% empty %}
                                    <td>空的</td>
                                </td>
                            </tr>
                        {% endfor %}
                        </tbody>
                    </table>
                </div>
    {% endblock %}

    删除出版社 ,对应的书也没了

     添加功能

    url略

    views.py

    class newadd(View):
        def get(self,request): 
            tusu = models.tusu.objects.all()  #获取所有出版社的信息返回给前端
            return render(request,'newadd.html',{'tusu':tusu})
        def post(self,request):                #post请求添加出版舍
            newname = request.POST.get('newname')      #获取要添加的书的名字
            put = request.POST.get('put')              #获取要添加的书名对应的外键的值
            models.Book.objects.create(title=newname,tusu_id=put)     #创建新数据
            return redirect(reverse('app1:newzs'))

    前端展示页功能 直接跳转

       <a href="{% url 'app1:newadd' %}" class="btn btn-primary">添加</a>

    添加页功能

     <div class="table-responsive">
                    <form class="form-horizontal" action="" method="post">
                        <div class="form-group">
                            <label for="inputEmail3" class="col-sm-2 control-label">书名</label>
                            <div class="col-sm-10">
                                <input type="text" class="form-control" id="inputEmail3" placeholder="书名" name="newname">
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="inputEmail3" class="col-sm-2 control-label">出版社</label>
                            <div class="col-sm-10">
                                <select name="put" id="inputEmail3" class="form-control">
                                    {% for i in tusu %}
                                        <option value="{{ i.pk }}">{{ i.mane }}</option>
                                    {% endfor %}
                                </select>
                            </div>
                        </div>
                        <div class="form-group">
                            <div class="col-sm-offset-2 col-sm-10">
                                <button type="submit" class="btn btn-default">添加</button>
                            </div>
                        </div>
                    </form>
                </div>

     修改功能

    url

        url(r'upda/(d+)$', aap1vw.upda.as_view(),name='upda'),   #使用分组的方法

    views.py

    class upda(View):
        def get(self,request,zh):           #分组要在这里接收前端传来的分组的位置参数 Book表的主键
             # zh = request.GET.get('zh')        #这是之前的接受前端传来的?号的方法 现在用分组的方法
            book_obg = models.Book.objects.get(pk=zh)
            tusu = models.tusu.objects.all()
            return render(request,'upda.html',{'book_obg':book_obg,'tusu':tusu})
        def post(self,request,zh):
            book_obg = models.Book.objects.get(pk=zh)  #拿到原有的书的对象
            upname = request.POST.get('upname')   #拿到修改后的书名
            put = request.POST.get('put')         #拿到修改后的书的对应的外键的值
            book_obg.title = upname
            book_obg.tusu_id = put
            book_obg.save()
            return redirect(reverse('app1:newzs'))

    展示页提交信息          #分组url得到的参数是Book表的主键

    <a href="{% url 'app1:upda' book.pk %}" class="btn btn-primary btn-sm">编辑</a>  

    修改页功能

    <div class="col-sm-10">
    <input type="text" class="form-control" id="inputEmail3" placeholder="书名" name="upname" value="{{ book_obg.title }}"> 
    </div>
    <div class="form-group">
    <label for="inputEmail3" class="col-sm-2 control-label">出版社</label>
    <div class="col-sm-10">
    <select name="put" id="inputEmail3" class="form-control">
         {% for i in tusu %}
         {% if book_obg.tusu == i %}   {# book_obg是前端提交的对象,加点外键对应的键即得到对应链接的对象 然后对比前端发来的对象是不是当次循环的对象 #}
          <option selected value="{{ i.pk }}">{{ i.mane }}</option>   {# 如果循环列表该次循环的对象是前端get提交来的对象 是就 selected 选中 #}
          {% else %}
          <option value="{{ i.pk }}">{{ i.mane }}</option>   {# 如果不是就不选中 #}
          {% endif %}
          {% endfor %}
     </select>
    </div>
    </div>

    删除功能将出版社和图书的删除合并

    url    定义两个分组分别传数据库对面的名字和对应的主键

    url(r'del_(tusu|book)/(d+)/$', aap1vw.Del,name='Del'),

    前端传出的值

        1.出版社传出的值为 对应的数据库名 和对应 的主键值 

    <a href="{% url 'app1:Del' 'tusu' foo.pk %}" class="btn btn-danger btn-sm">删除</a>

        2. 图书传出的值为 对应的数据库名 和对应的 主键值

    <a href="{% url 'app1:Del' 'book' book.pk %}" class="btn btn-danger btn-sm">删除</a>

    views.py 文件逻辑

    def Del(request,zz,hh):       #分别接收前端传来的两个参数
        if zz == 'tusu':          #图书的返回图书的展示页,出版社的返回出版社的  
            dd = 'app1:zhanshi' 
        elif zz == 'Book':        #此处可以优化 把展示页的别名改为对应数据库对象的名字
            dd = 'app1:newzs'     #可以省略以上4行代码
        Obj = getattr(models,zz)    #反射得到models 里的对应的图书的或出版社的数据库对象
        Obj.objects.get(pk=hh).delete()    #删除对应的数据库对象的选中的主键
        return redirect(reverse(dd))  #返回对应的展示页



    
    
    
  • 相关阅读:
    Corn Fields
    状压DP
    全排列函数
    搜索
    前缀和与差分
    最小花费
    【Lintcode】062.Search in Rotated Sorted Array
    【LeetCode】039. Combination Sum
    【LeetCode】040. Combination Sum II
    【LeetCode】047. Permutations II
  • 原文地址:https://www.cnblogs.com/ywrj/p/10412993.html
Copyright © 2020-2023  润新知