今年10月TIOBE榜Python首次排名第一, 而据“香农计划”(“Shannon Plan”) Python 在明年(3.11 )将提速1倍,总目标是4年提速5倍,所以入坑 Python 的前景还是很好的。龟叔一把年纪了还这么拼,我们没有理由躺平。 Python在编程语言中的入门门槛较低,应用也非常广泛,这得益于其涉及领域众多的安装包,使用某些安装包甚至几行代码就可以实现一个复杂的应用。
本文所讲解的 Django 是 Python 的一个著名 Web 框架, 大家所熟知的YouTube、Instagram、Dropbox、Spotify 等都曾经或正在使用 Django,国内很多大厂也都在使用 Django。当然,这里所说的使用大多都不是直接面向 C 端的大型应用,这与 Python 以及 Django 的特性相关。Python 虽然很优秀,但作为动态语言其性能总体而言是不及C++、JAVA等动态语言,所以不太适合构建大型高并发应用。这是就通常意义而言,大佬随意,这么说是因为在转为Go语言之前, 有很多大型互联网使用的就是 Python(比如知乎),而有些依然使用的是 Python(如豆瓣)。不论如何, Python具有丰富的内置和第三方库以及明显的开发效率上的优势,因而像 Django 这种框架对企业内部应用及快速验证市场、前期流量适中的相关场景会非常适用。
注:我的理解入门门槛低不代表容易, Python的简单在于其语法,而复杂在于其灵活性,这就使得其在用于大型项目时维护性变低,因为“千人千面”,不像 Java 的 Spring 和 SpringBoot 套路那么一致。
Django 本身并不是一个轻量级框架,它自带后台,实现了权限控制和后台管理的核心功能,对于很多用户甚至无需进行二次开发即可直接使用。当然默认的主题远称不上美观,我们可以安装grappelli、simpleui等免费主题,市场上也有一些付费主题。
Django 相关宝藏资源:https://github.com/jazzband
Django 的功能非常多,配合Django REST framework 还可用于开发 API。本文想要讲解的多数据库相关的实践。企业中可能存在一些老项目需要快速创建后台进行管理,或是希望将多个项目(数据库)放到同一个后台里进行管理,这时如果使用 Django 就要求能对多数据源同时进行管理。Django 本身就支持这一点。
文档地址:https://docs.djangoproject.com/en/3.2/topics/db/multi-db/
多数据库配置示例(本示例使用的是 Django 3.2版本,4.0中同样适用):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
DATABASES = { 'default': { 'NAME': 'app_data', 'ENGINE': 'django.db.backends.postgresql', 'USER': 'postgres_user', 'PASSWORD': 's3krit' }, 'users': { 'NAME': 'user_data', 'ENGINE': 'django.db.backends.mysql', 'USER': 'mysql_user', 'PASSWORD': 'priv4te' } } |
自动生成模型:
1 |
python manage.py inspectdb --database user_data > models.py |
这时可以使用 django-admin startapp xxxx
来创建应用并将 models.py 放入应用内(需要根据具体情况进行内容的微调)。接下来需要进行路由配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class DatabaseRouter: route_app_labels = {'user_data'} def db_for_read(self, model, **hints): if model._meta.app_label in self.route_app_labels: return 'user_data' return 'default' def db_for_write(self, model, **hints): if model._meta.app_label in self.route_app_labels: return 'user_data' return 'default' def allow_relation(self, obj1, obj2, **hints): return None def allow_migrate(self, db, app_label, model_name=None, **hints): if app_label in self.route_app_labels: return False return True |
将路由配置注册到配置文件中,如:
1 |
DATABASE_ROUTERS = ['settings.router.DatabaseRouter'] |
将模型注册至 admin.py,此时打开后台就会出现模型的内容,但仅限管理员查看,无法进行权限控制,这是因为外部导入的数据库一般我们是不能做 migrate 操作的,且多对多的支持当前受限。那这样不就丧失子统一管理后台的作用了吗?如何像默认数据库一样进行权限控制呢?
查看源码可以看到通过has_add_permission等方法(add, change, delete, view)实现的权限控制。因为我们不对默认库以外的表格进行迁移操作,因此在模型的 Meta 类加自定义权限是无法生效的,我是通过以下方式进行权限添加的(注:在此之的代码都是有官方背书的,下面这种是 Alan 实现的,仅供参考,如有更优雅的实现欢迎在评论区中与我交流。使用 f 进行格式化的写法要求 Python 在3.6及以上):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# utils/permissions.py from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType def create_permissions(model): content_type = ContentType.objects.get_for_model(model) model_name = model._meta.model_name curd = ['add', 'change', 'delete', 'view'] for op in curd: Permission.objects.get_or_create( codename=f'{op}_{model_name}', name=f'Can {op} {model_name}', content_type=content_type, ) |
然后在admin.py的文件中进行调用,
1 2 |
from utils.permissions import create_permissions create_permissions(ModelName) |
这样就可以像默认库中一样进行增删改查的控制了。
其它
通常不推荐在数据库中建立外键,那如何使用 Django 自带的强大外键功能呢?答案是逻辑外键,Django实现逻辑外键的方式是在 ForeignKey
字段中使用属性db_contraint=False
,此外还应注意对于外键字段 Django 会默认添加一个_id
的后缀,这可能导致找不到字段的错误,此时可使用db_column
属性指定字段名。
外键过度使用会存在一个坑,即默认在编辑页等处 Django 会去加载关联数据表的所有数据,这时打开页面会非常慢。一种解决方案是在admin.py 配置中添加autocomplete_fields
,并在外键对应表中添加 search_fields
进行优化:
1 2 3 4 5 6 |
class XxxAdmin(admin.ModelAdmin): search_fields = ('xxx', ) class XxxAdmin(admin.ModelAdmin): autocomplete_fields = ('xxx_id',) |
常见问题整理
- Django 2 & 3常见技术问题
- ERROR: Could not build wheels for cryptography which use PEP 517 and cannot be installed directly
1python3 -m pip install --upgrade pip