开发者

Django: How can I let the user define semantic relations between objects?

In mediawiki, a user can link to a page by just entering the [[Name of the Page]]. In semantic mediawiki, a user can make a semantic relationship to a page by identifying [[example::Some Page]] as an example page.

I want to be able to do this with django models.

For example, I want a user to be abl开发者_运维知识库e to write a description for a Task object in a workflow app, and put something like "Follow up with [[User.id:43]]."

I'd also love to be able to do the semantic thing.

Finally, I'd like to be able to look at User 43 and see what models link to it.

Is there a django package that will do some or all of this? If not, what is this methodology called generally?


First of all, I'd set up the following to handle link detection and creation:

  1. Create a ModelForm to receive the user's submitted Task. Create a custom validator to operate on the description field of this form. This validator would check that any links entered by the user correspond to the the [[:]] format you've specified.
  2. Override the save method on the Task model. This is a good time to inspect the contents of the description and create links as appropriate.
    • Side note: I would wrap the view function handling this request in a @transaction.commit_on_success decorator so that either the model and all the links get created, or nothing at all gets created.

Now, in the save method, the real action is happening. I would use a regex to pull out all the links and then work through them one by one.

  1. For each link, you need to determine the model linked to. This would be easy with a dictionary of models keyed on their names.
  2. You need to determine if the link has actually identified a valid model instance. If not, either skip this link or raise an exception and eject from the whole process (see above regarding transactions).
  3. You need to create the links. See below.

Django has a standard mechanism for generic foreign keys which you should definitely consider using here. You could create a link class something like:

class Link(models.Model):
    # link to particular task:
    task = models.ForeignKey(Task)

    # these three fields together set up a generic foreign key which 
    # represents the object you're linking to:
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

Your Task model objects would then automatically get an attribute called link_set which would be a list of Link instances.

Creating a link would look something like:

# encountered a description with [[User:43]]
instance = User.objects.get(pk=43)
link = Link.objects.create(task=my_task_object, content_object=instance)

By giving Link's content_object attribute an instance of another model, its content_type and object_id fields are automatically filled in for you, and your link will resolve back to that specified instance.

Hope this is helpful. Ask for more detail if you need it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜