django创建项目_社区管理

简介: django创建项目_社区管理

项目源代码的下载地址 code aliyun

项目代码下载学习地址

https://code.aliyun.com/734449600/shequguanli/repository/archive.zip?ref=master


编辑好的容器使用

容器大小 252mb

纯净容器地址:registry.cn-hangzhou.aliyuncs.com/mkmk/django:uwsgi

软件bug修复版 registry.cn-hangzhou.aliyuncs.com/mkmk/django:uwsgixctcmanagev1

20200329131704987.png


使用说明

docker run -tid --name uwsgidjango -p 40022:22  -p 48000:8000 --privileged=true   registry.cn-hangzhou.aliyuncs.com/mkmk/django:uwsgixctcmanagev1 init 

生产环境使用可以关闭掉 22 端口, 不写 40022:22 就是关闭容器端口


现在容器中已经有了一个/home/django10 项目 作为展示


将你的django 项目 替换 /home/django10

保留django10 中的 django10.xml 文件

修改为你的项目名称即可

docker exec -it uwsgidjango /bin/bash
执行启动脚本
startDjangoUwsgiNginx.sh

一条命令启动容器

当你完全配置好你的项目以后,可以将你的项目提交为镜像

并使用如下命令直接启动

docker run -tid --name uwsgidjango -p 40022:22  -p 48000:8000 --privileged=true   registry.cn-hangzhou.aliyuncs.com/mkmk/django:uwsgixctcmanagev1 init && docker exec -d uwsgidjango /bin/bash -c "/usr/bin/startDjangoUwsgiNginx.sh"


部署到服务器docker截图

本地docker截图

创建环境容器

docker pull registry.cn-hangzhou.aliyuncs.com/mkmk/centos:ssh
docker run -tid --name uwsgidjango -p 40022:22  -p 48000:8000 --privileged=true   registry.cn-hangzhou.aliyuncs.com/mkmk/centos:ssh init


检查编码与时间是否正常

locale
LANG=zh_CN.UTF-8
LC_CTYPE="zh_CN.UTF-8"
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
LC_MONETARY="zh_CN.UTF-8"
LC_MESSAGES="zh_CN.UTF-8"
LC_PAPER="zh_CN.UTF-8"
LC_NAME="zh_CN.UTF-8"
LC_ADDRESS="zh_CN.UTF-8"
LC_TELEPHONE="zh_CN.UTF-8"
LC_MEASUREMENT="zh_CN.UTF-8"
LC_IDENTIFICATION="zh_CN.UTF-8"
LC_ALL=zh_CN.UTF-8


 date
2020年 03月 29日 星期日 11:26:52 CST

配置必要的环境

python3

yum install python3


安装uwsgi

# 安装依赖
yum install gcc  python36-devel  kernel-devel  libxml*
pip3 install uwsgi 
ln -s /usr/local/bin/uwsgi /usr/bin/uwsgi
uwsgi -version
*** Starting uWSGI 2.0.18 (64bit) on [Sun Mar 29 11:45:14 2020]

配置uwsgi

在项目路径下 django10 等于项目名称

touch /home/django10/django10.xml
chmod 777 /home/django10/django10.xml

添加如下内容

<uwsgi>    
   <socket>127.0.0.1:8999</socket> <!-- 内部端口,自定义 --> 
   <chdir>/home/django10/</chdir> <!-- 项目路径 -->            
   <module>django10.wsgi</module>  <!-- Logistics为wsgi.py所在目录名--> 
   <processes>4</processes> <!-- 进程数 -->     
   <http-keepalive>true</http-keepalive>
   <buffer-size> 32768 </buffer-size>
   <daemonize>/home/django10/uwsgi.log</daemonize> <!-- 日志文件 -->
</uwsgi>

nginx

安装nginx

#安装拓展包,否则找不到nginx
yum install epel-release
yum install nginx

升级sqllite3

由于django需要sqllite3 大于3.8

但是centos自带的sqllite == 3.7 ,所以需要升级

# 下载源码
wget https://www.sqlite.org/2019/sqlite-autoconf-3290000.tar.gz
# 编译
tar zxvf sqlite-autoconf-3290000.tar.gz 
cd sqlite-autoconf-3290000/
./configure --prefix=/usr/local
make && make install
# 替换系统低版本 sqlite3
mv /usr/bin/sqlite3  /usr/bin/sqlite3_old
ln -s /usr/local/bin/sqlite3   /usr/bin/sqlite3
echo "/usr/local/lib" > /etc/ld.so.conf.d/sqlite3.conf
ldconfig
sqlite3 -version
3.29.0 2019-07-10 17:32:03 fc82b73eaac8b36950

配置nginx

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
    worker_connections 1024;
}
http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;
    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;
        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;
        location / {
        }
        error_page 404 /404.html;
            location = /40x.html {
        }
        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
    server {
        listen 8000;
        server_name _ ;
        large_client_header_buffers 4 32k;
            client_header_buffer_size  1k;
        charset utf-8;
            root /home/django10; #项目路径
            location / {
           include uwsgi_params;
           uwsgi_pass 127.0.0.1:8999;
           uwsgi_param UWSGI_SCRIPT django10.wsgi;
           uwsgi_param UWSGI_CHDIR /home/django10/;#项目路径
        }
        location /static/ {
        alias /home/django10/static/; #静态资源路径
      }
     }
# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2 default_server;
#        listen       [::]:443 ssl http2 default_server;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers HIGH:!aNULL:!MD5;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        location / {
#        }
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }
}

启动服务

编写启动脚本

## 编写启动脚本
touch /home/startDjangoUwsgiNginx.sh
chmod 777 /home/startDjangoUwsgiNginx.sh
ln -s /home/startDjangoUwsgiNginx.sh  /usr/bin/startDjangoUwsgiNginx.sh

启动服务

startDjangoUwsgiNginx.sh
查看django.xml 中的日志文件的路径
ModuleNotFoundError: No module named 'django'

新建django 项目

#启动服务器

python manage.py runserver

#迁移应用的 数据库

python manage.py makemigrations polls

提交构建好的镜像

清除内部缓存

暂停进程
pkill -9 uwsgi
pkill -9 python
pkill -9 python3
pkill -9 python*
pkill -9 java
#清除yum缓存
yum clean all
rm -rf /var/cache/yum/*             
*/ 
#清除pip 安装缓存
cd ~/.cache/pip 
rm -rf * 
echo 1 > /proc/sys/vm/drop_caches
echo 2 > /proc/sys/vm/drop_caches
echo 3 > /proc/sys/vm/drop_caches
docker commit [容器名称] registry.cn-hangzhou.aliyuncs.com/mkmk/django:uwsgi
docker push registry.cn-hangzhou.aliyuncs.com/mkmk/django:uwsgi

vue-jquery-bootstrap-django-sqlite3项目开发

创建django项目

ps 觉得手动创建配置文件麻烦的,可以直接去我的 github 下载,示例代码,进行二次开发

创建django项目 项目目录如下

首先我们需要配置环境

导入vue jquery bootstrap

下载 vue.js jquery.js bootstrap.css 放到static 下

配置django静态资源路径

在 项目名/django10/setting.py 中 添加如下配置

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


导入已有信息数据库

编写django setting.py 配置文件如下

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        # 修改这一行为你的数据库
        # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        'NAME': os.path.join(BASE_DIR, 'xctrenyuanxinx.db'),
    }
}

生成数据库 类

注意区分 django 项目名称 与应用名称

python3 manage.py inspectdb > 【app应用名称】/models.py


自动生成数据库如下:

编写view。py

相当于 servlet ,就是处理请求的方法


编写应用内 url.py 的路径映射

vi 项目名/应用名/url.py

from django.urls import path
import villagemanage.views as views
urlpatterns = [
    path('index/', views.index, name='index'),
    path('index2/', views.index2, name='index2'),
    path('getgroupinfo/<pindex>/', views.getgroupinfo, name='getgroupinfo'),
]


添加应用内 url.py 的路径映射 到 项目中

vi 项目名/url.py

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.index, name='index'),
    path('vg/', include('villagemanage.urls')),
]

编写前端视图

里边应用了 vue,循环视图,ajax,jquery, 动态添加元素, 分页等技术,可以参考学习

将 index.html 放到 templates 目录下边

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="/static/css/bootstrap.min.css" rel="stylesheet">
    <script src="/static/js/jquery-3.4.1.min.js"></script>
    <script src="/static/js/vue.min.js"></script>
    <script src="/static/js/bootstrap.min.js"></script>
</head>
 <body style="overflow-y:Scroll;overflow-x:hidden">
<div id="vue1" >
        {#    菜单列#}
        <div class="row navbar  bg-dark navbar-dark ">
      <button class="navbar-toggler bg-secondary navbar-dark" type="button" data-toggle="collapse" data-target="#collapsibleNavbar">
        <a class="navbar-brand" href="#">菜单</a>
                <span class="navbar-toggler-icon"></span>
      </button>
            <div class="col-10 d-flex flex-row-reverse " >
                    <nav class="navbar navbar-expand-sm  bg-secondary navbar-dark">
                      <ul class="navbar-nav ">
                        <li class="nav-item">
                          <a class="nav-link text-white" href="#">关于</a>
                        </li>
                        <li class="nav-item">
                          <a class="nav-link text-white" href="#">帮助</a>
                        </li>
                        <li class="nav-item">
                          <a class="nav-link text-white" href="#">登录</a>
                        </li>
                      </ul>
                    </nav>
          </div>
        </div>
        {#        标题导航一下的内容#}
        <div class="d-flex">
{#            可以展开可以隐藏的 #}
            <div id="collapsibleNavbar" class=" collapse  bg-light text-dark">
                    <div id="accordion">
                      <div   v-for="(item, index) in selectinner" :key="index">
                        <div class="card bg-light text-dark">
                          <div class="card-header" @click="gotosonpage(index)">
                            <a class="card-link" data-toggle="collapse" :href="getidbyindex('#info',index)" >
                              [[ item.head ]]
                            </a>
                          </div>
                          <div :id="getidbyindex('info',index)" class="collapse " data-parent="#accordion">
                            <div class="card-body">
                              [[ item.info ]]
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
            </div>
{#            实际内容展示#}
            <div class="flex-grow-1 bg-light text-dark">
                <div id="sonpage1" v-if=" 0 == nowsonpage"  class="col" style="display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
            width: 1550px">
                    <div class="row">
                        <form id="form1" class="form-inline" style="width: 1200px">
                            <div v-for="(item,index) in mulform.inputid " :key="index" >
                                <label  >[[mulform.inputname[index] ]]</label>
                                <input  type="text" class="form-control" :name="[[mulform.inputid[index] ]]"  :placeholder="[[mulform.phd[index] ]]">
                            </div>
                            <button type="button"  @click="consologroupinfo()" class="btn btn-primary btn-lg">查询</button>
                        </form>
                    </div>
                    <div  class="border border-primary   bg-light text-dark w-75 " style="  overflow:scroll;height: 600px">
                        <table class="table table-striped table-bordered" style="max-width: 90%">
{#                            表头内容#}
                            <thead class="thead-light" style="max-width: 90%">
                                  <tr style="max-width: 90%">
                                        <th style="white-space:nowrap ;max-width: 90%"  v-for="item in mulform.tablehead  ">[[item]]</th>
                                  </tr>
                            </thead>
{#                            表格中的每条信息#}
                        <tbody id="tb1" style="max-width: 90%">
                        </tbody>
                        </table>
                    </div>
                <div class="row">
                       <ol class="breadcrumb">
                           <li class="breadcrumb-item">共  <span class="badge badge-pill badge-success">[[sumpageindex]] </span> 页</li>
                           <li class="breadcrumb-item"><span @click="gotothesepage(-1)" class="badge badge-pill badge-success">上一页 </span></li>
                           <li class="breadcrumb-item">当前 <span class="badge badge-pill badge-success"> [[groupinfopindex]] 页</span></li>
                           <li class="breadcrumb-item active"><span @click="gotothesepage(1)" class="badge badge-pill badge-success"> 下一页 </span></li>
                           <li class="breadcrumb-item active">跳转至<input v-model="groupinfopindex" type="number" />  </li>
                           <li class="breadcrumb-item active"><span class="badge badge-pill badge-primary" @click="consologroupinfo()"><h6>点击跳转</h6></span></li>
                       </ol>
                    </div>
                </div>
                 <div id="sonpage2" v-if=" 1 == nowsonpage"> 模块 2  </div>
                 <div id="sonpage3" v-if=" 2 == nowsonpage"> 模块 3  </div>
            </div>
        </div>
</div>
</body>
<script type="text/javascript">
    var vm = new Vue({
        delimiters:['[[', ']]'],
        el: '#vue1',
        data: {
            {#代表当前显示的子页面序号#}
            nowsonpage:0,
            {# 下拉菜单中的标题以及介绍 #}
            selectinner:[{ "head": "按条件查询群体信息","info":"按照条件筛选出符合要求的多个人员信息" },
                        { "head": "个人信息录入与删除","info": "单个人员的信息导入与删除" },
                        { "head": "批量导入与删除","info": "批量导入多个人员信息,或者批量删除信息" }],
            {# 集体查询的提交表单    #}
            mulform:{inputid:["name","idnumber","loudao","danyuan","menpaihao","loudaozhang","nianling0","nianling1","xingbie"],
                inputname:["名字","身份证号码","楼道","单元 ","门牌号","楼道长","年龄下限","年龄上限","性别"],
                phd:["名字","身份证号码","楼道","单元 ","门牌号","楼道长","年龄下限","年龄上限","性别"],
                tablehead:["序号","姓名","年龄","性别","身份证号","管理类型","与户主关系","户主","户编号","楼栋","楼道长","楼道长电话","单元号","门牌号","本人联系电话","政治面貌","最高学历","民族","居住社区","婚姻状况"]
              },
            groupinfo:new Array(),
            groupinfopindex:1,
            sumpageindex:"?"
        },
        watch:{
              groupinfo:{ //监听的对象
                deep:true, //深度监听设置为 true
                handler:function(newV,oldV){
                  console.log('watch中:',newV)
                }
              }
            },
        methods: {
             {# 将子页面切换到 index 子页面 #}
             gotosonpage: function(index){
                 this.nowsonpage=index
             },
             {# 根据元素 id 以及 名称 绑定 id#}
             getidbyindex: function(name,index){
               return name+"_"+index
             },
             consologroupinfo:function (){
                 let that=this;
                $.ajax({
                    url : "/vg/getgroupinfo/"+that.groupinfopindex+"/",
                    type : "post",
                    headers : {
                        "X-CSRFToken": '{{ csrf_token }}'
                    },
                    dataType : "json",
                    data : $("#form1").serialize(),
                    success : function (data){
                        that.groupinfo=data.allinfo;
                        that.sumpageindex=data.sumpageindex;
                        var insertstr1=""
                        for(let index1 in that.groupinfo){
                            {#console.log(item);#}
                             insertstr1+='<tr style="max-width: 90%">'
                            for(let index2 in that.groupinfo[index1]){
                                 insertstr1+='<td style="max-width: 90%">'+that.groupinfo[index1][index2]+"</td>"
                            }
                            insertstr1+="</tr>"
                        }
                        var obj1=$("#tb1")
                        obj1.empty();
                        obj1.append(insertstr1)
                        console.log(that.groupinfo);
                        {#alert(data.allinfo)#}
                    },
                    error:function(){
                        alert("发生错误,请检查输入条件以及页最大编号");
                    }
                });
            },
            gotothesepage: function(offset){
                this.groupinfopindex+=offset;
                if(this.groupinfopindex < 1){
                    this.groupinfopindex=1;
                    alert("当前已经在第一页!")
                    return;
                }
                if(this.groupinfopindex > this.sumpageindex){
                    this.groupinfopindex=this.sumpageindex;
                    alert("当前已经在最后一页了!")
                    return;
                }
                this.consologroupinfo();
            },
            details: function() {
                return  this.site + " - 学的不仅是技术,更是梦想!";
            }
        }
    })
</script>
</html>

js常用代码

替换节点样式

思路,通常后端生成的元素节点样式难以改变,我们可以通过,隐藏节点,新建 好看的节点,关联两者的 各种事件即可

<script type="text/javascript">
                                {#$('#id_touxiang').value="上传",#}
{#                                 美化上传文件的按钮 ,并优化 上传图片的大小 #}
                                $(document).ready(function() {
                                    $('#id_touxiang').hide();
                                    var button1 = $('<button type="button" class="btn btn-success" id="id_touxiang2" style="font-size: 60px">点击拍照或上传头像</button>');
                                    $('#id_touxiang').after(button1);
                                    $('#id_touxiang2').click(function () {
                                        $('#id_touxiang').click()
                                    });
                                });
 </script>

美化前后对比

选择文件时压缩图片


随着手机像素越来越高,上传图片时,图片体积太大时有发生,为了减轻服务器压力,压缩图片尺寸时必要的

//file 上传图片,绑定change事件
<input type="file" onChange="uploadPic(this)" accept="image/*" />
function uploadPic(e) {
        var file = e.files[0];
        function callback(data){//回调获取压缩后的Blog
           if(data){
               console.log("压缩成功")
           }
         }
        this.compress(file, callback);
    }
//当图片宽度大于640时 进行等比例压缩,并返回Blob,否则返回false
function compress(fileObj, callback) {
        function dataURLtoBlob(dataurl) {//base64格式图片 转为Blob  
            var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
                bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
            while (n--) {
                u8arr[n] = bstr.charCodeAt(n);
            }
            return new Blob([u8arr], { type: mime });
        }
        if (typeof (FileReader) === 'undefined') {
            console.log("当前浏览器内核不支持base64图标压缩");
            return false;
        } else {
            try {
                var reader = new FileReader();
                var image = new Image();
                reader.readAsDataURL(fileObj);//开始读取指定的Blob中的内容。返回base64
                reader.onload = function (ev) {
                    image.src = ev.target.result;
                    image.onload = function () {
                        var imgWidth = this.width,
                            imgHeight = this.height; //获取图片宽高
                        if (imgWidth > 640) {//设置图片的最大宽度为640
                            imgWidth = 640;
                            imgHeight = 640 / this.width * imgHeight;//设置等比例高度
                            var canvas = document.createElement('canvas');
                            var ctx = canvas.getContext('2d');
                            canvas.width = imgWidth;
                            canvas.height = imgHeight;
                            ctx.drawImage(this, 0, 0, imgWidth, imgHeight);//根据宽高绘制图片
                            var fullQuality = canvas.toDataURL("image/png", 1.0);//canvas转为base64
                            var blogData=dataURLtoBlob(fullQuality);
                            callback(blogData);
                        }else{
                            callback(false);
                        }
                    }
                }
            } catch (e) {
                console.log("压缩失败!");
            }
        }
    }


图像压缩


依赖包网址https://cdn.jsdelivr.net/gh/WangYuLue/image-conversion/build/conversion.js
 
  function view(){
  const file = document.getElementById(‘demo’).files[0];
  console.log(file);
  imageConversion.compressAccurately(file,200).then(res=>{
  //The res in the promise is a compressed Blob type (which can be treated as a File type) file;
  console.log(res);
  })
  }

上传压缩的图片

第一步压缩图片到一个全局变量

function yasuoimg(elementid) {
  const file = document.getElementById(elementid).files[0];
{#  console.log(file);#}
  imageConversion.compressAccurately(file,200).then(res=>{
  //The res in the promise is a compressed Blob type (which can be treated as a File type) file;
  var inputfile0=document.getElementById(elementid).files[0];
  console.log("压缩前",inputfile0);
  filehaveyasuo = new window.File([res],inputfile0.name,{ type: inputfile0.type });
  console.log("压后",filehaveyasuo);
  $('#id_touxiang3').attr("src",URL.createObjectURL(res));
  })
}

修改formdata 中的数据

<script type="text/javascript">
 function uploadformset() {
  //得到django的 密匙
  {#var csrftoken = getCookie('csrftoken');#}
  var form = new FormData(document.getElementById("uploadinfo2"));
  for (var key of form.keys()) {
            console.log("修改前",key);
         }
  console.log("压缩后的图片",filehaveyasuo);
  form.delete('touxiang')
  form.append('touxiang', filehaveyasuo)
  for (var key of form.keys()) {
            console.log("修改后",key);
         }
  console.log("修改添加的文件后",form.get('touxiang'))
  $.ajax({
      cache: false,
      type: 'POST',
      // 根据表单id 生成数据
      data: form,
      url: "/new/uploadoneinfo/",
      traditional:true, //为必须内容   
      //dataType:'json',  //data为json时必须
      processData: false, //为必须内容
      contentType: false, //为必须内容
      success: function(data) {
         console.log(data);
      },
      beforeSend: function(xhr, settings) {
          {#xhr.setRequestHeader("X-CSRFToken", csrftoken);#}
      }
  });
 }
</script>


相关文章
|
4月前
|
API 数据库 Python
Python 教程之 Django(8)在 Django 管理界面中渲染模型
Python 教程之 Django(8)在 Django 管理界面中渲染模型
24 0
Python 教程之 Django(8)在 Django 管理界面中渲染模型
|
6月前
|
搜索推荐 算法 前端开发
旅游管理与推荐系统Python+Django网页平台+协同过滤推荐算法
旅游管理与推荐系统Python+Django网页平台+协同过滤推荐算法
149 0
|
3月前
|
前端开发 关系型数据库 MySQL
基于python+django+vue.js开发的社区养老管理系统
基于python+django+vue.js开发的社区养老管理系统
106 1
|
4月前
|
搜索推荐 算法 前端开发
美食物管理与推荐系统Python+Django网站开发+协同过滤推荐算法应用【计算机课设项目推荐】
美食物管理与推荐系统Python+Django网站开发+协同过滤推荐算法应用【计算机课设项目推荐】
106 4
美食物管理与推荐系统Python+Django网站开发+协同过滤推荐算法应用【计算机课设项目推荐】
|
15天前
|
数据处理 数据库 开发者
Django中的自定义管理命令:扩展管理功能的途径
【4月更文挑战第15天】Django教程:介绍如何创建和使用自定义管理命令以扩展框架功能。在应用的`management/commands`目录下创建Python文件,继承`BaseCommand`,实现`handle`方法。示例代码展示了如何定义参数和执行逻辑。自定义命令适用于批量数据处理、定期任务、项目初始化和自定义迁移操作。注意文件位置、命令安全性和稳定性。自定义管理命令能提升开发和维护效率。
|
15天前
|
关系型数据库 API 数据库
Django中的数据库事务管理:确保数据一致性
【4月更文挑战第15天】Django框架提供强大的数据库事务管理,确保ACID属性,保证数据一致性和完整性。文章深入讨论了Django事务管理,包括使用`@transaction.atomic`装饰器和`transaction.atomic()`上下文管理器手动控制事务,以及低级API进行精细管理。注意避免长时间事务、选择合适隔离级别、正确处理异常及了解数据库特性。掌握这些技巧对构建可靠Web应用至关重要。
|
18天前
|
前端开发 Python
Django路由管理:react-router或者urls.py
Django路由管理:react-router或者urls.py
|
5月前
|
搜索推荐 算法 前端开发
商品购物管理与推荐系统Python+Django网页界面+协同过滤推荐算法
商品购物管理与推荐系统Python+Django网页界面+协同过滤推荐算法
67 0
|
4月前
|
存储 安全 数据库
关于“Python”Django 管理网站的核心知识点整理大全52
关于“Python”Django 管理网站的核心知识点整理大全52
19 0
|
5月前
|
算法 关系型数据库 API
Python【算法中心 02】Web框架Django管理页面使用(管理员账号创建+API使用+应用添加)GreenPlum数据库引擎及API测试
Python【算法中心 02】Web框架Django管理页面使用(管理员账号创建+API使用+应用添加)GreenPlum数据库引擎及API测试
43 0