Architektur in Django-Projekten - wie man ĂŒberlebt

Ich denke, es ist fĂŒr niemanden ein Geheimnis, dass in GesprĂ€chen mit erfahrenen Python-Entwicklern und nicht nur oft SĂ€tze verrutschen, dass Django böse ist, dass Django eine schlechte Architektur hat und es unmöglich ist, ein großes Projekt ohne Schmerzen darauf zu schreiben. Selbst ein mittleres Django-Projekt ist oft schwer zu warten und zu erweitern. Ich schlage vor herauszufinden, warum dies geschieht und was mit Django-Projekten nicht stimmt.





Ein bisschen Theorie

Wenn wir anfangen, Django ohne Erfahrung aus anderen Sprachen und Frameworks zu lernen, lesen wir zusĂ€tzlich zur Dokumentation Tutorials, Artikel, BĂŒcher und in fast allem sehen wir so etwas:





Django ist ein Framework, das das Entwurfsmuster Model-View-Controller (MVC) verwendet.





Und dann ein paar ungenaue Diagramme und ErklĂ€rungen darĂŒber, was MVC ist. Warum sie ungenau sind und was mit ihnen nicht stimmt, können Sie hier oder hier sehen .





Typischerweise beschreiben solche Schemata MVC folgendermaßen:





  • Modell - Zugriff auf den Datenspeicher





  • Ansicht ist die Schnittstelle, mit der der Benutzer interagiert 





  • Controller ist eine Art Verbindungsobjekt zwischen Modell und Ansicht.





Diese allgemeinen Schemata verwirren und stören nur, wenn Sie eine Anwendung schreiben möchten, die GeschÀftslogik enthÀlt.





Es gibt zwei Dinge, die es wert sind, beachtet zu werden.





, 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 , . , , - , . — .








All Articles