neo4django mixin继承问题

时间:2013-09-18 17:09:53

标签: authentication inheritance multiple-inheritance neo4django

考虑my previous question,我尝试实现我需要的东西 以下是django app models.py。

的内容
from neo4django.db import models
from neo4django.auth.models import User as AuthUser

class MyManager(models.manager.NodeModelManager):
    def filterLocation(self,**kwargs):
        qs = self.get_query_set()
        if 'dist' in kwargs:
            qs = qs.filter(_where_dist=kwargs['dist'])
        elif 'prov' in kwargs:
            qs = qs.filter(_where_prov=kwargs['prov'])
        elif 'reg' in kwargs:
            qs = qs.filter(_where_reg=kwargs['reg'])
        return qs


class MyMixin(object):
    _test = models.BooleanProperty(default=True)
    _where_dist = models.StringProperty(indexed=True)
    _where_prov = models.StringProperty(indexed=True)
    _where_reg = models.StringProperty(indexed=True)

    search = MyManager()

    class Meta:
        abstract = True

class Activity(MyMixin,models.NodeModel):
    name = models.StringProperty()

class User(MyMixin,AuthUser):
    info = models.StringProperty()

我有很多问题。第一个是MyMixin属性的非继承:

>>> joe=User.objects.create(username='joe') # OK!
>>> joe
<User: joe>
>>> bill=User.objects.create(username='bill',_test=True)

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/home/tonjo/venv/tuned/local/lib/python2.7/site-packages/neo4django/db/models/manager.py", line 43, in create
    return self.get_query_set().create(**kwargs)
  File "/home/tonjo/venv/tuned/local/lib/python2.7/site-packages/neo4django/db/models/query.py", line 1296, in create
    return super(NodeQuerySet, self).create(**kwargs)
  File "/home/tonjo/venv/tuned/local/lib/python2.7/site-packages/django/db/models/query.py", line 375, in create
    obj = self.model(**kwargs)
  File "/home/tonjo/venv/tuned/local/lib/python2.7/site-packages/neo4django/db/models/base.py", line 141, in __init__
    super(NodeModel, self).__init__(*args, **kwargs)
  File "/home/tonjo/venv/tuned/local/lib/python2.7/site-packages/django/db/models/base.py", line 367, in __init__
    raise TypeError("'%s' is an invalid keyword argument for this function" % kwargs.keys()[0])
TypeError: '_test' is an invalid keyword argument for this function

但是创建也无法设置用户自己的属性!

>>> k=User.objects.create(username='kevin',info='The Best')

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/home/tonjo/venv/tuned/local/lib/python2.7/site-packages/neo4django/db/models/manager.py", line 43, in create
    return self.get_query_set().create(**kwargs)
  File "/home/tonjo/venv/tuned/local/lib/python2.7/site-packages/neo4django/db/models/query.py", line 1296, in create
    return super(NodeQuerySet, self).create(**kwargs)
  File "/home/tonjo/venv/tuned/local/lib/python2.7/site-packages/django/db/models/query.py", line 375, in create
    obj = self.model(**kwargs)
  File "/home/tonjo/venv/tuned/local/lib/python2.7/site-packages/neo4django/db/models/base.py", line 141, in __init__
    super(NodeModel, self).__init__(*args, **kwargs)
  File "/home/tonjo/venv/tuned/local/lib/python2.7/site-packages/django/db/models/base.py", line 367, in __init__
    raise TypeError("'%s' is an invalid keyword argument for this function" % kwargs.keys()[0])
TypeError: 'info' is an invalid keyword argument for this function

用户中不存在mixin或User类拥有的属性。 如果我以相反的顺序派生:

class User(AuthUser,MyMixin):  

他们在场,但我认为这不是一个好习惯, 不应该核心模型走向右边吗? 无论如何,正如我们在下面看到的,Activity没有这个问题,
就像AuthUser删除了所有属性(预期的行为?)。

虽然替代创建方法有效:

>>> k=User(username='kevin',info='The Best')
>>> k.save()
>>> k
<User: kevin>

但是使用其他Model,Activity,它直接从NodeModelManager继承 (对于User,我们有一个中间父级AuthUser),事情就更好了:

>>> a=Activity.objects.create(name="AA")
>>> a
<Activity: Activity object>

使用简单的NodeModel继承进行的几项测试都没问题, 多重继承和mixins会出现问题。

另一个问题,我的NodeModelManager:

>>> User.search.filterLocation(dist="b")

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/home/tonjo/prj/tuned_prj/tuned_django/myapp/models.py", line 6, in filterLocation
    qs = self.get_query_set()
  File "/home/tonjo/venv/tuned/local/lib/python2.7/site-packages/neo4django/db/models/manager.py", line 31, in get_query_
set
    return NodeQuerySet(self.model)
  File "/home/tonjo/venv/tuned/local/lib/python2.7/site-packages/neo4django/db/models/query.py", line 1222, in __init__
    self._app_label = model._meta.app_label
AttributeError: 'NoneType' object has no attribute '_meta'

这个超出了我的理解;) 在我从NodeModel的孩子派生的先前测试中,MyManager运行良好, 不是来自混合物。

1 个答案:

答案 0 :(得分:1)

这是一个非常复杂的问题,但希望我可以给你一个指针。

首先,您需要了解Django字段(以及扩展名neo4django属性)与它们所定义的类合作。这就是为什么他们Model上定义时(或者在neo4django中,NodeModel)。使用Django模型和字段没有简单的方法来进行多重继承 - 我的your other question的mixin建议允许添加Python方法和属性,但不会神奇地使PropertyField很好地发挥作用object作为父类。

如果你真的想避免在这种情况下重复属性定义,你可以选择几个。

一个是使用共享超类 - 但在这种情况下,你不能,因为你需要从你的一个类继承neo4django.auth.models.User。当neo4django支持Django 1.5+时,这个特殊要求将允许可交换的用户模型。

由于Django和neo4django使用了元类,因此大多数元编程都不会起作用。也就是说,我相信你可以通过一个聪明的班级装饰师或儿童元类来解决这个问题 - 但我不确定你是否应该从理智的角度出发:)

让我知道它是怎么回事 - 也许我错过了一种更简单的方法。