API的紧耦合类的最佳实践

时间:2012-03-22 08:47:30

标签: django api tastypie

我目前正在使用django和tastypie。我需要为问题和答案实现api。我分别创建了与问答模型相关的以下资源:

class QuestionResource(ModelResource):
    answers  = fields.ToManyField("material.resources.AnswerResource",
                                "answer_set",blank=True,full=True)

class AnswerResource(ModelResource):
    question = fields.ToOneField(QuestionResource,'question')

在我看来,答案属于问题,用户不应该在没有相应答案的情况下创建问题。在我之前的迭代中,我使用了django formset来包含问题和相关答案的信息。对于这种情况,对于tastypie来说,并没有一个简洁的开箱即用解决方案(据我所知)。

我是否应该只允许对问题资源的请求然后更新相应的答案,或者我是否应该丢失2个资源,这意味着用户必须确保在创建问题后提交相关答案。前者在我看来原则上更好,因为后者可以提出问题而没有答案,原则上绝不应该这样。

1 个答案:

答案 0 :(得分:1)

好吧,我认为在RESTful API中一次创建两个不同的资源是不可能的(因为你不能一次POST到两个不同的URL)。因此,为了保持API清洁和RESTful,我宁愿建议您遵循后一种方法并允许单独创建它们(除非您将它们组合成一个资源)。这可能不像看起来那么糟糕。

我理解这可能会产生没有答案的问题(我假设问题是应该出现的第一个实体,然后应该回答这个问题)。但是,在您的应用程序中,您可以通过不对问题进行操作来解决此问题,除非应答(例如,不要在任何地方显示)。

您甚至可以更进一步定义一个自定义管理器类,默认情况下会过滤掉那些未答复的问题,如下所示:

# assumed that `answers` is related_name in ForeignKey from Answer to Question
class Question( models.Model )
    objects = AnsweredQuestionsManager()
    all_questions = models.Manager()

    @property
    def is_answered( self ):
        return self.answers.count() > 0

class AnsweredQuestionsManager( models.Manager ):
    def get_query_set( self ):            
        return super( AnsweredQuestionManager, self )\
            .get_query_set().annotate(
                num_answers = Count( 'answers' ) ).filter( num_answers__gt = 0 )

然后Question.objects.all()只返回带答案的问题,而Question.all_questions.all()也会包含未回答的问题。

为了使您的数据库保持相对清洁,您可以定期(例如使用Cron)摆脱旧的,未回答的问题。

我希望这会让你更倾向于分离:)