1

考虑到我之前的问题,我尝试实现我所需要的。
下面是一个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

User 中不存在任何 mixin 或 User 类自己的属性。如果我以相反的顺序得出:

class User(AuthUser,MyMixin):  

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

虽然替代创建方法有效:

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

但是使用直接从 NodeModelManager 继承的另一个模型 Activity
(使用 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'

这超出了我的理解;) MyManager 在之前的测试中运行良好,我从 NodeModel 的子代而不是从 mixin 派生。

4

1 回答 1

1

这是一个相当复杂的问题,但希望我能给你一个指点。

首先,您需要了解 Django 字段(以及扩展的 neo4django 属性)与定义它们的类协作。这就是为什么它们在 a Model(或者,在 neo4django 中, a NodeModel)上定义时才起作用。没有简单的方法可以使用 Django 模型和字段进行多重继承——我在其他问题中的 mixin 建议允许添加 Python 方法和属性,但不会像父类一样神奇地制作PropertyField播放。object

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

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

大多数元编程都不容易工作,因为 Django 和 neo4django 使用元类。也就是说,我相信你可以用一个聪明的类装饰器或子元类来解决这个问题——但我不确定你应该从理智的角度来看:)

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

于 2013-09-18T18:18:20.397 回答