zoukankan      html  css  js  c++  java
  • Django进阶篇

    Django路由映射FBV 和 CBV

    django中请求处理方式有2种:FBV(function base views) 和 CBV(class base views),换言之就是一种用函数处理请求,一种用类处理请求。

    FBV

    # url.py
    from django.conf.urls import url, include
    from mytest import views
     
    urlpatterns = [
        url(r‘^index/‘, views.index),
    ]
    
    # views.py
    from django.shortcuts import render
     
     
    def index(req):
        if req.method == ‘POST‘:
            print(‘method is :‘ + req.method)
        elif req.method == ‘GET‘:
            print(‘method is :‘ + req.method)
        return render(req, ‘index.html‘)
    View Code

    CBV

    # urls.py
    from mytest import views
     
    urlpatterns = [
        # url(r‘^index/‘, views.index),
        url(r‘^index/‘, views.Index.as_view()),
    ]
    
    # views.py
    from django.views import View
    
     
    class Index(View):
        def get(self, req):
            print(‘method is :‘ + req.method)
            return render(req, ‘index.html‘)
     
        def post(self, req):
            print(‘method is :‘ + req.method)
            return render(req, ‘index.html‘)
    
    # 注:类要继承 View ,类中函数名必须小写。
    View Code

    关于CBV模式下的一个拓展

    # cbv 模式下继承了django的view类
    # 在请求来临的时候,会调用继承类的 dispatch 方法
    # 通过反射的方法它会去调用自己写的视图函数, 那么这便是一个切入点,可以在自己的 cbv 视图中,重写这个方法。 
    class View(object):
    
        def dispatch(self, request, *args, **kwargs):
            # Try to dispatch to the right method; if a method doesn't exist,
            # defer to the error handler. Also defer to the error handler if the
            # request method isn't on the approved list.
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            return handler(request, *args, **kwargs)
    View Code

    分页

    一、Django内置分页

    from django.shortcuts import render
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    
    L = []
    for i in range(999):
        L.append(i)       # 模拟数据库 生成数据
    
    def index(request):
        current_page = request.GET.get('page')  # 通过get请求得到当前请求的页数
    
        paginator = Paginator(L, 10)            # 实例化传入俩个参数(所有数据,当页显示条数)
        # per_page: 每页显示条目数量
        # count:    数据总个数
        # num_pages:总页数
        # page_range:总页数的索引范围,如: (1,10),(1,200)
        # page:     page对象
        try:
            posts = paginator.page(current_page)# 传入当前页码,观源码可得实例化了一个Page对象
            # has_next              是否有下一页
            # next_page_number      下一页页码
            # has_previous          是否有上一页
            # previous_page_number  上一页页码
            # object_list           分页之后的数据列表
            # number                当前页
            # paginator             paginator对象
        except PageNotAnInteger:    # 不是数字
            posts = paginator.page(1)
        except EmptyPage:           # 超出页码范围
            posts = paginator.page(paginator.num_pages)
        return render(request, 'index.html', {'posts': posts})  # posts封装了一些方法
    Views.py
    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <ul>
        {% for item in posts %}
            <li>{{ item }}</li>
        {% endfor %}
    </ul>
    
    <div class="pagination">
          <span class="step-links">
            {% if posts.has_previous %}
                <a href="?p={{ posts.previous_page_number }}">上一页</a>
            {% endif %}
              <span class="current">
                Page {{ posts.number }} of {{ posts.paginator.num_pages }}.  
              </span>
              {% if posts.has_next %}
                  <a href="?p={{ posts.next_page_number }}">下一页</a>
              {% endif %}
          </span>
    
    </div>
    </body>
    </html>
    HTML

    那么、Django的内置分页基本俩个类实现、并封装了一些方法来使用、此时并不能满足有一些的需求

    二、Django内置分页的拓展

    from django.shortcuts import render
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    
    user = []
    for i in range(1, 1001):
        dic = {'name': 'root' + str(i), 'pwd': i}
        user.append(dic)
    
    
    class DiyPaginator(Paginator):
        def __init__(self, current_page,max_pager_num, *args, **kwargs):
            """
            :param current_page:  当前页码
            :param max_pager_num: 显示页码个数的最大值
            :param args:
            :param kwargs:
            """
            self.current_page = int(current_page)
            self.max_pager_num = int(max_pager_num)
            super(DiyPaginator,self).__init__(*args,**kwargs)
    
        def pager_num_range(self):
            # 需要的参数
            # 当前页码    self.current_page
            # 页码数量    self.max_pager_num
            # 总页数      self.num_pages
    
            # 如果总页数小于页码个数最大值的情况
            if self.num_pages < self.max_pager_num:
                return range(1,self.num_pages+1)     # 返回 从 1 到 总页数
    
            # 如果总页数大于页码数量且当前所选页码小于页码数量的一半    
            part = self.max_pager_num//2
            if self.current_page <= part:
                return range(1,self.max_pager_num+1) # 返回 从 1 到 页码个数最大值
    
            # 如果当前页码加一半的页码 大于 总页数
            if (self.current_page+part) > self.num_pages:
                # 返回 从总页数-最大页码数 到 总页数      range的用法在此不作解释
                # 例如 96页+5页 超出总页数 则返回的范围是 从 总页数-最大页码数量+1 到 总页数+1    
                return range(self.num_pages-self.max_pager_num+1,self.num_pages+1)
    
            # 其余情况从 当前页码减去显示页码的平均值开始  到 当前页码加显示页码的平均值(并加一)结束
            return range(self.current_page-part,self.current_page+part+1)
    
    
    def index(request):
        p = request.GET.get('page')
        start = (int(p)-1)*10
        end = int(p)*10
        data = user[start:end]
        return render(request,'index.html',{'data':data,'user':user})
    
    
    def index1(request):
        current_page = request.GET.get('page')
        paginator = DiyPaginator(current_page, 9, user, 10)
        # Paginator所封装的方法
        # per_page: 每页显示条目数量
        # count:    数据总个数
        # num_pages:总页数
        # page_range:总页数的索引范围,如: (1,10),(1,200)
        # page:     page对象
        try:
            posts = paginator.page(current_page)
            # has_next              是否有下一页
            # next_page_number      下一页页码
            # has_previous          是否有上一页
            # previous_page_number  上一页页码
            # object_list           分页之后的数据列表
            # number                当前页
            # paginator             paginator对象
        except PageNotAnInteger:      # 不是整形数字
            posts = paginator.page(1)
        except EmptyPage:             # 如果是空值
            posts = paginator.page(paginator.num_pages)
    
        return render(request,'index1.html',{'posts':posts})
    扩展内置分页:views.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <ul>
            {% for row in posts.object_list %}
                <li>{{ row.name }}-{{ row.pwd }}</li>
            {% endfor %}
        </ul>
        {% include 'include/pager.html' %}
    </body>
    </html>
    
    ##################################
    include 组件代码
    
    {% if posts.has_previous %}
        <a href="/index1?page={{ posts.previous_page_number }}">上一页</a>
    {% endif %}
    
    {% for num in posts.paginator.pager_num_range %}
        {% if num == posts.number %}
            <a style="color: red;font-size: 20px" href="/index1?page={{ num }}">{{ num }}</a>
        {% else %}
            <a href="/index1?page={{ num }}">{{ num }}</a>
        {% endif %}
    {% endfor %}
    
    {% if posts.has_next %}
        <a href="/index1?page={{ posts.next_page_number }}">下一页</a>
    {% endif %}
    <span>
        当前页:{{ posts.number }}&nbsp;&nbsp;总页数:{{ posts.paginator.num_pages }}
    </span>
    扩展内置分页:HTML

    三、自定义分页(适用于任何地方)

    • 创建处理分页数据的类
    • 根据分页数据获取数据
    • 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]或者额外的作出一些拓展也可以

    创建处理分页数据的类时,大致也需要四个参数(详情观看类构造方法)

      1、为了减少服务器内存的负载,不再获取所有数据的,而是获得所有数据的总个数,然后再根据索引查数据库的内容

      2、当前页码

      3、每页显示的行数

      4、页码显示的数量

    对于页数的显示大致也可以归类为三种情况(详情观看类中page_num_range函数)

      1、计算的总页数小于页码显示的数量

      2、计算的总页数大于页码显示的数量

        A、当前页数小于页码数量的一半

        B、当前页数加页码数量的一半超出总页数的范围

      3、正常情况

        从 当前页数 减 一半页码数量 到 当前页数 加 一半页码数量

    class Pagination(object):
        def __init__(self,totalCount,currentPage,perPageItemNum=10,maxPageNum=9):
            """
            :param totalCount:     所有数据总个数
            :param currentPage:    当前页数
            :param perPageItemNum: 每页显示行数
            :param maxPageNum:     最多显示页码个数
            """
            self.total_count = totalCount
            # 对当前的页码进行一次异常捕获
            try:
                currentPage = int(currentPage)
                if currentPage <= 0:
                    currentPage = 1
                self.current_page = currentPage
            except Exception:
                self.current_page = 1
            self.per_page_item_num = perPageItemNum
            self.max_page_num = maxPageNum
    
        @property
        def start(self):
            # 数据索引开始的值
            return (self.current_page-1) * self.per_page_item_num
    
        @property
        def end(self):
            # 数据索引结束的值
            return self.current_page * self.per_page_item_num
    
        @property
        def num_pages(self):
            """
            总页数
            :return:
            """
            # 得商取余得内置函数
            x, o = divmod(self.total_count,self.per_page_item_num)
            if o == 0:
                return x
            return x + 1
    
        @property
        def page_num_range(self):
            if self.num_pages < self.max_page_num:
                return range(1, self.num_pages+1)
    
            part = self.max_page_num//2
            if self.current_page <= part:
                return range(1,self.max_page_num+1)
    
            if (self.current_page+part) > self.num_pages:
                return range(self.num_pages-self.max_page_num+1, self.num_pages+1)
            return range(self.current_page-part, self.current_page+part+1)
    
        def page_str(self):
            page_list = []
    
            first = "<li><a href='/index2/?page=1'>首页</a></li>"
            page_list.append(first)
    
            if self.current_page == 1:
                prev_page = "<li><a href='#'>上一页</a></li>"
            else:
                prev_page = "<li><a href='/index2/?page=%s'>上一页</a></li>" %(self.current_page-1)
            page_list.append(prev_page)
    
            for i in self.page_num_range:
                if i == self.current_page:
                    temp = "<li class='active'><a href='/index2/?page=%s'>%s</a></li>" %(i,i)
                else:
                    temp = "<li><a href='/index2/?page=%s'>%s</a></li>" % (i, i)
                page_list.append(temp)
    
            if self.current_page == self.num_pages:
                next_page = "<li><a href='#'>下一页</a></li>"
            else:
                next_page = "<li><a href='/index2/?page=%s'>下一页</a></li>" %(self.current_page+1)
            page_list.append(next_page)
    
            last = "<li><a href='/index2/?page=%s'>尾页</a></li>" %self.num_pages
            page_list.append(last)
    
            return ''.join(page_list)
    自定义分页
    def index2(request):
        from page.diypage import Pagination
        current_page = request.GET.get('page')
        page_obj = Pagination(1000,current_page)
    
        data_list = user[page_obj.start:page_obj.end]
        return render(request,'index2.html',{
            'data' : data_list,
            'page_obj' : page_obj
        })
    自定义分页:views.py
    # 本页面引用了bootstrap样式
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css" />
    </head>
    <body>
        <ul>
            {% for row in data %}
                <li>{{ row.name }}-{{ row.pwd }}</li>
            {% endfor %}
        </ul>
        {% for i in page_obj.pager_num_range %}
            <a href="/index2/?page={{ i }}">{{ i }}</a>
        {% endfor %}
        <hr/>
    
        <ul class="pagination pagination-sm">
            {{ page_obj.page_str|safe }}
          </ul>
        <div style="height: 300px;"></div>
    </body>
    </html>
    自定义分页:HTML

    序列化

      序列化是将对象状态转换为可保持或传输的格式的过程

      反序列化是指将存储在存储媒体中的对象状态装换成对象的过程 

      例如游戏都有存档的功能、再次开始的时候只需读档即可(这即是一个序列化与反序列的过程)

      序列化也可以将一个对象传递到另一个地方的

      关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式。

    1、serializers

    from django.core import serializers
     
    ret = models.BookType.objects.all()
     
    data = serializers.serialize("json", ret)

    2、json.dumps

    import json
     
    #ret = models.BookType.objects.all().values('caption')
    ret = models.BookType.objects.all().values_list('caption')
     
    ret=list(ret)
     
    result = json.dumps(ret)

    3、from django.http import JsonResponse

    django JsonResponse不支持返回列表形式的序列化。例如看看这个类的构造方法是怎么样执行的...

    class JsonResponse(HttpResponse):
        """
        将数据序列化成为JSON的Http响应类
    
        :param data: Data to be dumped into json. By default only ``dict`` objects
          are allowed to be passed due to a security flaw before EcmaScript 5. See
          the ``safe`` parameter for more information.
        :param encoder: Should be an json encoder class. Defaults to
          ``django.core.serializers.json.DjangoJSONEncoder``.
        :param safe: Controls if only ``dict`` objects may be serialized. Defaults
          to ``True``.
        :param json_dumps_params: A dictionary of kwargs passed to json.dumps().
        """
    
        def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
                     json_dumps_params=None, **kwargs):
            # 如果safe为True 和 data 不是 dict的实例对象 则抛出异常
            if safe and not isinstance(data, dict):
                raise TypeError(
                    'In order to allow non-dict objects to be serialized set the '
                    'safe parameter to False.'
                )
            if json_dumps_params is None:
                json_dumps_params = {}
            kwargs.setdefault('content_type', 'application/json')
            data = json.dumps(data, cls=encoder, **json_dumps_params)
            super(JsonResponse, self).__init__(content=data, **kwargs)
    View Code

    Cookices

    Cookie是存储在用户浏览器上的一个键值对

    A、获取Cookies

    request.COOKIES['key']
    request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
        参数:
            default: 默认值
               salt: 加密盐
            max_age: 后台控制过期时间

    B、设置Cookies

    rep = HttpResponse(...) 或 rep = render(request, ...)
     
    rep.set_cookie(key,value,...)
    rep.set_signed_cookie(key,value,salt='加密盐',...)
        参数:
            key,              键
            value='',         值
            max_age=None,     超时时间
            expires=None,     超时时间(IE requires expires, so set it if hasn't been already.)
            path='/',         Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
            domain=None,      Cookie生效的域名
            secure=False,     https传输
            httponly=False    只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

    C、由于Cookies保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie.

         更多详情更新中...

    Session

    Session是存储在服务器的一组键值对,且它依赖于Cookie,且安全系数比Cookie高

    Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:

    • 数据库(默认)
    • 缓存
    • 文件
    • 缓存+数据库
    • 加密cookie

    A、数据库Session

    Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
     
    a. 配置 settings.py
     
        SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)
         
        SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
        SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
        SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
        SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
        SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
        SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
        SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
        SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)
     
     
     
    b. 使用
     
        def index(request):
            # 获取、设置、删除Session中数据
            request.session['k1']
            request.session.get('k1',None)
            request.session['k1'] = 123
            request.session.setdefault('k1',123) # 存在则不设置
            del request.session['k1']
     
            # 所有 键、值、键值对
            request.session.keys()
            request.session.values()
            request.session.items()
            request.session.iterkeys()
            request.session.itervalues()
            request.session.iteritems()
     
     
            # 用户session的随机字符串
            request.session.session_key
     
            # 将所有Session失效日期小于当前日期的数据删除
            request.session.clear_expired()
     
            # 检查 用户session的随机字符串 在数据库中是否
            request.session.exists("session_key")
     
            # 删除当前用户的所有Session数据
            request.session.delete("session_key")
     
            request.session.set_expiry(value)
                * 如果value是个整数,session会在些秒数后失效。
                * 如果value是个datatime或timedelta,session就会在这个时间后失效。
                * 如果value是0,用户关闭浏览器session就会失效。
                * 如果value是None,session会依赖全局session失效策略。
    数据库Session

    跨站请求伪造

    Django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

    全局:

      中间件 django.middleware.csrf.CsrfViewMiddleware

    局部:

    • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
    • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

    注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

     

    Django中间件 

    django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。 

    在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下图。

     例如,可以在项目中的任何地方创建一个middleware.py的文件(可随意创建, 注册中间件的时候配置好路径即可)

    中间件中可以定义四个方法,分别是:

    • process_request(self,request)
    • process_view(self, request, callback, callback_args, callback_kwargs)
    • process_template_response(self,request,response)
    • process_exception(self, request, exception)
    • process_response(self, request, response)

    以上方法的返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,如果是HttpResonse对象,则直接将该对象返回给用户。

    自定义中间件

    1、创建中间件 

    class CustomMiddleware(object):
          
        def process_request(self,request):
            pass
    
        def process_view(self, request, callback, callback_args, callback_kwargs):
            i =1
    
        def process_exception(self, request, exception):
            pass
          
        def process_response(self, request, response):
            return response

    2、注册中间件

    如第一图所示最后一条,可根据自身业务去自定义一些中间件操作。  

    Django信号

    1,django内置信号

    Model signals
        pre_init                    # django的modal执行其构造方法前,自动触发
        post_init                   # django的modal执行其构造方法后,自动触发
        pre_save                    # django的modal对象保存前,自动触发
        post_save                   # django的modal对象保存后,自动触发
        pre_delete                  # django的modal对象删除前,自动触发
        post_delete                 # django的modal对象删除后,自动触发
        m2m_changed                 # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
        class_prepared              # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
    Management signals
        pre_migrate                 # 执行migrate命令前,自动触发
        post_migrate                # 执行migrate命令后,自动触发
    Request/response signals
        request_started             # 请求到来前,自动触发
        request_finished            # 请求结束后,自动触发
        got_request_exception       # 请求异常后,自动触发
    Test signals
        setting_changed             # 使用test测试修改配置文件时,自动触发
        template_rendered           # 使用test测试渲染模板时,自动触发
    Database Wrappers
        connection_created          # 创建数据库连接时,自动触发

    调用内置信号的俩种形式

    2,django自定义信号

    1 )、定义信号

    所有的信号都是 `django.dispatch.Signal` 的实例、那么在项目某个app下创建 名为 `custom_signals.py` 的文件,如下这么写

    # filename: custom_singals.py
    
    import django.dispatch
    
    # 声明了一个 `pizza_done` 信号,它将为接收者提供 `toppings`, `size` 参数
    # 可以在任何时候更改这个参数列表
    pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

    并配置信号回调函数

    在项目某个app下创建 名为 `register.py` 的文件,如下这么写

    # filename: register.py
    # 注册信号使用
    
    from app01.custom_singals import pizza_done
    
    
    def pizza_done_func(sender, **kwargs):
        print("msg:", sender, kwargs)
    
    
    pizza_done.connect(pizza_done_func)

    2 )、注册信号

    项目启动的时候要将这些信号注册,那么在对应 `app` 的 `apps.py` 文件中如下

    # filename: app_name/apps.py
    
    from django.apps import AppConfig
    
    # `django` 工具包中封装好的动态导入模块的方法
    from django.utils.module_loading import import_module  
    
    
    class App01Config(AppConfig):
        name = 'app01'
    
        def ready(self):
            # 项目启动所有 `app` 的 `ready` 方法下的代码均会执行
            import_module("app01.register")  # 注册信号

    3 )、发送信号

    事先定义 一组 `url` 映射关系,在视图业务操作中发送我们的信号( 有俩种发送信号的方法 )

    from django.shortcuts import HttpResponse
    
    from app01.custom_singals import pizza_done
    
    
    # Create your views here.
    
    class PizzaStore:
    
        def send_pizza(self, toppings, size):
            # 发送信号
            pizza_done.send(sender=self.__class__, toppings=toppings, size=size)
            # "OR"   上下俩个方法是等价的, 区别 ~ ~
            pizza_done.send_robust(sender=self.__class__, toppings=toppings, size=size)
    
    
    def index(request, ):
        # 业务操作, 执行信号发送操作
        PizzaStore().send_pizza("chicken", "40")
        return HttpResponse("ok")

    Django自定义manage.py命令

    正如之前,已经所知一些 `Django` 的一些命令, 例如 runserver、migrate....,那么它们执行的机制是如何的呢,是否可以做一些其它的命令满足我们的一些需求呢,请看下文

    在 APP 创建相关目录路径,`closepoll.py` 便是自定义的命令文件

    polls/
        __init__.py
        models.py
        management/
            __init__.py
            commands/
                __init__.py
                closepoll.py
        tests.py
        views.py

    文件里面必须继承基类,并实现抽象方法 `handle`

    from django.core.management.base import BaseCommand, CommandError
    from polls.models import Question as Poll
    
    class Command(BaseCommand):
        help = 'Closes the specified poll for voting'
    
        def add_arguments(self, parser):
         # 添加自定义参数,例如 python manage.py runserver -h 0.0.0.0 -p 8080  这样子 ~~
            parser.add_argument('poll_id', nargs='+', type=int) 
    
        def handle(self, *args, **options):
            for poll_id in options['poll_id']:
                try:
                    poll = Poll.objects.get(pk=poll_id)
                except Poll.DoesNotExist:
                    raise CommandError('Poll "%s" does not exist' % poll_id)
    
                poll.opened = False
                poll.save()
    
                self.stdout.write(self.style.SUCCESS('Successfully closed poll "%s"' % poll_id))

    运行自定义命令

    python3 manage.py closepoll -poll_id 10

    # 上述是在命令行运行文件,那么在代码中如何运行,
    from django.core import management
    management.call_command('closepoll', args=())  # 参数详解待更新
  • 相关阅读:
    详解java定时任务
    Java之Exception
    Java设计模式
    Java中的static关键字解析
    浅析Java中的final关键字
    深入理解Java的接口和抽象类
    一个故事讲清楚NIO
    Java并发编程:线程池的使用
    Java垃圾回收机制
    ubuntu sublime text 2 破解版
  • 原文地址:https://www.cnblogs.com/zhangliang91/p/10547645.html
Copyright © 2011-2022 走看看