Saya pikir itu bukan rahasia bagi siapa pun yang dalam percakapan dengan pengembang Python yang berpengalaman, dan tidak hanya, frase sering tergelincir bahwa Django jahat, bahwa Django memiliki arsitektur yang buruk dan tidak mungkin untuk menulis proyek besar di atasnya tanpa rasa sakit. Bahkan proyek medium Django seringkali sulit untuk dipertahankan dan diperluas. Saya mengusulkan untuk mencari tahu mengapa ini terjadi dan apa yang salah dengan proyek Django.
Sedikit teori
Ketika kami mulai mempelajari Django tanpa pengalaman dari bahasa dan kerangka kerja lain, selain dokumentasi, kami membaca tutorial, artikel, buku, dan hampir semuanya kami melihat sesuatu seperti ini:
Django adalah kerangka kerja yang menggunakan pola desain Model-View-Controller (MVC).
Dan kemudian sekelompok diagram dan penjelasan yang tidak akurat tentang apa itu MVC. Mengapa mereka tidak akurat dan apa yang salah dengan mereka, Anda bisa lihat di sini atau di sini .
Biasanya, skema seperti itu menggambarkan MVC dengan cara ini:
Model - akses ke penyimpanan data
View adalah antarmuka yang digunakan pengguna untuk berinteraksi
Kontroler adalah sejenis objek penghubung antara model dan tampilan.
Skema umum ini hanya membingungkan dan menghalangi saat Anda ingin menulis aplikasi yang berisi logika bisnis.
Ada dua hal yang perlu diperhatikan.
, 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 , . , , - , . β .