良好的Django设计规范,可在DRY之后稍后添加REST API

时间:2019-02-16 09:30:46

标签: django rest dry

我正在使用纯Django启动Web应用程序。但是,将来可能会需要REST API。如果发生这种情况,最明显的选择是Django REST框架。

“老式”和REST部件共享模型,但是视图略有不同(例如,权限定义),并且用序列化程序替换了表单。最明显的方式就是重复几次应用程序逻辑,从而导致无法遵循DRY原理,因此代码变得难以维护。

我有一个主意,就是将所有逻辑写入模型(因为它们是共享的),但是在这种情况下,将不会使用权限混合,通用视图和代码也不是最好的。

现在,我的想法耗尽了。最佳做法是什么?

1 个答案:

答案 0 :(得分:3)

由于您不确定API的未来要求,我会尽量简化事情,并且猜测可能会带来额外的复杂性,当要求明确后,甚至可能不需要。

Django表单和Rest Framework序列化程序都已为您提供了一种声明性方法,该方法抽象了基本内容所需的样板代码,而这些代码通常仍占您代码的大部分。 例如,您的Django表单之一可能如下所示:

class ArticleForm(ModelForm):
    class Meta:
        model = Article
        fields = ['title', 'content']

将来,DRS序列化器将是:

class ArticleSerializer(ModelSerializer):
    class Meta:
        model = Article
        fields = ['title', 'content']

如您所见,如果您坚持使用ModelForm和ModelSerializer,则不会有太多重复。您也可以只将字段列表存储在变量中,然后重复使用。

对于更多自定义内容,您可以从将逻辑共享为简单功能开始,例如:

def save_article_with_author(article_data, author_data):
    # custom data manipulation before saving, consider that article_data will be a dictionary either if it comes from deserialized JSON (api) or POST data
    # send email, whatever

此功能可以在表单和序列化程序之间共享。

对于与数据提取有关的所有内容,我会尽量使用模型管理器,定义可继续使用的自定义查询集,例如用于表单和序列化器的选项。

我倾向于避免编写任何不直接在模型类中读取或写入数据的逻辑。我认为这将业务逻辑与数据层过多地耦合在一起。举例来说,我从不想将任何身份验证/权限检查写入模型的save()方法中,因为这会使不同的层次紧密地结合在一起。

作为一个经验法则,可以想象一下这种情况:您添加了说说权限检查或在创建用户时覆盖了Article模型的save()方法时发送电子邮件的逻辑。 然后,稍后要求您编写一个简单的manage命令,该命令从电子表格中批量导入用户。此时,您在save()方法中所做的事情确实会受到影响,因为您可以通过模型自由访问数据,而不必担心权限,电子邮件等所有问题。

关于视图层并假设您需要实现一些共享的身份验证/权限检查,并且您不想拥有单独的视图,则可以使用以下方法: https://www.django-rest-framework.org/topics/html-and-forms/

  

Blockquote   REST框架适用于返回API样式响应和常规HTML页面。此外,序列化程序可以用作HTML表单并在模板中呈现。

以下是有关如何根据请求内容类型从HTML动态转换为JSON的一些准则:

https://www.django-rest-framework.org/api-guide/renderers/#advanced-renderer-usage

在您的情况下,这似乎是个不错的选择,在您全神贯注看您是否对所要做的事情没有太多限制之前,我会写下一个快速的概念证明。