在此处打开Cmd

因为习惯了Linux可以直接在当前目录打开终端,但 PowerShell 我用起来又没那么舒服(windows10在最近的更新之后默认的就是打开 PowerShell 而不是 cmd 了,虽然可以改,但有时候我还是想用 PowerShell 的)。于是查资料搞了一波注册表修改,既不影响原有的shift+滑鼠右键打开 PowerShell 的方式,又增加了直接滑鼠右键在当前目录下打开CMD的效果。
把以下代码保存为OpenCmdHere.reg
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Directory\shell\OpenCmdHere]
@="在此处打开命令提示符"
"Icon"="cmd.exe"

[HKEY_CLASSES_ROOT\Directory\shell\OpenCmdHere\command]
@="cmd.exe /s /k pushd "\%V\""

[HKEY_CLASSES_ROOT\Directory\Background\shell\OpenCmdHere]
@="在此处打开命令窗口"
"Icon"="cmd.exe"

[HKEY_CLASSES_ROOT\Directory\Background\shell\OpenCmdHere\command]
@="cmd.exe /s /k pushd "\%V\""

[HKEY_CLASSES_ROOT\Drive\shell\OpenCmdHere]
@="在此处打开命令窗口"
"Icon"="cmd.exe"

[HKEY_CLASSES_ROOT\Drive\shell\OpenCmdHere\command]
@="cmd.exe /s /k pushd "\%V\""

[HKEY_CLASSES_ROOT\LibraryFolder\background\shell\OpenCmdHere]
@="在此处打开命令窗口"
"Icon"="cmd.exe"

[HKEY_CLASSES_ROOT\LibraryFolder\background\shell\OpenCmdHere\command]
@="cmd.exe /s /k pushd "\%V\""
然后双击运行就OK了。

纯Css画聊天气泡

这学期我们有门必修的选修课C#,期末大作业我做的是个Socket通讯的软件,什么加密,打洞通讯都写好了。最后写界面的时候,觉得纯文字太单调了,于是用了WebBrowser控件做聊天界面。由于CSS不怎么熟,写了好几个小时才搞出想要的聊天气泡效果。遂做记录。

一个正常的聊天气泡应该这个样子

  • 圆角矩形很容易,一行边框属性设定 border-radius: 5px;
  • 画尖角同样的使用边框,只不过这个边框很粗,粗到至少比元素本身大。想想那个流传许久的加一条线把一个五边形分成两个三角形的题目就能理解了。
    那么我直接把元素本身的高宽设置成0,然后边框的粗细就是三角形的大小了,三角形的颜色自然也就是边框的颜色。
width: 0;
height: 0;
border: 12px solid transparent;
border-right-color: #D3D3D3;
接下来就是把圆角矩形和尖角拼接起来了,尖角这个只有装饰性的作用让我想起了beforeafter,在翻阅了MDN关于伪元素的介绍之后我成功写出了气泡。
然而开心之后我发现这玩意在长文本的时候,尖角会错位。于是我又查了查定位,用绝对定位解决了错位问题。之所以不用相对定位,是因为相对定位会导致这个元素在原来位置的空间不会被其他元素使用,就会莫名占了一行,比较难看。
总的代码如下:
    .left {
        float: left;
    }
    .right {
        float: right;
    }
    .message {
        position: relative;
        min-height: 20px;
        background: #D3D3D3;
        border-radius: 5px;
        word-break: break-word;
        font-size: 18px;
        color: black;
        padding: 8px;
    }
    .left .message::before {
        content: "";
        display: block;
        position: absolute;
        width: 0;
        height: 0;
        float: left;
        line-height: 0px;
        border: 12px solid transparent;
        border-right-color: #D3D3D3;
        top: 7px;
        left: -24px;
    }
    .right .message::after {
        content: "";
        display: block;
        position: absolute;
        width: 0;
        height: 0;
        float: right;
        border: 12px solid transparent;
        border-left-color: #D3D3D3;
        top: 7px;
        right: -24px;
    }
使用就很简单,左边的气泡就把message包裹在left里,右边同理。至于message元素到底是<div>还是<p>,我暂时没发现差别,都是一样的。(拒绝支持IE6!)
<div class="left">
    <div class="message">
        我在左边
    </div>
</div>
<div class="right">
    <p class="message">
        我在右边
    </p>
</div>

参考链接:

django-suitV2 美化django后台

一. 基本配置


根据官方文档来安装好之后。
pip install https://github.com/darklow/django-suit/tarball/v2
在项目的setting.py中增加一行'ProjectName.apps.SuitConfig',
INSTALLED_APPS = [
    # other statements
    'ProjectName.apps.SuitConfig',
    'django.contrib.admin',
    # other statements
]
确保django.contrib.admin在下面。
然后在setting.py同目录下建立新的文件apps.py加入以下代码
from suit.apps import DjangoSuitConfig

class SuitConfig(DjangoSuitConfig):
    layout = "vertical"
layout属性值决定后台的布局是横式还是竖式,分别对应:‘horizontal’‘vertical’

二. 高级配置


表格颜色

在后台数据表格一条条的,对于一些特殊的数据,我们会期待它们有不同的颜色。
admin.py的为模型类注册的管理类中增加如下方法即可改变颜色
    def suit_row_attributes(self, obj, request):
        class_map = {
            'Europe': 'table-success',
            'South America': 'table-warning',
            'North America': 'table-success',
            'Africa': 'table-danger',
            'Australia': 'table-warning',
            'Asia': 'table-info',
            'Antarctica': 'table-info',
        }
        css_class = class_map.get(obj.name)
        if css_class:
            return {'class': css_class}
map的keys是get()中的值,values则是对应的颜色。


to be continue...

Django后台导出数据到Excel并下载

肯定有很多人都有这样的需求,“小x,把这个数据给我整理成表格”,Django作为常用的搭建公司内部数据展示的框架很多时候也需要一个一键导出到excel功能。

注册Action


在Django自带的后台里,选定后,选项往往只有删除一个功能,Django的Admin模块允许我们自己注册功能到该选项框里。
@admin.register(Debit)
class DebitAdmin(admin.ModelAdmin):
    # other statements
    actions = ["SaveExecl",]
actions就是自定义的动作的名称列表。( 功能代码写好千万别忘了注册

编写Action函数


在注册之后,需要自己编写对应的函数,注意函数名要和action这个列表里的某一个字符串一致。

  • 修改函数显示名称
def SaveExecl(self, request, queryset):
    pass
SaveExecl.short_description = "以表格形式下载"
(注意以上缩进没错,它两的相对缩进就是如此 !)
这个函数在后台显示为 short_description 的内容,然而如果你不自己写 short_description 它就会显示原本的函数名称 ( 英文对那些英语不好的中国人太不友好

  • 编写储存表格部分
注意到上面函数定义的时候有三个参数,第一个和第二个暂且不管,在这里我们只需要知道第三个参数是被选中的数据。根据这一点可以遍历获取每一条数据
for each in queryset:
    pass
    '''
    一个each就是一条数据
    访问每一条数据的内容只需要执行类似于 each.Name 的语句即可
    因为每个人使用的编写模块和需求不一定一样,所以在这里不放代码只解释怎么获取数据
    '''
  • 编写下载表格部分
这里采取的是一个流的方法,基本能适用于大部分情况。
直接塞进 HttpResponse 里这种只适用小文件的方法就不放出来了。
在以上函数里增加如下代码,filename 需要是一个存在的文件路径,在这里也就是上面储存的表格文件名称。倒数第二行最右边的Result.xls根据想要的下载的时候显示的文件名称来改名。( 我试了,不知道为啥中文不行。)
        def file_iterator(filename, chunk_size=512):
            with open(filename,'rb') as f:
                while True:
                    c = f.read(chunk_size)
                    if c:
                        yield c
                    else:
                        break
        
        response = StreamingHttpResponse(file_iterator(filename))
        response['Content-Type'] = 'application/octet-stream'
        response['Content-Disposition'] = 'attachment; filename="{}" '.format("Result.xls")
        return response
啊,这段代码是我写的时候抄别人的,但是网上到处是这同一段代码,不知道来源就不贴原帖了。


最后还是贴一下整体的代码。写注释的两个地方需要写上自己的需要的操作
from django.contrib import admin
from .models import Debit
from django.http import StreamingHttpResponse
import xlwt
import os

@admin.register(Debit)
class DebitAdmin(admin.ModelAdmin):
    # other statements
    actions = ["SaveExecl",]
    def SaveExecl(self, request, queryset):
        filename = "统计表.xls"
        if os.path.exists(filename):
            os.remove(filename)
        
        Begin = xlwt.Workbook()
        # some sentences
        Begin.save("%s"%(filename))
        
        def file_iterator(filename, chunk_size=512):
            with open(filename,'rb') as f:
                while True:
                    c = f.read(chunk_size)
                    if c:
                        yield c
                    else:
                        break
        
        response = StreamingHttpResponse(file_iterator(filename))
        response['Content-Type'] = 'application/octet-stream'
        response['Content-Disposition'] = 'attachment; filename="{}" '.format("Result.xls")
        return response
    SaveExecl.short_description = "以表格形式下载"

关于表格的处理部分,xlsx我是用openpyxl,操作简单,做出来的图表炫酷。

Django后台自定义各种名称


众所周知,Django默认的后台是英文。在修改了Settings之后,Django自带的改成了中文,自己写的App对应的依旧是英文。
于是花了一些时间来查咋改名字。毕竟中国人更适应中文。

修改App名称


对应的App目录下的apps.py文件里有Django自动生成的AppNameConfig类 (如果没有,说明这个App不是manage.py startapp AppName命令生成的)。
一般这个类里只有默认的一个属性name,我们自己增加两条属性
class AppNameConfig(AppConfig):
    name = 'appname'
    verbose_name = u"应用名称"
    verbose_name_plural = u"应用名称"
然后在对应的App目录下__init__.py文件里增加一条语句
default_app_config = 'AppName.apps.AppNameConfig'
然后重启服务器即可。

修改Model名称


在自己定义的model类里面增加class Meta然后重启服务器即可
class Example(models.Model):
    # other statements
    class Meta:
        verbose_name = u"模块名称"
        verbose_name_plural = u"模块名称"

修改Model内字段名称


这几乎是所有Django教程里都会提到的,定义时增加verbose_name参数即可
class Example(models.Model):
    Name = models.CharField(verbose_name="姓名", max_length=20)

修改默认的Django标题


Django自带的后台页面左上角硕大的Django字样和页面标题,还有后台首页的标题都可以很容易的进行修改。只需要在随便一个导入了admin模块的文件里增加几行代码
admin.site.site_header = '我在左上角'  
admin.site.site_title = '我在浏览器标签'  
admin.site.index_title = '我在后台首页'  
  • 注意:如果你用了类似于suit之类的美化后台的第三方库,修改标题就不能如此。


挖个坑,等suitV2文档写好,准备写一篇使用suitV2来美化后台的。

Python脚本使用命令行参数


最近使用you-get在Youtube上下载了一系列电视剧,但是下载下来的文件名实在是。。
于是写了一个批量修改文件名的脚本,突发奇想的用一波命令行参数,于是search了一波,发现谷歌出来的文章写的都不甚明了,于是我去找了Python标准库文档。

getopt模块


使用getopt模块来进行命令行处理并不难
import sys, getopt
opts, args = getopt.getopt(sys.argv[1:], "hFD:C", ["help", "path="])
sys.argv
sys.argv是命令行参数列表,例如输入如下命令
python test.py -F test test_1
那么,sys.argv的内容为["test.py", "-F", "test", "test_1"]。要记住sys.argv[0]永远是调用的脚本名,所以对参数的处理应该从sys.argv[1]开始。
getopt.getopt
  • 第一个参数
    该函数第一个参数是需要处理的命令,如上所说,从sys.argv[1]开始。
  • 第二个参数
    第二个参数包含所有需要处理的短选项,譬如需要处理-F,-h,-C三个短选项,那么第二个参数使用hFC。如果某个短选项需要参数,譬如使用-F test,那么第二个选项中的 F 应该在后面加一个:。譬如hF:C,就意味着可以处理这三个参数,其中-F需要参数。
  • 第三个参数
    第三个参数是一个列表,包含所有需要处理的长选项。譬如["help", "path="]就意味着能处理--help和带参数的--path的选项。
  • 返回值
    该函数会返回两个值,第一个是包含(key, value)的列表,第二个是没有匹配到选项的剩余参数列表。
使用起来很简单
import sys, getopt
opts, args = getopt.getopt(sys.argv[1:], "hFD:C", ["help", "path="])
for each in opts:
    print(each[0])
    print(each[1])
for each in args:
    print(each)

argparse模块


这个是3.2版本之后新增的模块。也用于处理命令行
目前没需求,暂时懒得看。先挖坑,以后填

一个使用命令行参数的小脚本在我的Github

配合Nginx使用Uwsgi部署Django

最近实在是没什么事情干。正好又有一台CentOS服务器空着。

下载Nginx,uwsgi, Mysql


我用的是CentOS7和Python3.5,所以如下(安装新版Python参照另一篇)
yum install -y nginx mariadb mariadb-devel mariadb-server
pip3.5 install uwsgi

编写uwsgi,nginx, mysql配置


按照官方文档的说法,我写了如下配置,保存在项目根目录下的uwsgi.ini中
[uwsgi]
socket = /website/proxy/DOCUMENTS/uwsgi.sock
chmod-socket = 777
processes = 4
threads = 2
stats = 127.0.0.1:9001
chdir = /website/proxy/
wsgi-file = proxy/wsgi.py
daemonize = DOCUMENTS/uwsgi.log
pidfile = DOCUMENTS/proxy-master.pid
然后nginx中这样写
upstream django {
    server unix://website/proxy/DOCUMENTS/uwsgi.sock;
}
server {
    listen       80;
    server_name  192.168.78.142;
    location / {
        include uwsgi_params;
        uwsgi_pass django;
    }
    location /static/ {
        alias /website/proxy/static/;
    }
}
uwsgi_pass的值和uwsgi.ini配置中socket的值必须一致。

配置mysql

/etc/my.cnf加入以下代码以配置默认编码为UTF8
[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
接下来三条命令
# start mariadb
sudo systemctl start mariadb
# Harden MySQL Server
sudo mysql_secure_installation
sudo systemctl enable mariadb

nginx开机自启动


使用vi /etc/init.d/nginx写入如下代码
#!/bin/bash
# chkconfig: - 85 15
nginx = /usr/sbin/nginx
conf = /etc/nginx/nginx.conf

case $1 in
    start)
        echo -n "Starting Nginx"
        $nginx -c $conf
        echo " done"
    ;;

    stop)
        echo -n "Stopping Nginx"
        $nginx -s stop
        echo " done"
    ;;

    test)
        $nginx -t -c $conf
    ;;

    reload)
        echo -n "Reloading Nginx"
        $nginx -s reload
        echo " done"
    ;;

    restart)
        $0 stop
        $0 start
    ;;

    show)
        ps -aux|grep nginx
    ;;

    *)
        echo -n "Usage: $0 {start|restart|reload|stop|test|show}"
    ;;

esac
然后使用三条命令:
sudo chmod +x /etc/init.d/nginx
sudo chkconfig --add nginx
sudo chkconfig nginx on

uwsgi开机自启动


同理,使用vi /etc/nginx/uwsgi写入
#!/bin/bash
# chkconfig: - 85 15
uwsgi = /usr/local/bin/uwsgi
path = /path/to/djangoproject/
conf = uwsgi.ini
pid = ProjectName-master.pid

case $1 in
    start)
        cd $path
        $uwsgi $conf
    ;;

    stop)
        $uwsgi --stop $path$pid
    ;;

    show)
        ps -ef|grep uwsgi
    ;;

    reload)
        $uwsgi --reload $path$pid
    ;;

    *)
        echo -n "Usage: $0 {start|restart|stop|show}"
    ;;

esac
然后使用三条命令:
sudo chmod +x /etc/init.d/uwsgi
sudo chkconfig --add uwsgi
sudo chkconfig uwsgi on
最后,使用命令sudo service uwsgi startsudo service nginx start开启网站。

多站点配置方法


因为暂时还没这个需求,就懒的去看文档了,http://uwsgi-docs-zh.readthedocs.io/zh_CN/latest/Emperor.html里提到了多站点的配置
以后我需要了,再来把这个坑给填掉。