Django 多表继承(Multi-table Inheritance)子类属性的访问

最近在开发一套活动预约系统,其中电影类活动牵涉到选座购票,而其他类型的活动则一般只需展示或提供记名预约即可。根据具体场景,具体关系设计如下:

多表继承结构
多表继承结构

对于 B 基于 A 的多表继承,Django ORM 的处理方式是:生成表 a 与表 b,并在表 b 中自动添加 OneToOneField 列 a.ptr。在上图中,对于 event.Event 和 movieticket.MovieShowtime 两个多表继承关系的模型,在 shell 中是这样访问的:

>>> e = Event.objects.get(pk=1)
>>> ms = e.movieshowtime

在父类中,我们定义了 event_type 的 choices 可选值,

class Event(models.Model):
    EVENT_TYPE_MOVIE = 'M'
    EVENT_TYPE_WORKSHOP = 'W'
    EVENT_TYPE_TALK = 'T'
    EVENT_TYPES = (
        (EVENT_TYPE_MOVIE, '电影放映 / Movie Screening'),
        (EVENT_TYPE_WORKSHOP, '工作坊 / Workshop'),
        (EVENT_TYPE_TALK, '讲座 / Talk'),
    )

并在子类中定义表示活动种类的 event_type 这一 CharField。

class MovieShowtime(Event):
    event_type = models.CharField(
        max_length=2,
        choices=Event.EVENT_TYPES,
        default=Event.EVENT_TYPE_MOVIE,
        editable=False)

若不这样做,则我们可能需要覆盖重写改变初始化模型类实例的方法来默认记录类型信息。(Otherwise, we would need to override create method of model instances to have type info recorded by default.)更优雅的方式请见文末。

我们约定,所有子类都有 event_type 这一属性,为了让后续操作可访问该域,我们可以在父类增添一个方法。

class Event(models.Model):
    pass

    def event_type(self):
        for subcls in ('movieshowtime', 'workshop', 'talk'):
            try:
                subcls_instance = getattr(self, subcls)
                return {
                    'abbr': subcls_instance.event_type,
                    'full': subcls_instance.get_event_type_display(),
                }
            except:
                pass
        return None

当然,我们也可以使用更优雅的方式(https://www.djangosnippets.org/snippets/1034/)来实现这一效果。

MATLAB 设置 Windows 下 MEX 编译环境

MATLAB 可以调用由 C/C++ 或 FORTRAN 语言文件编译生成的二进制 MATLAB 可执行文件(MEX, MATLAB executable)。与普通的 C/C++/FORTRAN 不同,MEX 源文件需要额外设置 gateway 函数来对接 MATLAB。Mathworks 也提供了相关的头文件,提供了一些数据类型的定义,以及对数据大小的预处理等各类功能。

这一功能在提升某些运算方面具有极大的潜力。对于同一架构、同一操作系统、同一 MATLAB 版本而言,编译完成后的 MEX 文件是通用的。但反之,架构、操作系统或 MATLAB 版本中的任一因素均可导致 MEX 文件不可通用。所以,对于开源软件作者而言,还是维护源代码比维护二进制发行版更为现实。但这也要求用户掌握对 MEX 编译环境的配置。

MEX 相关功能在三类主流操作系统上都有所支持,但各个系统上 MATLAB 所支持的编译器种类不尽相同。Windows 上受 MATLAB 支持的编译器种类是最多的,其中包括由 Intel Parallel Studio 自带的大名鼎鼎的 Intel C++ Compiler。

在大多数情况下,编译器安装好后,通过简单执行 mex -setup language_name ,MATLAB 就能通过环境变量或注册表值找到所需的编译器文件。但是,有可能出现以下几种情况:

  • 环境变量设置不正确
  • 注册表键值设置不正确
  • MATLAB 版本号较小,无法支持当前新版本的编译器(如 R2017a 无法支持 Intel Parallel Studio XE 2018,默认只能支持 2017 及以下版本)

就个人经历而言,曾把 Visual Studio 2017 从 SSD 的系统盘中卸载后重装到 HDD 中去过一次,但重装后对应的注册表键值却没有被安装程序重新修改。对于这种情况,在设置 mex 时开启 verbose 模式就可以看得很清楚到底哪里缺东西或是搞错了。

>> mex -setup C++ -v
Verbose mode is on.
... Looking for compiler 'Intel C++ Composer XE 2013 with Microsoft SDK 7.1' ...
... Looking for environment variable 'ICPP_COMPILER14' ...No.
... Looking for environment variable 'ICPP_COMPILER13' ...No.

...

... Looking for registry setting 'HKLM\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VS7' 15.0 ...Yes ('Some_Wrong_Path').
... Executing command 'set "vcroot=Some_Wrong_Path"&for /f "delims= " %a in ('type "Some_Wrong_Path\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "Some_Wrong_Path\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%' ...Yes ('Some_Wrong_Path').

而对于无法兼容最新版编译器的情况,在 MATLAB 或是对应编译器的接口没有 break changes 的情况下,一般是能够两边调通的。要做的就是告诉 MATLAB,要去找哪些依赖文件,能运行怎样的编译命令。

GitHub:rymut/matlab-mex-intel18 这个仓库中(MATLAB Central File Exchange 镜像),我们就能找到让 R2017a 支持 2018 版英特尔 ICC 的 XML 配置文件。而在 R2017b 中,已经内置了对应的 XML 配置文件。如果下载到对应路径后,再运行开启 verbose 模式的 mex setup 命令,就能看到与 XML 文件中 <locationFinder> 下相对应的搜寻过程了。

看完本文,可以试试运行  cd([matlabroot '\bin\win64\mexopts']) 进一步探索有哪些可以自由定制的选项。

编译原理课程专题大纲

为了在将来更好地完成领域特定语言(DSL)的设计,2018年春学期,继2017年春学期对编译原理持续仅1个月的旁听经历后,我选择在今年继续完整旁听编译原理(CS131)课程。

在上海科技大学信息学院,CS131是一门被归入计算机科学与技术专业方向的面向本科生的4学分的专业选修课。每周共设2次时长各90分钟的讲座课,以及1次讨论课。设两类作业,编程作业(PA)与书面作业(WA)。

  • 概论
    • 上下文无关语法(Context-Free Grammar)
    • 需要研究的基本问题
  • 词法分析(Lexical Analysis)
    • 词法分析的总体流程
    • 基于双 buffer 的 token 扫读(Scanning)
    • 语言(Language)的严格定义及基本运算
    • 正则表达式(Regular Expression)的定义与基本定律
    • Token 的定义、识别,与基于状态转移图(Transition Diagram)的表示
    • 确定性(Deterministic)与非确定性有限自动状态机(Finite Automaton)的定义,与基于状态转移图/表的表示
    • DFA 与 NFA 的代码实现
    • NFA 向 DFA 的转换,与两者的特点比较
    • 正则表达式向 NFA 的转换
    • NFA 间的连接组合
    • 正则表达式向 DFA 的直接转换
    • DFA 的最简化
    • 使用 Flex 与 Lex
    • (考察大纲外)所有语言运算的对应 DFA 运算

IIS 配置强制 HTTPS 重定向

在 IIS 中配置 HTTPS 重定向的资料在中文网站上不是很多,在此给出 web.config 的一个示例。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <defaultDocument>
      <!-- ... -->
    </defaultDocument>
    <rewrite>
      <rules>
        <rule name="ENFORCE_HTTPS" enabled="true" stopProcessing="true">
          <match url="(.*)" />
          <conditions logicalGrouping="MatchAny">
            <add input="{HTTPS}" pattern="OFF" />
            <add input="{SERVER_PORT}" pattern="80" />
          </conditions>
          <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

在 IIS 中,rule 的 stopProcessing 这一属性表示的是:如果满足这一规则,则处理完当前规则后不处理其他规则。

在 IIS 上部署 HTTPS 也并不是特别麻烦,使用 Certify 能很方便地在图形化界面下部署基于 Let’s Encrypt 的免费 SSL 证书。

技术自留地

从 2017 年起,我开始接触越来越多的实际技术应用,着手越来越多的实际编程工作。与之前完成作业为主不同,实际的软件开发过程中,会遇到以下种种

  • 输入输出规范都要自己进行约定
  • 所需完成的功能复杂,接口繁多,业务的重要性高于算法效率
  • 一个人无法高效完成所有环节,需要拆分任务
  • 以前很少接触的 GUI、DSL 开始显得不可或缺
  • ……

各类之前未曾遇到过的问题。在这里,技术积累的点滴将会被记录下来。由于囊中羞涩,本博客暂时托管在阿里云 1 元/年的万网虚拟主机上,暂时无计划通过 CDN 配置 https 访问。在初期,本博客看起来会比较偏软件开发/计算机科学,但随着个人学习计划的推进,会逐渐增加数学类内容,以及电路类、信号类等传统 EE 方向的内容。