一、背景
在swagger接口文档中发现删除操作不如django admin管理后台来的方便,不用自己去手动输入id。
但是发现一个AttributeError报错,也就是unique_together 问题。
图1
图2
如上图报错,是个keyerror问题。
看来mongoengine 虽说是orm库,但是并没有很好的对接支持django admin后台管理功能,不能像mysql model 一样可以加入后台方便管理。
二、解决方案
猜测在django 中unique_together是model 下class Meta的属性,但是在Document模型下添加属性并没有解决问题,于是找到/opt/work/venv_py39/lib/python3.9/site-packages/django/contrib/admin/views/main.py 的代码,做了下类型打印发现,有两个options的属性是相差很大的,显然unique_together也在这两个options模块下。
根据报错和源码研究,需要对options增加初始属性,但是我们这里只使用了Document,所以需要了解
doc和options的关系,
from django_mongoengine.forms.document_options import DocumentMetaWrapper
from django_mongoengine.document import DjangoFlavor
from django_mongoengine.fields import ObjectIdField
from mongoengine.base import metaclasses as mtc
from mongoengine import document as me
from functools import partial
from django.utils.functional import cached_property
from django.db.models import UniqueConstraint
mtc.ObjectIdField = partial(
ObjectIdField, editable=False, auto_created=True, blank=True)
class DocMet(DocumentMetaWrapper):
unique_together = []
constraints = []
@cached_property
def total_unique_constraints(self):
"""
Return a list of total unique constraints. Useful for determining set
of fields guaranteed to be unique for all rows.
"""
return [
constraint
for constraint in self.constraints
if (
isinstance(constraint, UniqueConstraint)
and constraint.condition is None
and not constraint.contains_expressions
)
]
def django_meta(meta, *top_bases):
class metaclass(meta):
def __new__(cls, name, bases, attrs):
change_bases = len(bases) == 1 and (
bases[0].__name__ == "temporary_meta")
if change_bases:
new_bases = top_bases
else:
new_bases = ()
for b in bases:
if getattr(b, 'swap_base', False):
new_bases += top_bases
else:
new_bases += (b,)
new_cls = meta.__new__(cls, name, new_bases, attrs)
new_cls._meta = DocMet(new_cls)
return new_cls
return type.__new__(metaclass, 'temporary_meta', (), {})
class Doc(
django_meta(
mtc.TopLevelDocumentMetaclass,
DjangoFlavor,
me.Document,
)
):
swap_base = True
重写了Document,这里简写了类名,避免冲突,也为了简单。
admin.site.register([CweDoc])
然后在admin.py中配置上述程序,既可以看到
改写还有TypeError: ‘metaclass’ object is not iterable 问题,遗留问题属于admin.ModelAdmin 继承使用问题了,也就是要增加展示字段,需要解决剩下的问题了,这里就先不记录了。