跳至主要内容

博文

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

肯定有很多人都有这样的需求,“小x,把这个数据给我整理成表格”,Django作为常用的搭建公司内部数据展示的框架很多时候也需要一个一键导出到excel功能。 注册Action 在Django自带的后台里,选定后,选项往往只有删除一个功能,Django的Admin模块允许我们自己注册功能到该选项框里。 @admin.register(Debit)classDebitAdmin(admin.ModelAdmin):# other statements actions = ["SaveExecl",] actions就是自定义的动作的名称列表。( 功能代码写好千万别忘了注册 编写Action函数 在注册之后,需要自己编写对应的函数,注意函数名要和action这个列表里的某一个字符串一致。 修改函数显示名称defSaveExecl(self, request, queryset):pass SaveExecl.short_description = "以表格形式下载" (注意以上缩进没错,它两的相对缩进就是如此 !)
这个函数在后台显示为 short_description 的内容,然而如果你不自己写 short_description 它就会显示原本的函数名称 ( 英文对那些英语不好的中国人太不友好 编写储存表格部分 注意到上面函数定义的时候有三个参数,第一个和第二个暂且不管,在这里我们只需要知道第三个参数是被选中的数据。根据这一点可以遍历获取每一条数据 for each in queryset: pass''' 一个each就是一条数据 访问每一条数据的内容只需要执行类似于 each.Name 的语句即可 因为每个人使用的编写模块和需求不一定一样,所以在这里不放代码只解释怎么获取数据 ''' 编写下载表格部分 这里采取的是一个流的方法,基本能适用于大部分情况。
直接塞进 HttpResponse 里这种只适用小文件的方法就不放出来了。 在以上函数里增加如下代码,filename 需要是一个存在的文件路径,在这里也就是上面储存的表格文件名称。倒数第二行最右边的Result.xls根据想要的下载的时候显示的文件名称来改名。( 我试了,不知道为…

Django后台自定义各种名称

众所周知,Django默认的后台是英文。在修改了Settings之后,Django自带的改成了中文,自己写的App对应的依旧是英文。
于是花了一些时间来查咋改名字。毕竟中国人更适应中文。 修改App名称 对应的App目录下的apps.py文件里有Django自动生成的AppNameConfig类 (如果没有,说明这个App不是manage.py startapp AppName命令生成的)。
一般这个类里只有默认的一个属性name,我们自己增加两条属性 classAppNameConfig(AppConfig): name = 'appname' verbose_name = u"应用名称" verbose_name_plural = u"应用名称" 然后在对应的App目录下__init__.py文件里增加一条语句 default_app_config = 'AppName.apps.UsersConfig' 然后重启服务器即可。 修改Model名称 在自己定义的model类里面增加class Meta然后重启服务器即可 classExample(models.Model):# other statementsclassMeta: verbose_name = u"模块名称" verbose_name_plural = u"模块名称" 修改Model内字段名称 这几乎是所有Django教程里都会提到的,定义时增加verbose_name参数即可 classExample(models.Model): Name = models.CharField(verbose_name="姓名", max_length=20) 修改默认的Django标题

Python脚本使用命令行参数

最近使用you-get在Youtube上下载了一系列电视剧,但是下载下来的文件名实在是。。
于是写了一个批量修改文件名的脚本,突发奇想的用一波命令行参数,于是search了一波,发现谷歌出来的文章写的都不甚明了,于是我去找了Python标准库文档。 getopt模块 使用getopt模块来进行命令行处理并不难 import sys, getopt opts, args = getopt.getopt(sys.argv[1:], "hFD:C", ["help", "path="]) sys.argvsys.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)的列表,第二个是没有匹配到选项的剩余参数列表。 使用起来很简单

无符号长整数四则运算

最近在学数据结构,老师给我们布置了一个大数计算作业。于是花了两天用C++写了一个Unsigned Large类,把四则运算,位移运算,比较运算,输入输出,和内置类型的相互转化全部重载了一遍。其中除法用了很久,遂作此篇以记录。 加减实现起来很容易,不外乎对每一个位置实现全加器,处理进位借位。
对于加法,最高位进位要注意是否补1。
对于减法,最高位要注意去0。 乘法 鉴于我渣渣的数学水平,谷歌出来的简易方法我不会用。于是只能模拟手算了。 对于任意无符号整数都可以将其分解成 a0+a1﹡101+a2﹡102+……+an﹡10n 那么对于任意无符号长整数A*B都可以分解成 (a0+a1﹡101+a2﹡102+……+an﹡10n)﹡(b0+b1﹡101+b2﹡102+……+bn﹡10n) 注意到10m 的系数为 ∑ai*bj,i+j=m
接下来只需要将系数进行遍历,降到个位,每降一次自减10,进位+1。
即可。 result.Start[0] = 0; for (int i = 0; i < length + temp.length; i++) { int sum = 0; for (int j = 0; j <= i; j++) { if (i - j < temp.length && j < length) { sum += Start[j] * temp.Start[i - j]; } } result.Start[i] += sum; result.Start[i + 1] = 0; while (result.Start[i] > 9) { result.Start[i] -= 10; result.Start[i + 1] += 1; } result.length++; } 除法 除法模拟手算太麻烦了,于是考虑了二分法。

Django随机抛出数据

因为在写一个自己用的ProxyWeb,主要功能是从各种免费代理网站爬取有效的代理,然后提供一个API给我自己,每访问一次这个API就随机从已有的数据库里抛出一个代理给我用。 但随机抛出,我没想到啥好办法,因为pk的范围实在是无法确定,没法用get+随机pk来获取代理信息,所以谷歌了一番。 较高效的随机抛出数据 直接给出方法 Record.objects.all()[random.randint(0, Record.objects.count() - 1)] 一些比较慢的方法1Record.objects.order_by('?')[:2] 这个在StackOverflow上被一个大佬指出在含有大量数据的数据库中会极其缓慢,我没测试过,不过大佬说的有理有据,我觉得是没有错的。 大佬是这样说的(我根据印象里大佬的话写的,不是翻译出来的哈): 这个方法会获取整张表的所有数据,进行随机排序后取前两条数据 试想,如果整张表含有几百万条甚至千万条数据,全部读出来排序(虽然是随便排,但还是需要排一遍对吧),这玩意该花多久。反正我的破电脑说不定直接就死机了hhh 2my_ids = MyModel.objects.values_list('id', flat=True) rand_ids = random.sample(my_ids, 2) random_records = MyModel.objects.filter(id__in=rand_ids) 这个也比较慢,第一行读取了整张表所有数据的 id ,第二行从这些 id 里随便抽两个,第三行根据第二行随机出来的两个 id 来筛选数据。
个人认为比第一种略快,但比最上面的方法略慢一些。因为读取id并生成一个列表比起count要慢一些。

Python中的for else

遇见很多人问过Python中一次跳出多重循环的优雅方法,遂作此篇。

python中有一个很神奇的for else搭配。 for each in list: # some sentences else: # some sentences 在for 正常结束时,会执行else中的语句。而当for循环中有break并执行时,else包裹的代码块将不会执行。 多重循环的跳出 在C++可以使用goto轻松愉悦的一次性跳出多重循环,然而python中并没有goto或者相似的语法设计,于是多重循环的一次性跳出总是让人觉得很烦躁,或许会写出很多个if来判断是不是该跳出去。
这时候可以利用for else语句神奇的设定来做到优雅地跳出。 for each_0 in list_0: for each_1 in list_1: for each_2 in list_2: if something: break else: #some sentence continue break else: #some sentence continue break else: #some sentences 根据for else的规则,不难看出,在something为假时,任何一个break语句都不会被触发,因为被continue掉了。而一旦第一个break成立,就像雪崩一样,多重循环的每一层break都被触发,直接跳出多重循环,而避免了多次if判断是否满足跳出条件。 查找判断的优雅写法 在C++中,需要查找某一个序列中是否存在特定元素,也许会写出这样的代码 #include<iostream> int main(void) { int list[10];int i=0; //赋值等语句略过 for(;i<10;i++) { if (list[i]==number) break; } if (i<10) { std::cout<<"…

抓取期末成绩

上一次,我使用selenium来抓取我校教务系统的信息,但是速度太慢。
于是我抓了教务系统的安卓端的包,分析了一下。 简单分析 用户成功登录之后都会有一个session记录在服务器,并且在后续的操作中必须发送这个sessionid才行。登陆成功的其他信息和sessionid会以json格式发送回来。 所以利用requests这个库很容易就能抓到想要的内容。 实践 登录from requests import Session userdata = Session() getJson = userdata.post( "http://mjwgl.ahnu.edu.cn/login/remotelogin", data={ "username": userDict["username"], "password": userDict["password"], "usertype": "stu", "device": "aphone", "sessionid": "" }) username,password和usertype不用说,我校教务系统登陆必须的。
而device和sessionid则是手机端特有的两个。大约是用来标识手机端的吧。 获取成绩页面userdata.post( getJson.json()["homeurl"], data={"requesttype": "cjcx", "sessionid": getJson.json()["sessionid"]}) result = userdata.get( "http://mjwgl.ahnu.edu.cn/query/cjquery/index?action=ok&xkxn=%s&xkx…

配合Nginx使用Uwsgi部署Django

最近实在是没什么事情干。正好又有一台CentOS服务器空着。 下载Nginx,uwsgi 我用的是CentOS和Python3.5,所以如下(安装新版Python参照另一篇) yum install nginx pip3.5 install uwsgi 编写uwsgi,nginx配置 按照官方文档的说法,我写了如下配置,保存在项目根目录下的uwsgi.ini中 [uwsgi] socket = 127.0.0.1:8001 processes = 4 threads = 2 stats = 127.0.0.1:9001 chdir = /root/website/django/book/ wsgi-file = book/wsgi.py safe-pidfile = /root/website/django/book/uwsgi.pid 然后nginx中这样写 server { listen 80; server_name domain; location / { include uwsgi_params; uwsgi_pass 127.0.0.1:8001; } location /static/ { alias /path/to/django/static/; } } uwsgi_pass的值和uwsgi.ini配置中socket的值必须一致。
然后开启nginx,再使用命令uwsgi uwsgi.ini运行uwsgi即可。 多站点配置方法 因为暂时还没这个需求,就懒的去看文档了,http://uwsgi-docs-zh.readthedocs.io/zh_CN/latest/Emperor.html里提到了多站点的配置
以后我需要了,再来把这个坑给填掉。

君子不器

开学之际,无意从知乎看到关于这个讨论,有感而发。
遂作此篇,以激励自己,与诸君共勉。 子曰:“君子不器。” 那么什么是器? 易经有云:形而上者谓之道,形而下者谓之器。 器,是有形之物,是道现于外的表现。
而不器,便是道。道体至虚,无极无量。 君子不器便是说:作为君子,不能囿于一技之长,而当志于道。
从纷扰的万物之间追寻到那个亘古不变的道,天道与本心合一,才能驾驭各种事物,以不变应万变。
道不是坐在某处,天天诵经就能悟的。
要是不了解器,又怎么能把握到那个最本质的道呢?我辈当读万卷书,行万里路,以求道。 子曰:朝闻道,夕死可矣。 今尚未闻道,亦未死,岂可止乎。 ——2017年8月30日于学校宿舍