栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

在Django中创建动态模型字段

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在Django中创建动态模型字段

有几种方法:

  • 键/值模型(简单,良好的支持)
  • TextField中的JSON数据(简单,灵活,无法轻松搜索/索引)
  • 动态模型定义(不是那么容易,很多隐藏的问题)
    听起来好像你想要最后一个,但是我不确定这对你来说是最好的。Django非常易于更改/更新,如果系统管理员需要其他字段,只需为其添加字段并使用向南迁移即可。我不喜欢通用键/值数据库架构,像Django这样的强大框架的全部要点是,你可以轻松编写和重写自定义架构,而无需求助于通用方法。

如果必须允许站点用户/管理员直接定义其数据,我相信其他人将向你展示如何执行上述前两种方法。第三种方法是你要的,更疯狂的是,我将向你展示如何做。我不建议在几乎所有情况下都使用它,但有时它是合适的。

动态模型

一旦知道要做什么,这就相对简单了。你需要:

  • 1或2个模型来存储字段的名称和类型
  • (可选)为你的(子类化的)动态模型定义通用功能的抽象模型
  • 在需要时构建(或重建)动态模型的功能
  • 添加/删除/重命名字段时用于构建或更新数据库表的代码

1.存储模型定义

这取决于你。我想你将拥有一个模型,

CustomCarModel
CustomField
让用户/管理员定义和存储所需字段的名称和类型。你不必直接镜像Django字段,可以创建自己的类型,以便用户更好地理解。

forms.ModelForm
与内联表单集一起使用可让用户构建其自定义类。

2.抽象模型

同样,这很简单,只需为所有动态模型创建具有公共字段/方法的基本模型即可。使该模型抽象。

3.建立动态模型

定义一个函数,该函数接收所需的信息(可能是#1类的实例)并生成一个模型类。这是一个基本示例:

from django.db.models.loading import cachefrom django.db import modelsdef get_custom_car_model(car_model_definition):  """ Create a custom (dynamic) model class based on the given definition.  """  # What's the name of your app?  _app_label = 'myapp'  # you need to come up with a unique table name  _db_table = 'dynamic_car_%d' % car_model_definition.pk  # you need to come up with a unique model name (used in model caching)  _model_name = "DynamicCar%d" % car_model_definition.pk  # Remove any exist model definition from Django's cache  try:    del cache.app_models[_app_label][_model_name.lower()]  except KeyError:    pass  # We'll build the class attributes here  attrs = {}  # Store a link to the definition for convenience  attrs['car_model_definition'] = car_model_definition  # Create the relevant meta information  class meta:      app_label = _app_label      db_table = _db_table      managed = False      verbose_name = 'Dynamic Car %s' % car_model_definition      verbose_name_plural = 'Dynamic Cars for %s' % car_model_definition      ordering = ('my_field',)  attrs['__module__'] = 'path.to.your.apps.module'  attrs['meta'] = meta  # All of that was just getting the class ready, here is the magic  # Build your model by adding django database Field subclasses to the attrs dict  # What this looks like depends on how you store the users's definitions  # For now, I'll just make them all CharFields  for field in car_model_definition.fields.all():    attrs[field.name] = models.CharField(max_length=50, db_index=True)  # Create the new model class  model_class = type(_model_name, (CustomCarModelbase,), attrs)  return model_class

4.更新数据库表的代码

上面的代码将为你生成一个动态模型,但不会创建数据库表。我建议使用South进行表操作。这里有几个功能,你可以将它们连接到保存前/保存后信号:

import loggingfrom south.db import dbfrom django.db import connectiondef create_db_table(model_class):  """ Takes a Django model class and create a database table, if necessary.  """  table_name = model_class._meta.db_table  if (connection.introspection.table_name_converter(table_name)         not in connection.introspection.table_names()):    fields = [(f.name, f) for f in model_class._meta.fields]    db.create_table(table_name, fields)    logging.debug("Creating table '%s'" % table_name)def add_necessary_db_columns(model_class):  """ Creates new table or relevant columns as necessary based on the model_class.    No columns or data are renamed or removed.    XXX: May need tweaking if db_column != field.name  """  # Create table if missing  create_db_table(model_class)  # Add field columns if missing  table_name = model_class._meta.db_table  fields = [(f.column, f) for f in model_class._meta.fields]  db_column_names = [row[0] for row in connection.introspection.get_table_description(connection.cursor(), table_name)]  for column_name, field in fields:    if column_name not in db_column_names:      logging.debug("Adding field '%s' to table '%s'" % (column_name, table_name))      db.add_column(table_name, column_name, field)

在那里,你拥有了!你可以调用get_custom_car_model()传递Django模型,该模型可用于执行常规django查询:

CarModel = get_custom_car_model(my_definition)CarModel.objects.all()

问题

  • 在运行创建它们的代码之前,你的模型对Django都是隐藏的。但是get_custom_car_model,你可以在
    class_prepared
    定义模型的信号中为定义的每个实例运行。
  • ForeignKeys/ ManyToManyFields
    可能不起作用(我没有尝试过)
  • 你将要使用Django的模型缓存,这样就不必每次都要使用查询来运行和创建模型。为了简单起见,我在上面省略了此内容
  • 你可以将动态模型添加到admin中,但是你还需要动态创建admin类,并使用信号适当地注册/重新注册/注销。

总结

如果你对增加的复杂性和问题感到满意,请尽情享受!它运行着,由于Django和Python的灵活性,它可以按预期运行。你可以将模型输入Django

ModelForm
,让用户编辑其实例,并直接使用数据库的字段执行查询。如果上面没有什么你不了解的地方,最好不要采用这种方法(我故意不解释某些概念对初学者的意义)。把事情简单化!

我确实不认为有很多人需要这样做,但是我自己使用了它,因为我们表中有很多数据,并且确实非常需要让用户自定义列,而这些列很少更改。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/375922.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号