Django源码解析|Migrations文件的生成

栏目: Python · 发布时间: 5年前

内容简介:这其实是Django源码解析视频中的一个细节。当我们创建好一个Model之后,需要执行比如Mode定义如下:

背景

这其实是Django源码解析视频中的一个细节。

当我们创建好一个Model之后,需要执行 makemigrations 操作,生成对应的Migrations文件。那么问题来了,Django是如何把Model生成对应的Migrations文件的呢?

比如Mode定义如下:

from django.db import models


class Post(models.Model):
    title = models.CharField(max_length=100)
    created_time = models.DateTimeField(auto_now_add=True)

生成的Migrations如下:

from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Post',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('title', models.CharField(max_length=100)),
                ('created_time', models.DateTimeField(auto_now_add=True)),
            ],
        ),
    ]

其实我们关心的是operations里面的内容。

需要注意的是,这个代码也是文本,是由Django生成的。

代码实现

视频里虽然讲解了,不过最好大家还是能够自己实现一个简单的逻辑,这样才能掌握更多技巧和库的用法。话不多说,我们直接上代码,实现一个小的Demo。

import inspect


class CreateModel:
    def __init__(self, name, age=20):
        self.name = name
        self.age = age

    def deconstruct(self):
        kwargs = {
            'name': self.name,
            'age': self.age,
        }
        return (
            self.__class__.__qualname__,
            [self.name],
            kwargs
        )


def get_func_args(func):
    # django/utils/inspect.py
    sig = inspect.signature(func)
    return [
        arg_name for arg_name, param in sig.parameters.items()
        if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
    ]


def rewrite(foo):
    name, args, kwargs = foo.deconstruct()
    operation_args = get_func_args(foo.__init__)
    buf = []
    buf.append(f'{name}(')
    for i, arg in enumerate(args):
        arg_value = arg
        arg_name = operation_args[i]
        buf.append(f'"{arg_value}",')

    i = len(args)
    for arg_name in operation_args[i:]:
        if arg_name in kwargs:
            arg_value = kwargs[arg_name]
            buf.append(f'{arg_name}={arg_value},')
    buf.append(')')
    print('\n'.join(buf))


if __name__ == '__main__':
    # 把下面的定义转写到文件中
    foo = CreateModel(
        'the5fire',
        age=30
    )

    rewrite(foo)

上面代码的核心是通过inspect对拿到的类实例(也就是: foo )进行解析,整体逻辑不难理解。

很多人觉得这个定义已然存在了,为什么还要通过代码来写一遍。关键问题在于, 我们需要站在机器的视角来看问题 。机器拿到的只是一个对象,它需要做的是把对象转换为文本。

- from the5fire.com

----EOF-----

微信公众号:Python程序员杂谈

Django源码解析|Migrations文件的生成

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Head First Rails

Head First Rails

David Griffiths / O'Reilly Media / 2008-12-30 / USD 49.99

Figure its about time that you hop on the Ruby on Rails bandwagon? You've heard that it'll increase your productivity exponentially, and allow you to created full fledged web applications with minimal......一起来看看 《Head First Rails》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器