経験豊富なPython開発者の会話で、Djangoが悪であり、Djangoのアーキテクチャが悪く、苦痛なしに大規模なプロジェクトを作成することは不可能であるというフレーズがしばしばスリップすることは、誰にとっても秘密ではないと思います。中規模のDjangoプロジェクトでさえ、維持と拡張が難しいことがよくあります。なぜこれが起こっているのか、そしてDjangoプロジェクトの何が悪いのかを理解することを提案します。
少し理論
ドキュメントに加えて、他の言語やフレームワークの経験なしにDjangoを学び始めると、チュートリアル、記事、本を読み、ほとんどすべてで次のようなものが表示されます:
Djangoは、Model-View-Controller(MVC)デザインパターンを使用するフレームワークです。
そして、MVCとは何かについての不正確な図と説明の束。なぜそれらが不正確で、何が悪いのか、ここまたはここで見ることができます。
通常、このようなスキームはMVCを次のように記述します。
モデル-データストアへのアクセス
ビューは、ユーザーが対話するためのインターフェースです
コントローラは、モデルとビューを接続するオブジェクトの一種です。
これらの一般的なスキームは、ビジネスロジックを含むアプリケーションを作成する場合にのみ混乱して邪魔になります。
注目に値する2つのことがあります。
, M MVC — , , , . , MVC MV*. MVC M domain model — , . , M MVC , domain model , . , , -.
, Django controller, , Django views — , . , FAQ, , View MVC, , DRF, Controller Django . FAQ, , Django MTV (Model, Template, and View). Web MVC Django , view .
, Django MVC , MVC — - . , .
Django , :
front-end/templates
serializers/forms
views
models
, . Django c DRF. , .
— . :
,
— . , :
serializers/forms
serializers ( serializers forms):
Python
Python Python (, Django dict)
, create update, save() view.
:
class CommentSerializer(serializers.Serializer):
email = serializers.EmailField()
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
def create(self, validated_data):
return Comment.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.email = validated_data.get('email', instance.email)
instance.content = validated_data.get('content', instance.content)
instance.created = validated_data.get('created', instance.created)
instance.save()
return instance
- view:
# .save() will create a new instance.
serializer = CommentSerializer(data=data)
# .save() will update the existing `comment` instance.
serializer = CommentSerializer(comment, data=data)
comment = serializer.save()
, .
ModelSerializer ModelViewSet, CRUD - .
# serializers.py
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = ‘__all__’
# views.py
class OrderViewsSet(viewsets.ModelViewSet):
queryset = Order.objects.all()
serializer_class = OrderSerializer
ModelViewSet ModelSerializer, , .
, , create , - .
# serializers.py
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = []
def create(self, validated_data):
# ,
...
#
instance = super(OrderSerializer, self).create(validated_data)
#
...
#
...
#
...
return instance
# views.py
class OrderViewsSet(viewsets.ModelViewSet):
queryset = Order.objects.all()
serializer_class = OrderSerializer
- , view.
:
:
CRUD
Django DRF CRUD.
:
MVC
- (/) . - .
View MVC Django. , MVC — -.
, - .
- .
— , views. - , , .
- , .
DRF Serializers Django Forms. serializers, . Django Forms DRF Serializers .
/
, .
. , , , -, - ( ).
-. - , CRUD, save , .
ModelSerializer create update ( ModelSerializer read only — ). - , CRUD , DRF .
Views
View Django , , . , , , views -, -. , views Django , - , («, , »; Fat Stupid Ugly Controllers).
- :
# views.py
class OrderViewsSet(viewsets.ModelViewSet):
queryset = Order.objects.all()
serializer_class = OrderSerializer
def perform_create(self, serializer):
# ,
...
#
super(OrderViewsSet, self).perform_create(serializer)
#
...
#
...
#
...
, ModelViewSet , . , perform_create ( super, ModelViewSet). ModelViewSet APIView:
# views.py
class OrderCreateApi(views.APIView):
class InputSerializer(serializers.ModelSerializer):
number = serializers.IntegerField()
...
def post(self, request):
serializer = self.InputSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
# ,
...
#
order = Order.objects.create(**serializer.validated_data)
#
...
#
...
#
...
return Response(status=status.HTTP_201_CREATED)
serializers, views.
# views.py
class OrderViewsSet(viewsets.ModelViewSet):
queryset = Order.objects.all()
serializer_class = OrderSerializer
def get_queryset(self):
queryset = super(OrderViewsSet, self).get_queryset()
queryset = queryset.filter(user=self.request.user)
return queryset
, , CRUD, , , . , .
:
, save serializers. serializers “” “” .
CRUD
Django DRF , CRUD views .
MVC
- .
view view, - . , - , , Celery .
DRF View Django View. views, . Django View DRF View .
views serializers Django + http client .
views , Celery , , views , — , .
view , -.
.
-
-.
- .
serializers — views -.
ModelViewSet , , APIView GenericAPIView.
CRUD, ModelViewSet .
models
Model MVC, , models -.
:
# models.py
class Order(models.Model):
number = serializers.IntegerField()
created = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=16)
def update_status(self, status: str) -> None:
self.status = status
self.save(update_fields=('status',))
...
@classmethod
def create(cls, data...):
instance = cls(...)
# ,
...
#
instance = instance.save()
#
...
# ( )
...
#
...
# views.py
class OrderCreateApi(views.APIView):
class InputSerializer(serializers.ModelSerializer):
number = serializers.IntegerField()
...
def post(self, request):
serializer = self.InputSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
Order.create(**serializer.validated_data)
return Response(status=status.HTTP_201_CREATED)
view serializer . classmethod, . , , - .
, - save(), .
Managers.
# views.py
class OrderListApi(views.APIView):
class OutputSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = ‘__all__’
def get(self, request):
orders = Order.objects.filter(user=request.user)
#
# , Order.objects.filter(user=request.user, is_deleted=False, is_archived=False...)
# Manager
data = self.OutputSerializer(orders, many=True).data
return Response(data)
:
serializers views “” - .
MVC
. View , . MVC.
- , , , views serializers. python . save managers , .
, DRF Views, Django Views, Celery ..
, . Django models ORM — .
- , , . , . , , , , .
CRUD
CRUD, .
MVC . , - .
Services
Django , , Model MVC , .
services Model, - . models property, -, , . :
# models.py
class Order(models.Model):
number = serializers.IntegerField()
created = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=16)
def update_status(self, status: str) -> None:
self.status = status
self.save(update_fields=('status',))
...
# services.py
# DTO
def order_create(name: str, number: int ...) -> bool:
# ,
...
#
order = Order.objects.create(...)
#
...
# ( )
...
#
...
# views.py
class OrderCreateApi(views.APIView):
class InputSerializer(serializers.ModelSerializer):
number = serializers.IntegerField()
...
def post(self, request):
serializer = self.InputSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
services.order_create(**serializer.validated_data)
return Response(status=status.HTTP_201_CREATED)
:
views — , ,
serializers — ,
services — (Service Objects)
managers — ( )
models —
:
# services.py
def order_get_by_user(user: User) -> Iterable[Order]:
return Order.objects.filter(user=user)
# views.py
class OrderListApi(views.APIView):
class OutputSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = ('id', 'number', ...)
def get(self, request):
orders = services.order_get_by_user(user=request.user)
data = self.OutputSerializer(orders, many=True).data
return Response(data)
:
MVC
, - .
Python , .
+ - .
- , .
.
. Django . , Django ORM, .
CRUD
CRUD, .
. , . , .
, , , .
Django, HackSoftware , (services selectors) managers. serializers views . dry-python.
, “” Django . Django DRF , . , , - , . — .