Есть ViewSet
class DocViewSet(viewsets.ModelViewSet): queryset = Doc.objects.all() serializer_class = DocSerializer ... @list_route(methods=['post']) def createby(self, request): """ Создание документа по атрибутам """ req = request.data ddate = req.get('ddate') nameTypeDoc = req.get('typedoc') nameContact = req.get('contact') comment = req.get('comment') doc = Doc.createBy(nameTypeDoc, nameContact, ddate, comment) serializer = self.get_serializer(doc) return Response(serializer.data) ...
Что не нравится.
1. Из request дергаются атрибуты создаваемого док-та. Ладно. Между получением атрибутов и Doc.create хотелось бы воткнуть валидатор. Валидировать прямо в методе не красиво. Ну допустим:
... comment = req.get('comment') if SomeValidator.isValid(ddate,nameTypeDoc,nameContact,comment): doc = Doc.createBy(nameTypeDoc, nameContact, ddate, comment) ...
В каком-то другом методе будет другой валидатор. Возникает куча зависимостей от валидаторов.
2. Из ViewSet напрямую дергаю метод модели. В параметрах nameTypeDoc,nameContact. Получается в модель Doc нужно закинуть зависимости TypeDoc и Contact
class Doc(models.Model): """ Заголовок документа """ n = models.AutoField(primary_key=True) typeDoc = models.ForeignKey('TypeDoc', default=1, db_column='typedoc_n') ddate = models.DateField(default=date.today()) contact = models.ForeignKey('Contact', default=1, db_column='contact_n') ... @staticmethod def createBy(nameTypeDoc=None, nameContact=None, ddate=None, comment=''): """ Создание документа по названию типа и имени контакта ddate в формате 'YYYY-mm-dd' """ typeDoc = TypeDoc().getByName(nameTypeDoc) contact = Contact().getOrCreate(nameContact) if ddate is None: _ddate = date.today() else: d = datetime.strptime(ddate, '%Y-%m-%d') _ddate = date(d.year, d.month, d.day) doc = Doc(contact=contact, typeDoc=typeDoc, ddate=_ddate, comment=comment) doc.save() return doc
Ваще не здорово!
3.
serializer = self.get_serializer(doc)
Для этого метода пусть будет сериализатор по умолчанию. Для другого нужен другой. Можно так:
class DocViewSetFilter(filters.FilterSet): serializer_classes = { 'createby': DocShortSerializer, 'get_with_docitems': DocFullSerializer,
Че-то как-то жирно.
Получается нужен какой-то слой бизнес-логики DocService , ктр. связывает Doc, Contact, TypeDoc. Зависимости от валидаторов и сериализаторов вроде все-таки остаются тут.
Вообще хотелось бы нечто следующее:
from models import TypeDoc, Contact, Doc class DocCreator : def createby(params) typeDoc = TypeDoc().getByName(nameTypeDoc) contact = Contact().getOrCreate(nameContact) if ddate is None: _ddate = date.today() else: d = datetime.strptime(ddate, '%Y-%m-%d') _ddate = date(d.year, d.month, d.day) doc = Doc(contact=contact, typeDoc=typeDoc, ddate=_ddate, comment=comment) doc.save() return doc ....
В DocViewSet закинуть import DocCreator
Так что-ли? Очень не нравится что класс DocViewSet будет иметь много методов , да еще и с кучей зависимостей. Может через mixin решать? В общем как у вас принято? А вообще хотелось бы какой нибудь типовой проект посмотреть с drf. Но не уровня HelloWorld