Esempio n. 1
0
class NakopitelnayaVedomostResource(ModelResource):
    regforms = fields.ManyToManyField(TractorRegFormResource,
                                      'regforms',
                                      full=True,
                                      null=True)
    outfits = fields.ManyToManyField(OutfitResource,
                                     'outfits',
                                     full=True,
                                     null=True)
    author = fields.ForeignKey(UserResource, 'author', full=True)
    station = fields.ForeignKey(StationResource, 'station', full=True)
    event = fields.ForeignKey(OutfitEventResource,
                              'event',
                              full=True,
                              null=True)
    departament_full = fields.ApiField('get_departament_display')
    calcs = fields.ApiField('get_calcs_counter')

    class Meta:
        queryset = models.NakopitelnayaVedomost.objects.all()
        resource_name = 'nakopitelnie_vedomosti'
        list_allowed_methods = ['get', 'post', 'put', 'delete']
        detail_allowed_methods = ['get', 'post', 'put', 'delete']
        collection_name = 'nakopitelnie_vedomosti'
        authorization = Authorization()
        authentication = MultiAuthentication(SessionAuthentication(),
                                             ApiKeyAuthentication())
        filtering = {
            'id': ALL,
            'date': ALL,
            'created_date': ALL,
            'author': ALL_WITH_RELATIONS,
            'station': ALL_WITH_RELATIONS,
            'event': ALL_WITH_RELATIONS,
            'departament': ALL,
        }

    def post_list(self, request, **kwargs):
        data = json.loads(request.body.decode('utf-8'))
        data['author'] = request.user.pk
        errors = []
        calcs_list = []
        form = prd_forms.NakopitelnayaVedomostForm(data)
        if form.is_valid():
            vedomost = form.save()
            for of in vedomost.outfits.all():
                of.conducted = True
                of.save()
            for rf in vedomost.regforms.all():
                rf.conducted = True
                rf.save()
        else:
            errors.append(form.errors)
        if not len(errors):
            return self.create_response(request, {'id': vedomost.pk})
        else:
            return self.error_response(request, errors)
Esempio n. 2
0
class DriverTaskResource(ModelResource):
    customer = fields.ApiField('customer_id')
    car = fields.ApiField('car_id')
    conds_full = fields.ApiField('get_conditions_display')
    get_rate = fields.ApiField('get_rate')

    class Meta:
        queryset = models.DriverTask.objects.all()
        limit = 200
        resource_name = 'driver_task'
        list_allowed_methods = ['get', 'post', 'put', 'delete']
        detail_allowed_methods = ['get', 'post', 'put', 'delete']
        always_return_data = True
        collection_name = 'driver_tasks'
        authorization = Authorization()
        authentication = MultiAuthentication(SessionAuthentication(),
                                             ApiKeyAuthentication())
Esempio n. 3
0
class TinyProfileResource(GenericResource):
    '''
    Tiny Resource representing profiles.

    Typically used to include the critical user information in other
    resources, as in ActionResource for example.
    '''

    content_type = fields.CharField(default="profile")
    username = fields.CharField()
    short_description = fields.CharField()
    first_name = fields.CharField()
    user_id = fields.IntegerField()
    url = fields.CharField()
    mugshot_url = fields.CharField()
    full_name = fields.CharField()
    num_agoras = fields.IntegerField()
    num_votes = fields.IntegerField()
    permissions_on_user = fields.ApiField()

    class Meta(GenericMeta):
        queryset = Profile.objects.filter(user__id__gt=-1)
        fields = ["id"]

    def dehydrate_permissions_on_user(self, bundle):
        return bundle.obj.get_perms(bundle.request.user)

    def dehydrate_username(self, bundle):
        return bundle.obj.user.username

    def dehydrate_short_description(self, bundle):
        return bundle.obj.get_short_description()

    def dehydrate_first_name(self, bundle):
        return bundle.obj.user.first_name

    def dehydrate_user_id(self, bundle):
        return bundle.obj.user.id

    def dehydrate_url(self, bundle):
        return bundle.obj.get_link()

    def dehydrate_mugshot_url(self, bundle):
        return bundle.obj.get_mugshot_url()

    def dehydrate_full_name(self, bundle):
        return bundle.obj.user.get_full_name()

    def dehydrate_num_agoras(self, bundle):
        return bundle.obj.user.agoras.count()

    def dehydrate_num_votes(self, bundle):
        return bundle.obj.count_direct_votes()
Esempio n. 4
0
class SvodnayaVedomostResource(ModelResource):
    calcs = fields.ManyToManyField(SvodnayaZapisResource, 'calcs', full=True)
    author = fields.ForeignKey(UserResource, 'author', full=True)
    station = fields.ForeignKey(StationResource, 'station', full=True)
    event = fields.ForeignKey(OutfitEventResource,
                              'event',
                              full=True,
                              null=True)
    departament_full = fields.ApiField('get_departament_display')

    class Meta:
        queryset = models.SvodnayaVedomost.objects.all()
        resource_name = 'svodnie_vedomosti'
        list_allowed_methods = ['get', 'post', 'put', 'delete']
        detail_allowed_methods = ['get', 'post', 'put', 'delete']
        collection_name = 'svodnie_vedomosti'
        authorization = Authorization()
        authentication = MultiAuthentication(SessionAuthentication(),
                                             ApiKeyAuthentication())
        filtering = {
            'id': ALL,
            'date': ALL,
            'created_date': ALL,
            'author': ALL_WITH_RELATIONS,
            'station': ALL_WITH_RELATIONS,
            'event': ALL_WITH_RELATIONS,
            'departament': ALL
        }

    def post_list(self, request, **kwargs):
        data = json.loads(request.body.decode('utf-8'))
        data['author'] = request.user.pk
        errors = []
        calcs_list = []
        for calc in data['calcs']:
            calc_form = prd_forms.SvodnayaZapisForm(calc['data'])
            if calc_form.is_valid():
                c = calc_form.save()
                c.waybill.conduct()
                calcs_list.append(c.pk)
            else:
                errors.append(calc_form.errors)
        data['calcs'] = calcs_list

        form = prd_forms.SvodnayaVedomostForm(data)
        if form.is_valid():
            sv = form.save()
        else:
            errors.append(form.errors)
        if not len(errors):
            return self.create_response(request, {'id': sv.pk})
        else:
            return self.error_response(request, errors)
Esempio n. 5
0
class FuelResource(ModelResource):
    name = fields.ApiField('get_full')

    class Meta:
        queryset = models.Fuel.objects.all()
        resource_name = 'fuel'
        list_allowed_methods = ['get', 'post', 'put', 'delete']
        detail_allowed_methods = ['get', 'post', 'put', 'delete']
        always_return_data = True
        collection_name = 'fuels'
        authorization = Authorization()
        authentication = MultiAuthentication(SessionAuthentication(),
                                             ApiKeyAuthentication())
Esempio n. 6
0
class OutfitEventResource(ModelResource):
    full_name = fields.ApiField('full_name')

    class Meta:
        queryset = models.OutfitEvent.objects.all()
        resource_name = 'outfit_events'
        list_allowed_methods = ['get', 'post', 'put', 'delete']
        detail_allowed_methods = ['get', 'post', 'put', 'delete']
        always_return_data = True
        collection_name = 'outfit_events'
        authorization = Authorization()
        authentication = MultiAuthentication(SessionAuthentication(),
                                             ApiKeyAuthentication())
        limit = 200
Esempio n. 7
0
class WorkerResource(ModelResource):
    full_name = fields.ApiField('get_short_full_name')
    station = fields.ForeignKey(StationResource, 'station', null=True)
    position = fields.ApiField('get_position')

    class Meta:
        queryset = models.Worker.objects.all()
        resource_name = 'workers'
        list_allowed_methods = ['get', 'post', 'put', 'delete']
        detail_allowed_methods = ['get', 'post', 'put', 'delete']
        collection_name = 'workers'
        authorization = Authorization()
        authentication = MultiAuthentication(SessionAuthentication(),
                                             ApiKeyAuthentication())
        limit = 200
        filtering = {
            'id': ALL,
            'station': ALL_WITH_RELATIONS,
            'level': ALL,
        }

    def __str__(self):
        return '{} {}.{}.'.format(self.surname, self.name[0],
                                  self.patronymic[0])
Esempio n. 8
0
class ProjectPictureResource(ModelResource):
    image = fields.Base64FileField(attribute="original_image")
    project = fields.ApiField()
    license = fields.IntegerField()

    class Meta:
        queryset = ProjectPicture.objects.all()
        resource_name = 'picture'
        throttle = CacheDBThrottle()

        authentication = ApiKeyAuthentication()
        authorization = Authorization()
        allowed_methods = ['post']
        fields = ["desc", "author", "source"]

    def hydrate_project(self, bundle):
        if "project" not in bundle.data or "slug" not in bundle.data[
                "project"] or "lang" not in bundle.data["project"]:
            raise ApiFieldError("A picture must be attached to a project")

        project = bundle.data["project"]
        try:
            project = I4pProjectTranslation.objects.get(
                slug=project["slug"],
                language_code=project["lang"],
                master__in=I4pProject.on_site.all())
        except:
            raise ApiFieldError("Unable to find associated project")

        project = project.master
        bundle.obj.project = project
        return bundle

    def hydrate_license(self, bundle):
        if "license" not in bundle.data:
            raise ApiFieldError("You must set a license for your picture")

        try:
            license = License.objects.get(id=bundle.data["license"])
        except:
            raise ApiFieldError("The selected license is incorrect")

        bundle.obj.license = license
        return bundle
Esempio n. 9
0
class CarResource(ModelResource):
    fuel = fields.ForeignKey(FuelResource, 'fuel', full=True, null=True)
    full_name = fields.ApiField('full_name')

    class Meta:
        queryset = models.Car.objects.all()
        resource_name = 'car'
        limit = 200
        list_allowed_methods = ['get', 'post', 'put', 'delete']
        detail_allowed_methods = ['get', 'post', 'put', 'delete']
        always_return_data = True
        collection_name = 'cars'
        filtering = {
            'id': ALL,
            'kind': ALL,
            'name': ALL_WITH_RELATIONS,
            'number': ALL,
        }
        authorization = Authorization()
        authentication = MultiAuthentication(SessionAuthentication(),
                                             ApiKeyAuthentication())
Esempio n. 10
0
class FieldsResource(ModelResource):
    type = fields.ApiField()
    table = fields.ToOneField('userlayers.api.resources.TablesResource',
                              'model_def')

    class Meta:
        queryset = FieldDefinition.objects.select_subclasses()
        authorization = get_field_auth()()
        authentication = SessionAuthentication()
        validation = FieldValidation()
        fields = ['name']

    def hydrate(self, bundle):
        bundle = super(FieldsResource, self).hydrate(bundle)
        verbose_name = bundle.data['name']
        form = FieldForm(bundle.data)
        if not form.is_valid():
            raise ImmediateHttpResponse(
                response=self.error_response(bundle.request, form.errors))
        bundle.data = form.cleaned_data
        if not bundle.obj.pk:
            model = dict(FIELD_TYPES)[bundle.data['type']]
            if not isinstance(bundle.obj, model):
                self._meta.object_class = model
                bundle.obj = model()
            bundle.obj.null = True
            bundle.obj.blank = True
        bundle.obj.verbose_name = verbose_name
        return bundle

    def dehydrate(self, bundle):
        obj = bundle.obj.type_cast()
        f_type = dict((v, k) for k, v in FIELD_TYPES)[type(obj)]
        bundle.data['type'] = f_type

        if isinstance(obj, GeometryFieldDefinition):
            bundle.data['is_3d'] = obj.dim == GeometryFieldDefinition.DIM_3D
        return bundle
Esempio n. 11
0
class AdvanceSearchAppResource(Resource):
    hits = fields.ApiField(attribute='hits', null=True)

    class Meta:
        resource_name = 'advance-search'
        list_allowed_methods = ['post']
        serializer = default_serializer
        authentication = default_authentication
        object_class = SearchObject
        always_return_data = True

    def detail_uri_kwargs(self, bundle_or_obj):
        kwargs = {}
        if isinstance(bundle_or_obj, Bundle):
            kwargs['pk'] = bundle_or_obj.obj.id
        else:
            kwargs['pk'] = bundle_or_obj['id']

        return kwargs

    def get_object_list(self, request):
        return request

    def obj_get_list(self, bundle, **kwargs):
        return self.get_object_list(bundle.request)

    def obj_create(self, bundle, **kwargs):
        user = bundle.request.user
        groups = user.groups.all()

        # if anonymous user search public data only
        query_text = bundle.data.get("text", None)
        type_tag = bundle.data.get("TypeTag", [])
        index_list = []
        for type in type_tag:
            if type == 'Experiment':
                index_list.append('experiments')
            elif type == 'Dataset':
                index_list.append('dataset')
            elif type == 'Datafile':
                index_list.append('datafile')
        end_date = bundle.data.get("EndDate", None)
        start_date = bundle.data.get("StartDate", None)
        if end_date is not None:
            end_date_utc = datetime.datetime.strptime(end_date, "%Y-%m-%dT%H:%M:%S.%fZ") \
                .replace(tzinfo=pytz.timezone('UTC'))
            end_date = end_date_utc.astimezone(LOCAL_TZ).date()
        else:
            # set end date to today's date
            end_date = datetime.datetime.today().replace(
                tzinfo=pytz.timezone('UTC'))
        if start_date:
            start_date_utc = datetime.datetime.strptime(start_date, "%Y-%m-%dT%H:%M:%S.%fZ") \
                .replace(tzinfo=pytz.timezone('UTC'))
            start_date = start_date_utc.astimezone(LOCAL_TZ).date()
        instrument_list = bundle.data.get("InstrumentList", None)
        instrument_list_id = []
        if instrument_list:
            for ins in instrument_list:
                instrument_list_id.append(
                    Instrument.objects.get(name__exact=ins).id)
        # query for experiment model
        ms = MultiSearch(index=index_list)
        if 'experiments' in index_list:
            query_exp = Q("match", title=query_text)
            if user.is_authenticated:
                query_exp_oacl = Q("term", objectacls__entityId=user.id) | \
                                 Q("term", public_access=100)
                for group in groups:
                    query_exp_oacl = query_exp_oacl | \
                                     Q("term", objectacls__entityId=group.id)
            else:
                query_exp_oacl = Q("term", public_access=100)
            if start_date is not None:
                query_exp = query_exp & Q("range",
                                          created_time={
                                              'gte': start_date,
                                              'lte': end_date
                                          })
            query_exp = query_exp & query_exp_oacl
            ms = ms.add(
                Search(index='experiments').extra(
                    size=MAX_SEARCH_RESULTS,
                    min_score=MIN_CUTOFF_SCORE).query(query_exp))
        if 'dataset' in index_list:
            query_dataset = Q("match", description=query_text)
            if user.is_authenticated:
                query_dataset_oacl = Q("term", **{'experiments.objectacls.entityId': user.id}) | \
                                     Q("term", **{'experiments.public_access': 100})
                for group in groups:
                    query_dataset_oacl = query_dataset_oacl | \
                                         Q("term", **{'experiments.objectacls.entityId': group.id})
            else:
                query_dataset_oacl = Q("term",
                                       **{'experiments.public_access': 100})
            if start_date is not None:
                query_dataset = query_dataset & Q("range",
                                                  created_time={
                                                      'gte': start_date,
                                                      'lte': end_date
                                                  })
            if instrument_list:
                query_dataset = query_dataset & Q(
                    "terms", **{'instrument.id': instrument_list_id})
            # add instrument query
            ms = ms.add(
                Search(index='dataset').extra(
                    size=MAX_SEARCH_RESULTS,
                    min_score=MIN_CUTOFF_SCORE).query(query_dataset).query(
                        'nested', path='experiments',
                        query=query_dataset_oacl))
        if 'datafile' in index_list:
            query_datafile = Q("match", filename=query_text)
            if user.is_authenticated:
                query_datafile_oacl = Q("term", **{'dataset.experiments.objectacls.entityId': user.id}) | \
                                      Q("term", **{'dataset.experiments.public_access': 100})
                for group in groups:
                    query_datafile_oacl = query_datafile_oacl | \
                                          Q("term", **{'dataset.experiments.objectacls.entityId': group.id})
            else:
                query_datafile_oacl = Q(
                    "term", **{'dataset.experiments.public_access': 100})
            if start_date is not None:
                query_datafile = query_datafile & Q("range",
                                                    created_time={
                                                        'gte': start_date,
                                                        'lte': end_date
                                                    })
            ms = ms.add(
                Search(index='datafile').extra(
                    size=MAX_SEARCH_RESULTS,
                    min_score=MIN_CUTOFF_SCORE).query(query_datafile).query(
                        'nested',
                        path='dataset.experiments',
                        query=query_datafile_oacl))
        result = ms.execute()
        result_dict = {k: [] for k in ["experiments", "datasets", "datafiles"]}
        for item in result:
            for hit in item.hits.hits:
                if hit["_index"] == "dataset":
                    result_dict["datasets"].append(hit)

                elif hit["_index"] == "experiments":
                    result_dict["experiments"].append(hit)

                elif hit["_index"] == "datafile":
                    result_dict["datafiles"].append(hit)

        if bundle.request.method == 'POST':
            bundle.obj = SearchObject(id=1, hits=result_dict)
        return bundle
Esempio n. 12
0
class UserResource(ModelResource):
    full_name = fields.ApiField('get_full_name')
    station = fields.ForeignKey('primary_docs.api.resources.StationResource',
                                'station',
                                full=True,
                                null=True)
    organization = fields.ForeignKey(
        'primary_docs.api.resources.OrganizationResource',
        'organization',
        full=True,
        null=True)

    class Meta:
        queryset = User.objects.all()
        resource_name = 'users'
        allowed_methods = ['get', 'post', 'delete', 'put', 'options']
        authorization = Authorization()
        authentication = MultiAuthentication(
            ApiKeyAuthentication(),
            BasicAuthentication(),
        )
        collection_name = 'users'
        detail_uri_name = 'username'
        fields = (
            'username',
            'id',
            'full_name',
            'first_name',
            'last_name',
            'third_name',
            'position',
            'avatar',
            'is_staff',
            'email',
        )
        filtering = {
            'id': (
                'exact',
                'ne',
            ),
        }

    def dehydrate_avatar(self, bundle, **kwargs):
        url = bundle.request.build_absolute_uri(bundle.obj.avatar.url)
        return url

    def dehydrate(self, bundle):
        if bundle.request.GET.get('auth'):
            if bundle.obj == bundle.request.user:
                bundle.data['api_key'] = bundle.request.user.api_key.key
        return bundle

    def post_list(self, request, **kwargs):
        form = UserForm(request.POST or None, request.FILES or None)
        if form.is_valid():
            user = User.objects.create_user(**form.cleaned_data)
        else:
            return self.error_response(request, form.errors)

    def put_list(self, request, **kwargs):
        pk = request.GET.get('pk')
        if pk:
            try:
                instance = User.objects.get(pk=pk)
            except Exception as e:
                return self.error_response(request, e)
            if request.user.pk == instance.pk or request.user.is_staff:
                form = UserForm(request.POST or None,
                                request.FILES or None,
                                instance=instance)
                if form.is_valid():
                    user = form.save()
                    user.set_password(form.cleaned_data['password'])
                    user.save()
                    return user
                else:
                    return self.error_response(request, form.errors)
            return self.error_response(request, 'Не достаточно прав!')
Esempio n. 13
0
        class AgoraPermissionsResource(TinyAgoraResource):
            agora_permissions = fields.ApiField()

            def dehydrate_agora_permissions(self, bundle):
                return bundle.obj.get_perms(bundle.request.user)
Esempio n. 14
0
class ImageResource(ChemblModelResource):

# ----------------------------------------------------------------------------------------------------------------------

    image = fields.ApiField()

    class Meta(ChemblResourceMeta):
        resource_name = 'image'
        serializer = fakeSerializer
        default_format = 'image/png'
        fields = ('image',)
        description = {'api_dispatch_detail' : '''
Get image of the compound, specified by

*  _ChEMBL ID_ or
*  _Standard InChI Key_

You can specify optional parameters:

*  __engine__ - chemistry toolkit used for rendering, can be _rdkit_ or _indigo_, default: _rdkit_.
*  __dimensions__ - size of the image (the length of the square image side). Can't be more than _500_, default: _500_.
*  __ignoreCoords__ - Ignore 2D coordinates encoded in the molfile and let the chemistry toolkit to recompute them.


'''}
        queryset = CompoundStructures.objects.all() if 'downgraded' not in available_fields else \
                        CompoundStructures.objects.exclude(molecule__downgraded=True)


# -----------------------------------------------------------------------------------------------------------------------

    def base_urls(self):
        return [
            url(r"^(?P<resource_name>%s)%s$" % (self._meta.resource_name, trailing_slash(),), self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)\.(?P<format>\w+)$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/schema\.(?P<format>\w+)$" % self._meta.resource_name, self.wrap_view('get_schema'), name="api_get_schema"),
            url(r"^(?P<resource_name>%s)/schema%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('get_schema'), name="api_get_schema"),
            url(r"^(?P<resource_name>%s)/datatables\.(?P<format>\w+)$" % self._meta.resource_name, self.wrap_view('get_datatables'), name="api_get_datatables"),
            url(r"^(?P<resource_name>%s)/(?P<molecule__chembl_id>[Cc][Hh][Ee][Mm][Bb][Ll]\d[\d]*)%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<standard_inchi_key>[A-Z]{14}-[A-Z]{10}-[A-Z])%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<molecule__chembl_id>[Cc][Hh][Ee][Mm][Bb][Ll]\d[\d]*)\.(?P<format>\w+)$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<standard_inchi_key>[A-Z]{14}-[A-Z]{10}-[A-Z])\.(?P<format>\w+)$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<molecule__chembl_id>[Cc][Hh][Ee][Mm][Bb][Ll]\d[\d]*)$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<standard_inchi_key>[A-Z]{14}-[A-Z]{10}-[A-Z])$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<standard_inchi_key>[A-Z]{14}-[A-Z]{10}-[A-Z])\.(?P<format>png|svg)$" % MoleculeResource._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<molecule__chembl_id>[Cc][Hh][Ee][Mm][Bb][Ll]\d[\d]*)\.(?P<format>png|svg)$" % MoleculeResource._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
        ]

# ----------------------------------------------------------------------------------------------------------------------

    def prepend_urls(self):
        return []

# ----------------------------------------------------------------------------------------------------------------------

    def error_response(self, request, errors, response_class=None):
        if request.format not in ChEMBLApiSerializer.formats:
            request.format = 'json'
        return super(ImageResource, self).error_response(request, errors, response_class)

# ----------------------------------------------------------------------------------------------------------------------

    def wrap_view(self, view):
        @csrf_exempt
        def wrapper(request, *args, **kwargs):

            if request.method == 'GET':
                kwargs.update(request.GET.dict())

            elif request.method == 'POST':
                if request.META.get('CONTENT_TYPE', 'application/json').startswith(
                        ('multipart/form-data', 'multipart/form-data')):
                    post_arg = request.POST.dict()
                else:
                    post_arg = self.deserialize(request, request.body,
                                                format=request.META.get('CONTENT_TYPE', 'application/json'))
                kwargs.update(post_arg)

            request.format = kwargs.get('format', None)

            if 'molecule__chembl_id' in kwargs and isinstance(kwargs['molecule__chembl_id'], basestring):
                kwargs['molecule__chembl_id'] = kwargs['molecule__chembl_id'].upper()

            wrapped_view = super(ChemblModelResource, self).wrap_view(view)
            return wrapped_view(request, *args, **kwargs)

        return wrapper

# ----------------------------------------------------------------------------------------------------------------------

    def cached_obj_get(self, **kwargs):
        """
        A version of ``obj_get`` that uses the cache as a means to get
        commonly-accessed data faster.
        """
        get_failed = False
        cache_key = self.generate_cache_key('detail', **kwargs)

        try:
            cached_bundle = self._meta.cache.get(cache_key)
        except Exception:
            cached_bundle = None
            get_failed = True
            self.log.error('Caching get exception', exc_info=True, extra={'kwargs': kwargs, })

        if cached_bundle is None:
            cached_bundle = self.obj_get(**kwargs)
            if not get_failed:
                try:
                    self._meta.cache.set(cache_key, cached_bundle)
                except Exception:
                    self.log.error('Caching set exception', exc_info=True, extra={'kwargs': kwargs, })

        return cached_bundle

# ----------------------------------------------------------------------------------------------------------------------

    def obj_get(self, **kwargs):

        chembl_id = kwargs.get('molecule__chembl_id')
        standard_inchi_key = kwargs.get('standard_inchi_key')

        if not chembl_id and not standard_inchi_key:
            raise BadRequest("ChEMBL ID or standard InChi Key required.")

        filters = dict((k,v) for k,v in kwargs.items() if k in ('molecule__chembl_id','standard_inchi_key'))
        stringified_kwargs = ', '.join(["%s=%s" % (k, v) for k, v in filters.items()])

        filters.update({
            'molecule__chembl__entity_type':'COMPOUND',
            'molecule__compoundstructures__isnull': False,
            'molecule__compoundproperties__isnull': False,
        })

        try:
            molfile_list = self.get_object_list(None).filter(**filters).values_list('molfile', flat=True)

            if len(molfile_list) <= 0:
                raise ObjectDoesNotExist("Couldn't find an instance of '%s' which matched '%s'." %
                                                           (self._meta.object_class.__name__, stringified_kwargs))
            elif len(molfile_list) > 1:
                raise MultipleObjectsReturned("More than '%s' matched '%s'." %
                                              (self._meta.object_class.__name__, stringified_kwargs))
        except ValueError:
            raise NotFound("Invalid resource lookup data provided (mismatched type).")

        return molfile_list[0]

# ----------------------------------------------------------------------------------------------------------------------

    def render_image(self, mol, request, **kwargs):
        frmt = kwargs.get('format', 'png')
        try:
            size = int(kwargs.get("dimensions", 500))
        except ValueError:
            return self.answerBadRequest(request, "Image dimensions supplied are invalid")
        ignoreCoords = kwargs.get("ignoreCoords", False)

        bgColor = kwargs.get("bgColor")
        if bgColor and isinstance(bgColor, basestring):
            bgColor = bgColor.lower()
            if bgColor in COLOR_NAMES:
                options.bgColor = COLOR_NAMES[bgColor]
            else:
                options.bgColor = None
        else:
            options.bgColor = None

        if size < 1 or size > 500:
            return self.answerBadRequest(request, "Image dimensions supplied are invalid, max value is 500")

        if frmt == 'png':
            engine = kwargs.get("engine", 'rdkit').lower()
            if engine not in SUPPORTED_ENGINES:
                return self.answerBadRequest(request, "Unsupported engine %s" % engine)
            img, mimetype = self.render_png(mol, size, engine, ignoreCoords)
            if request.is_ajax():
                img = base64.b64encode(img)
        elif frmt == 'svg':
            engine = kwargs.get("engine", 'rdkit').lower()
            if engine not in SUPPORTED_ENGINES:
                return self.answerBadRequest(request, "Unsupported engine %s" % engine)
            img, mimetype = self.render_svg(mol, size, engine, ignoreCoords)
        elif frmt == 'json':
            img, mimetype = self.render_json(mol, size, ignoreCoords)
        elif frmt == 'chemcha':
            img, mimetype = self.render_chemcha(mol, size, ignoreCoords)
            if request.is_ajax():
                img = base64.b64encode(img)
        else:
            return self.answerBadRequest(request, "Unsupported format %s" % frmt)
        response = HttpResponse(content_type=mimetype)
        response.write(img)
        return response

# ----------------------------------------------------------------------------------------------------------------------

    def render_svg(self, molstring, size, engine, ignoreCoords):
        ret = None
        if engine == 'rdkit':
            mol = Chem.MolFromMolBlock(str(molstring), sanitize=False)
            mol.UpdatePropertyCache(strict=False)
            ret = render_rdkit(mol, None, options, 'svg', size, True, ignoreCoords)
        elif engine == 'indigo':
            mol = indigoObj.loadMolecule(str(molstring))
            ret = render_indigo(mol, options, 'svg', 10, size, True, ignoreCoords)
        return ret, "image/svg+xml"

# ----------------------------------------------------------------------------------------------------------------------

    def render_json(self, molstring, size, ignoreCoords):
        mol = Chem.MolFromMolBlock(str(molstring), sanitize=False)
        mol.UpdatePropertyCache(strict=False)
        if ignoreCoords:
            AllChem.Compute2DCoords(mol)

        leg = mol.GetProp("_Name") if mol.HasProp("_Name") else None
        return MolToJSON(mol, size=(size,size), legend=leg, fitImage=True, options=options), 'application/json'

# ----------------------------------------------------------------------------------------------------------------------

    def render_png(self, molstring, size, engine, ignoreCoords):
        ret = None
        if engine == 'rdkit':
            fontSize = int(size / 33)
            if size < 200:
                fontSize = 1
            options.atomLabelFontSize = fontSize
            mol = Chem.MolFromMolBlock(str(molstring), sanitize=False)
            mol.UpdatePropertyCache(strict=False)
            ret = render_rdkit(mol, None, options, 'png', size, True, ignoreCoords)
        elif engine == 'indigo':
            mol = indigoObj.loadMolecule(str(molstring))
            ret = render_indigo(mol, options, 'png', 10, size, True, ignoreCoords)
        return ret, "image/png"

# ----------------------------------------------------------------------------------------------------------------------

    def get_detail(self, request, **kwargs):
        cache_key = self.generate_cache_key('image', **dict({'is_ajax': request.is_ajax()}, **kwargs))
        get_failed = False

        in_cache = False
        start = time.time()
        if kwargs.get('format', 'png') == 'chemcha' and '_' in kwargs:
            ret = self.image_get(request, **kwargs)
        else:
            try:
                ret = self._meta.cache.get(cache_key)
                in_cache = True
            except Exception:
                ret = None
                get_failed = True
                self.log.error('Cashing get exception', exc_info=True, extra=kwargs)

            if ret is None:
                in_cache = False
                ret = self.image_get(request, **kwargs)
                if not get_failed:
                    try:
                        self._meta.cache.set(cache_key, ret)
                    except Exception:
                        self.log.error('Cashing set exception', exc_info=True, extra=kwargs)

        if WS_DEBUG:
            end = time.time()
            ret['X-ChEMBL-in-cache'] = in_cache
            ret['X-ChEMBL-retrieval-time'] = end - start
        return ret

# ----------------------------------------------------------------------------------------------------------------------

    def image_get(self, request, **kwargs):
        try:
            mol = self.cached_obj_get(**kwargs)
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices("More than one resource is found at this URI.")

        return self.render_image(mol, request, **kwargs)

# ----------------------------------------------------------------------------------------------------------------------

    def render_chemcha(self, molstring, size, ignoreCoords):
        buf = StringIO.StringIO()
        fontSize = int(size / 33)
        if size < 200:
            fontSize = 1
        mol = Chem.MolFromMolBlock(str(molstring), sanitize=False)
        mol.UpdatePropertyCache(strict=False)
        if ignoreCoords:
            AllChem.Compute2DCoords(mol)

        if DrawingOptions:
            options = DrawingOptions()
            options.useFraction = 1.0
            options.dblBondOffset = .13
            options.atomLabelFontSize = fontSize
        else:
            options = {"useFraction": 1.0,
                       "dblBondOffset": .13,
                       'atomLabelFontSize': fontSize,}
        image = draw.MolToImage(mol, size=(size, size), fitImage=True, options=options)
        image = SineWarp().render(image)
        image.save(buf, "PNG")
        return buf.getvalue(), "image/png"

# ----------------------------------------------------------------------------------------------------------------------

    def generate_cache_key(self, *args, **kwargs):

        molecule__chembl_id = kwargs.get('molecule__chembl_id', '')
        standard_inchi_key = kwargs.get('standard_inchi_key', '')
        bgColor = kwargs.get('bgColor', '').lower()
        format = kwargs.get('format', 'png')
        engine = kwargs.get('engine', 'rdkit')
        dimensions = kwargs.get('dimensions', 500)
        ignoreCoords = kwargs.get("ignoreCoords", False)
        is_ajax = kwargs.get("is_ajax", 2)

        # Use a list plus a ``.join()`` because it's faster than concatenation.
        cache_key = "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s" % (self._meta.api_name,
                                                          self._meta.resource_name,
                                                          '|'.join(args),
                                                          str(molecule__chembl_id),
                                                          str(standard_inchi_key),
                                                          str(format),
                                                          str(engine),
                                                          str(dimensions),
                                                          str(ignoreCoords),
                                                          str(is_ajax),
                                                          bgColor)
        return cache_key
Esempio n. 15
0
class HostResource(Resource):

    name = fields.CharField(attribute='name')
    modified = fields.IntegerField(attribute='modified', null=True)
    puppet_status = fields.IntegerField(attribute='puppet_status', null=True)
    build = fields.BooleanField(attribute='build')
    console_url = fields.CharField(attribute='console_url',
                                   null=True,
                                   readonly=True)
    parameters = fields.ApiField(attribute='parameters', null=True)
    hostgroups = fields.ApiField(attribute='hostgroups', null=True)
    hostgroups_id = fields.ApiField(attribute='hostgroups_id', null=True)
    hostgroup_id = fields.CharField(attribute='hostgroup_id', null=True)

    def __init__(self, *args, **kwargs):
        super(HostResource, self).__init__(*args, **kwargs)
        self.foreman = Foreman()

    class Meta:
        resource_name = 'host'
        object_class = HostObject
        authorization = Authorization()

    def detail_uri_kwargs(self, bundle_or_obj):
        kwargs = {}

        if isinstance(bundle_or_obj, Bundle):
            kwargs['pk'] = bundle_or_obj.obj.name
        else:
            kwargs['pk'] = bundle_or_obj.name

        return kwargs

    def get_object_list(self, request):
        #TODO: check if anon
        if request.user:
            query = self.foreman.get_hosts_by_user(request.user.username)
            results = []
            for host in query:
                new_host = HostObject(initial=host)
                results.append(new_host)
            return results
        return []

    def obj_get_list(self, bundle, **kwargs):
        return self.get_object_list(bundle.request)

    def obj_get(self, bundle, **kwargs):
        host = self.foreman.get_host(kwargs['pk'])
        return HostObject(initial=host)

    def obj_create(self, bundle, **kwargs):
        pass

    def put_detail(self, request, **kwargs):

        hostnames = self.foreman.get_hostnames_by_user(request.user.username)
        if kwargs['pk'] not in hostnames:
            raise ApiException('Permission denied')

        return super(HostResource, self).put_detail(request, **kwargs)

    def obj_update(self, bundle, **kwargs):
        bundle.obj = HostObject(initial=kwargs)
        bundle = self.full_hydrate(bundle)

        self.foreman.update_host(bundle.obj)

    def obj_delete_list(self, bundle, **kwargs):
        pass

    def obj_delete(self, bundle, **kwargs):
        pass

    def rollback(self, bundles):
        pass
Esempio n. 16
0
class I4pProjectEditResource(ModelResource):
    """
    Resource used when we have to make edit in database (create, update…) a project sheet
    """
    lang = fields.CharField(null=False)
    # We HAVE TO define site as a field, to avoid error with translations
    # as m2m require an access to created object to save relations
    site = fields.ApiField(null=True)
    topics = fields.ApiField(null=True)

    class Meta:
        queryset = I4pProject.objects.all()
        fields = ["created", "website", "status"]
        include_resource_uri = False
        authentication = ApiKeyAuthentication()
        authorization = Authorization()
        throttle = CacheDBThrottle()

        new_allowed_methods = ['post']

    def detail_uri_kwargs(self, bundle_or_obj):
        kwargs = {}

        if isinstance(bundle_or_obj, Bundle):
            kwargs[
                self._meta.
                detail_uri_name] = bundle_or_obj.obj.language_code + "/" + bundle_or_obj.obj.slug
        else:
            kwargs[
                self._meta.
                detail_uri_name] = bundle_or_obj.language_code + "/" + bundle_or_obj.slug

        return kwargs

    def resource_uri_kwargs(self, bundle_or_obj=None):
        kwargs = {
            'resource_name': 'project',
        }

        if self._meta.api_name is not None:
            kwargs['api_name'] = self._meta.api_name

        if bundle_or_obj is not None:
            kwargs.update(self.detail_uri_kwargs(bundle_or_obj))

        return kwargs

    def prepend_urls(self):
        array = []
        array.append(
            url(r"^project/new%s" % trailing_slash(),
                self.wrap_view('dispatch_new'),
                name="api_dispatch_new"))
        return array

    def dispatch_new(self, request, **kwargs):
        return self.dispatch('new', request, **kwargs)

    def post_new(self, request, **kwargs):
        return self.post_list(request, **kwargs)

    # This method is used only to check if everything is ok before saving anything
    def alter_deserialized_detail_data(self, request, deserialized):
        # 'Topics' tests
        site = Site.objects.get_current()
        if "topics" not in deserialized or len(deserialized["topics"]) == 0:
            site_topics = SiteTopic.objects.filter(site=site)
            if len(site_topics) > 1:
                raise ApiFieldError(
                    "There is more than one topic for this site, you have to provide a 'topics' field"
                )
        else:
            valid_topic = 0
            for topic_slug in deserialized["topics"]:
                site_topic = SiteTopic.objects.filter(
                    site=site, topic__slug=topic_slug) or None
                if site_topic:
                    valid_topic += 1
            if valid_topic == 0:
                raise ApiFieldError(
                    "No valid topic provided. Please check your 'topics' field."
                )

        # 'Lang' tests
        if "lang" not in deserialized:
            raise ApiFieldError(
                "The 'lang' parameter is mandatory to create a new project'")
        elif len(deserialized["lang"]) < 1:
            raise ApiFieldError(
                "The 'lang' paramater requires at least one translation")
        else:
            valid_lang = 0
            for language_code, language_data in deserialized['lang'].iteritems(
            ):
                if language_code not in dict(LANGUAGES):
                    continue
                if "title" not in language_data:
                    raise ApiFieldError(
                        "A translation requires a least a 'title' parameter")
                else:
                    valid_lang += 1
            if valid_lang == 0:
                raise ApiFieldError("No valid translation sent")

        return deserialized

    # Read warning above about "site" field
    def hydrate_site(self, bundle):
        bundle.obj.site.add(Site.objects.get_current())
        return bundle

    def hydrate_topics(self, bundle):
        site = Site.objects.get_current()
        if "topics" not in bundle.data or len(bundle.data["topics"]) == 0:
            site_topics = SiteTopic.objects.filter(site=site)
            bundle.obj.topics.add(site_topics[0])
        else:
            for topic_slug in bundle.data["topics"]:
                site_topic = SiteTopic.objects.filter(
                    site=site, topic__slug=topic_slug) or None
                if site_topic:
                    bundle.obj.topics.add(site_topic[0])

        return bundle

    def hydrate_lang(self, bundle):
        translated_bundle = Bundle()
        translation_resource = I4pProjectTranslationEditResource()

        for language_code, language_data in bundle.data['lang'].iteritems():
            if language_code not in dict(LANGUAGES):
                continue
            translated_bundle.data = language_data
            translated_bundle.obj = bundle.obj.translate(language_code)
            translation_resource.obj_create(translated_bundle)

        return bundle
Esempio n. 17
0
class ImageResource(ChemblModelResource):

# ----------------------------------------------------------------------------------------------------------------------

    image = fields.ApiField()

    class Meta(ChemblResourceMeta):
        resource_name = 'image'
        serializer = fakeSerializer
        default_format = 'image/svg+xml'
        fields = ('image',)
        description = {'api_dispatch_detail' : '''
Get image of the compound, specified by

*  _ChEMBL ID_ or
*  _Standard InChI Key_

You can specify optional parameters:

*  __engine__ - chemistry toolkit used for rendering, can be _rdkit_ only, default: _rdkit_.
*  __dimensions__ - size of the image (the length of the square image side). Can't be more than _500_, default: _500_.
*  __ignoreCoords__ - Ignore 2D coordinates encoded in the molfile and let the chemistry toolkit to recompute them.


'''}
        queryset = CompoundStructures.objects.all() if 'downgraded' not in available_fields else \
                        CompoundStructures.objects.exclude(molecule__downgraded=True)


# -----------------------------------------------------------------------------------------------------------------------

    def base_urls(self):
        return [
            url(r"^(?P<resource_name>%s)%s$" % (self._meta.resource_name, trailing_slash(),), self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)\.(?P<format>\w+)$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/schema\.(?P<format>\w+)$" % self._meta.resource_name, self.wrap_view('get_schema'), name="api_get_schema"),
            url(r"^(?P<resource_name>%s)/schema%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('get_schema'), name="api_get_schema"),
            url(r"^(?P<resource_name>%s)/datatables\.(?P<format>\w+)$" % self._meta.resource_name, self.wrap_view('get_datatables'), name="api_get_datatables"),
            url(r"^(?P<resource_name>%s)/(?P<molecule__chembl_id>[Cc][Hh][Ee][Mm][Bb][Ll]\d[\d]*)%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<standard_inchi_key>[A-Z]{14}-[A-Z]{10}-[A-Z])%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<molecule__chembl_id>[Cc][Hh][Ee][Mm][Bb][Ll]\d[\d]*)\.(?P<format>\w+)$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<standard_inchi_key>[A-Z]{14}-[A-Z]{10}-[A-Z])\.(?P<format>\w+)$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<molecule__chembl_id>[Cc][Hh][Ee][Mm][Bb][Ll]\d[\d]*)$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<standard_inchi_key>[A-Z]{14}-[A-Z]{10}-[A-Z])$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<standard_inchi_key>[A-Z]{14}-[A-Z]{10}-[A-Z])\.(?P<format>svg)$" % MoleculeResource._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<molecule__chembl_id>[Cc][Hh][Ee][Mm][Bb][Ll]\d[\d]*)\.(?P<format>svg|png)$" % MoleculeResource._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
        ]

# ----------------------------------------------------------------------------------------------------------------------

    def prepend_urls(self):
        return []

# ----------------------------------------------------------------------------------------------------------------------

    def error_response(self, request, errors, response_class=None):
        if request.format not in ChEMBLApiSerializer.formats:
            request.format = 'json'
        return super(ImageResource, self).error_response(request, errors, response_class)

# ----------------------------------------------------------------------------------------------------------------------

    def wrap_view(self, view):
        @csrf_exempt
        def wrapper(request, *args, **kwargs):

            if request.method == 'GET':
                kwargs.update(request.GET.dict())

            elif request.method == 'POST':
                if request.META.get('CONTENT_TYPE', 'application/json').startswith(
                        ('multipart/form-data', 'multipart/form-data')):
                    post_arg = request.POST.dict()
                else:
                    post_arg = self.deserialize(request, request.body,
                                                format=request.META.get('CONTENT_TYPE', 'application/json'))
                kwargs.update(post_arg)

            request.format = kwargs.get('format', None)

            if 'molecule__chembl_id' in kwargs and isinstance(kwargs['molecule__chembl_id'], str):
                kwargs['molecule__chembl_id'] = kwargs['molecule__chembl_id'].upper()

            wrapped_view = super(ChemblModelResource, self).wrap_view(view)
            return wrapped_view(request, *args, **kwargs)

        return wrapper

# ----------------------------------------------------------------------------------------------------------------------

    def cached_obj_get(self, **kwargs):
        """
        A version of ``obj_get`` that uses the cache as a means to get
        commonly-accessed data faster.
        """
        get_failed = False
        cache_key = self.generate_cache_key('detail', **kwargs)

        try:
            cached_bundle = self._meta.cache.get(cache_key)
        except Exception:
            cached_bundle = None
            get_failed = True
            self.log.error('Caching get exception', exc_info=True, extra={'kwargs': kwargs, })

        if cached_bundle is None:
            cached_bundle = self.obj_get(**kwargs)
            if not get_failed:
                try:
                    self._meta.cache.set(cache_key, cached_bundle)
                except Exception:
                    self.log.error('Caching set exception', exc_info=True, extra={'kwargs': kwargs, })

        return cached_bundle

# ----------------------------------------------------------------------------------------------------------------------

    def obj_get(self, **kwargs):

        chembl_id = kwargs.get('molecule__chembl_id')
        standard_inchi_key = kwargs.get('standard_inchi_key')

        if not chembl_id and not standard_inchi_key:
            raise BadRequest("ChEMBL ID or standard InChi Key required.")

        filters = dict((k,v) for k,v in list(kwargs.items()) if k in ('molecule__chembl_id','standard_inchi_key'))
        stringified_kwargs = ', '.join(["%s=%s" % (k, v) for k, v in list(filters.items())])

        filters.update({
            'molecule__chembl__entity_type':'COMPOUND',
            'molecule__compoundstructures__isnull': False,
        })

        try:
            molfile_list = self.get_object_list(None).filter(**filters).values_list('molfile', flat=True)

            if len(molfile_list) <= 0:
                raise ObjectDoesNotExist("Couldn't find an instance of '%s' which matched '%s'." %
                                                           (self._meta.object_class.__name__, stringified_kwargs))
            elif len(molfile_list) > 1:
                raise MultipleObjectsReturned("More than '%s' matched '%s'." %
                                              (self._meta.object_class.__name__, stringified_kwargs))
        except ValueError:
            raise NotFound("Invalid resource lookup data provided (mismatched type).")

        return molfile_list[0]

# ----------------------------------------------------------------------------------------------------------------------

    def render_image(self, mol, request, **kwargs):
        global BEAKER_CTAB_TO_SVG_URL

        req_format = getattr(request, 'format', 'svg')

        try:
            size = int(kwargs.get("dimensions", 500))
        except ValueError:
            return self.answerBadRequest(request, "Image dimensions supplied are invalid")

        ignoreCoords = kwargs.get("ignoreCoords", False)

        if size < 1 or size > 1500:
            return self.answerBadRequest(request, "Image dimensions supplied are invalid, max value is 500")
        engine = kwargs.get("engine", 'rdkit').lower()
        if engine not in SUPPORTED_ENGINES:
            return self.answerBadRequest(request, "Unsupported engine %s" % engine)

        img_mime_type = None
        mol_img = None

        if engine == 'rdkit' and req_format == 'svg':
            img_url = BEAKER_CTAB_TO_SVG_URL
            img_url += '?size={0}'.format(size)
            if ignoreCoords:
                img_url += '&computeCoords=1'
            img_request = requests.post(img_url, data=mol)
            if img_request.status_code != 200:
                self.answerBadRequest(request, 'ERROR: Beaker at "{0}" failed to produce an image for "{1}"'
                                      .format(BEAKER_CTAB_TO_SVG_URL, mol))
            mol_img = img_request.content
            img_mime_type = "image/svg+xml"
        else:
            self.answerBadRequest(request, 'Unsupported rendering engine "{0}" or format "{1}"'
                                  .format(engine, req_format))

        response = HttpResponse(content_type=img_mime_type)
        response.write(mol_img)

        return response

# ----------------------------------------------------------------------------------------------------------------------

    def get_detail(self, request, **kwargs):
        cache_key = self.generate_cache_key('image', **dict({'is_ajax': request.is_ajax()}, **kwargs))
        get_failed = False

        frmt = request.format

        if frmt == 'png':
            self.answerBadRequest(request, 'PNG format has been deprecated, please use SVG.')
        if frmt == 'json':
            self.answerBadRequest(request, 'JSON image format has been deprecated, please use SVG.')

        in_cache = False
        start = time.time()
        try:
            ret = self._meta.cache.get(cache_key)
            in_cache = True
        except Exception:
            ret = None
            get_failed = True
            self.log.error('Cashing get exception', exc_info=True, extra=kwargs)

        if ret is None:
            in_cache = False
            ret = self.image_get(request, **kwargs)
            if not get_failed:
                try:
                    self._meta.cache.set(cache_key, ret)
                except Exception:
                    self.log.error('Cashing set exception', exc_info=True, extra=kwargs)

        if settings.DEBUG:
            end = time.time()
            ret['X-ChEMBL-in-cache'] = in_cache
            ret['X-ChEMBL-retrieval-time'] = end - start
        return ret

# ----------------------------------------------------------------------------------------------------------------------

    def image_get(self, request, **kwargs):
        try:
            mol = self.cached_obj_get(**kwargs)
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices("More than one resource is found at this URI.")

        return self.render_image(mol, request, **kwargs)

# ----------------------------------------------------------------------------------------------------------------------

    def generate_cache_key(self, *args, **kwargs):

        molecule__chembl_id = kwargs.get('molecule__chembl_id', '')
        standard_inchi_key = kwargs.get('standard_inchi_key', '')
        bgColor = kwargs.get('bgColor', '').lower()
        format = kwargs.get('format', 'svg')
        engine = kwargs.get('engine', 'rdkit')
        dimensions = kwargs.get('dimensions', 500)
        ignoreCoords = kwargs.get("ignoreCoords", False)
        is_ajax = kwargs.get("is_ajax", 2)

        # Use a list plus a ``.join()`` because it's faster than concatenation.
        cache_key = "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s" % (self._meta.api_name,
                                                          self._meta.resource_name,
                                                          '|'.join(args),
                                                          str(molecule__chembl_id),
                                                          str(standard_inchi_key),
                                                          str(format),
                                                          str(engine),
                                                          str(dimensions),
                                                          str(ignoreCoords),
                                                          str(is_ajax),
                                                          bgColor)
        return cache_key
Esempio n. 18
0
class FuelDistributionResource(ModelResource):
    author = fields.ForeignKey(UserResource, 'author', full=True)
    station = fields.ForeignKey(StationResource, 'station', full=True)
    car = fields.ForeignKey(CarResource, 'car', full=True, null=True)
    worker = fields.ForeignKey(WorkerResource, 'worker', full=True)
    waybills = fields.ToManyField(WayBillResource,
                                  'waybills',
                                  full_list=False,
                                  full=True,
                                  full_detail=True,
                                  null=True)
    outfits = fields.ToManyField(OutfitResource,
                                 'outfits',
                                 full_list=False,
                                 full=True,
                                 full_detail=True,
                                 null=True)
    regforms = fields.ToManyField(TractorRegFormResource,
                                  'regforms',
                                  full_list=False,
                                  full=True,
                                  full_detail=True,
                                  null=True)
    kind_full = fields.ApiField('get_kind_display')

    class Meta:
        queryset = models.FuelDistribution.objects.all()
        list_allowed_methods = ['get', 'post', 'put', 'delete']
        detail_allowed_methods = ['get', 'post', 'put', 'delete']
        resource_name = 'fuel-distributions'
        collection_name = 'fuel_distributions'
        always_return_data = True
        authorization = Authorization()
        authentication = MultiAuthentication(SessionAuthentication(),
                                             ApiKeyAuthentication())
        filtering = {
            'station': ALL_WITH_RELATIONS,
            'car': ALL_WITH_RELATIONS,
            'worker': ALL_WITH_RELATIONS,
            'waybills': ALL_WITH_RELATIONS,
            'outfits': ALL_WITH_RELATIONS,
            'regforms': ALL_WITH_RELATIONS,
            'author': ALL_WITH_RELATIONS,
            'date': ALL,
        }

    def post_list(self, request, **kwargs):
        data = json.loads(request.body.decode('utf-8'))
        data['author'] = request.user.pk
        form = prd_forms.FuelDistributionForm(data)
        if form.is_valid() and data.get('documents'):
            fuel_distribution = form.save()
            if fuel_distribution.kind == 'WB':
                for waybill in data['documents']:
                    fuel_distribution.waybills.add(
                        models.Waybill.objects.get(pk=waybill))
            elif fuel_distribution.kind == 'OF':
                for outfit in data['documents']:
                    fuel_distribution.outfits.add(
                        models.Outfit.objects.get(pk=outfit))
            elif fuel_distribution.kind == 'TR':
                for regform in data['documents']:
                    fuel_distribution.regforms.add(
                        models.TractorRegForm.objects.get(pk=regform))

            return self.create_response(request, {'id': fuel_distribution.pk})

        return self.error_response(request, form.errors)
Esempio n. 19
0
class WorkTimeTableResource(ModelResource):
    entries = fields.ManyToManyField(WorkTimeEntryResource,
                                     'entries',
                                     full_list=False,
                                     full=True,
                                     full_detail=True,
                                     null=True)
    outfits = fields.ManyToManyField(OutfitResource,
                                     'outfits',
                                     full_list=False,
                                     full=True,
                                     full_detail=True,
                                     null=True)
    regforms = fields.ManyToManyField(TractorRegFormResource,
                                      'regforms',
                                      full_list=False,
                                      full=True,
                                      full_detail=True,
                                      null=True)
    waybills = fields.ManyToManyField(WayBillResource,
                                      'waybills',
                                      full_list=False,
                                      full=True,
                                      full_detail=True,
                                      null=True)
    author = fields.ForeignKey(UserResource, 'author', full=True)
    responsible = fields.ForeignKey(WorkerResource, 'responsible', full=True)
    performer = fields.ForeignKey(WorkerResource, 'performer', full=True)
    organization = fields.ForeignKey(OrganizationResource,
                                     'organization',
                                     full=True,
                                     null=True)
    station = fields.ForeignKey(StationResource, 'station', full=True)
    departament_full = fields.ApiField('get_departament_display')

    class Meta:
        queryset = models.WorkTimeTable.objects.all()
        resource_name = 'worktime_tables'
        list_allowed_methods = ['get', 'post', 'put', 'delete']
        detail_allowed_methods = ['get', 'post', 'put', 'delete']
        collection_name = 'worktime_tables'
        authorization = Authorization()
        authentication = MultiAuthentication(SessionAuthentication(),
                                             ApiKeyAuthentication())
        filtering = {
            'id': ALL,
            'date': ALL,
            'created_date': ALL,
            'author': ALL_WITH_RELATIONS,
            'station': ALL_WITH_RELATIONS,
            'departament': ALL,
        }

    def post_list(self, request, **kwargs):
        data = json.loads(request.body.decode('utf-8'))
        data['author'] = request.user.pk
        errors = []
        form = prd_forms.WorkTimeTableForm(data)
        if form.is_valid() and data.get('__entries', None):
            table = form.save()
            for entry_data in data['__entries']:
                entry_form = prd_forms.WorkTimeEntryForm(entry_data)
                if entry_form.is_valid():
                    entry = entry_form.save()
                    table.entries.add(entry.pk)
                else:
                    errors.append(form.errors)
        else:
            errors.append(form.errors)

        if not len(errors) and data.get('__entries', None):
            table.save()
            return self.create_response(request, {'id': table.pk})
        else:
            return self.error_response(request, errors)
Esempio n. 20
0
class TablesResource(ModelResource):
    name = fields.ApiField('verbose_name')
    fields = fields.ToManyField(FieldsResource,
                                'fielddefinitions',
                                related_name='table',
                                full=True)

    class Meta:
        queryset = ModelDefinition.objects.all()
        authorization = get_table_auth()()
        authentication = SessionAuthentication()
        validation = FormValidation(form_class=TableForm)
        fields = ['name']

    def fill_obj(self, bundle):
        slug = translit_and_slugify(bundle.data['name'])
        bundle.obj.verbose_name = bundle.data['name']
        bundle.obj.app_label = tables_app.name
        if not bundle.obj.db_table:
            table_name = get_db_table_name(bundle.request.user,
                                           bundle.data['name'])[:63]
            bundle.obj.db_table = table_name
            bundle.obj.model = table_name
            bundle.obj.object_name = table_name

    def signal_payload(self, bundle):
        uri = self.get_resource_uri(bundle.obj)
        proxy_uri = TableProxyResource().uri_for_table(bundle.obj.pk)
        return dict(sender='api',
                    user=bundle.request.user,
                    md=bundle.obj,
                    uri=uri,
                    proxy_uri=proxy_uri)

    def emit_created_signal(self, bundle):
        table_created.send(**self.signal_payload(bundle))

    def emit_updated_signal(self, bundle):
        table_updated.send(**self.signal_payload(bundle))

    @transaction.atomic
    def save(self, bundle, *args, **kwargs):
        self.fill_obj(bundle)
        if bundle.obj.pk:
            #hack for renaming
            bundle.obj.model_class(force_create=True)
        return super(TablesResource, self).save(bundle, *args, **kwargs)

    def _create_auto_fields(self, bundle):
        FieldModel = dict(GEOMETRY_FIELD_TYPES).get(
            bundle.data.get('geometry_type'), DEFAULT_MD_GEOMETRY_FIELD_TYPE)
        kwargs = {
            'name': DEFAULT_MD_GEOMETRY_FIELD_NAME,
            'model_def': bundle.obj,
            'null': True,
            'blank': True,
        }
        if bundle.data.get('is_3d'):
            kwargs['dim'] = FieldModel.DIM_3D
        obj = FieldModel(**kwargs)
        bundle.data['fields'].append(Bundle(obj=obj))

    @transaction.atomic
    def obj_create(self, bundle, **kwargs):
        self._create_auto_fields(bundle)
        bundle = super(TablesResource, self).obj_create(bundle, **kwargs)
        self.emit_created_signal(bundle)
        logger.info('"%s" created table "%s"' %
                    (bundle.request.user, bundle.obj.db_table))
        return bundle

    @transaction.atomic
    def obj_update(self, *args, **kwargs):
        bundle = super(TablesResource, self).obj_update(*args, **kwargs)
        self.emit_updated_signal(bundle)
        logger.info('"%s" updated table "%s"' %
                    (bundle.request.user, bundle.obj.db_table))
        return bundle

    def obj_delete(self, bundle, **kwargs):
        super(TablesResource, self).obj_delete(bundle, **kwargs)
        logger.info('"%s" removed table "%s"' %
                    (bundle.request.user, bundle.obj.db_table))

    def save_m2m(self, bundle):
        #This is only place for create UserToTable entry. Because we need to do it after save MD, but before save m2m (fields),
        #because fields authorization checks UserToTable entry
        UserToTable.objects.get_or_create(md=bundle.obj,
                                          user=bundle.request.user)

        for f in bundle.data['fields']:
            f.obj.model_def = bundle.obj
        return super(TablesResource, self).save_m2m(bundle)

    def dehydrate(self, bundle):
        bundle.data['objects_uri'] = TableProxyResource().uri_for_table(
            bundle.obj.pk)
        return bundle
Esempio n. 21
0
class SearchAppResource(Resource):
    """Tastypie resource for simple-search"""
    hits = fields.ApiField(attribute='hits', null=True)

    class Meta:
        resource_name = 'simple-search'
        list_allowed_methods = ['get']
        serializer = default_serializer
        authentication = default_authentication
        object_class = SearchObject
        always_return_data = True

    def detail_uri_kwargs(self, bundle_or_obj):
        kwargs = {}
        if isinstance(bundle_or_obj, Bundle):
            kwargs['pk'] = bundle_or_obj.obj.id
        else:
            kwargs['pk'] = bundle_or_obj['id']

        return kwargs

    def get_object_list(self, request):
        user = request.user
        query_text = request.GET.get('query', None)
        if not user.is_authenticated:
            result_dict = simple_search_public_data(query_text)
            return [SearchObject(id=1, hits=result_dict)]
        groups = user.groups.all()
        index_list = ['experiments', 'dataset', 'datafile']
        ms = MultiSearch(index=index_list)

        query_exp = Q("match", title=query_text)
        query_exp_oacl = Q("term", objectacls__entityId=user.id) | \
            Q("term", public_access=100)
        for group in groups:
            query_exp_oacl = query_exp_oacl | \
                                 Q("term", objectacls__entityId=group.id)
        query_exp = query_exp & query_exp_oacl
        ms = ms.add(
            Search(index='experiments').extra(
                size=MAX_SEARCH_RESULTS,
                min_score=MIN_CUTOFF_SCORE).query(query_exp))

        query_dataset = Q("match", description=query_text)
        query_dataset_oacl = Q("term", **{'experiments.objectacls.entityId': user.id}) | \
            Q("term", **{'experiments.public_access': 100})
        for group in groups:
            query_dataset_oacl = query_dataset_oacl | \
                                 Q("term", **{'experiments.objectacls.entityId': group.id})
        ms = ms.add(
            Search(index='dataset').extra(
                size=MAX_SEARCH_RESULTS,
                min_score=MIN_CUTOFF_SCORE).query(query_dataset).query(
                    'nested', path='experiments', query=query_dataset_oacl))

        query_datafile = Q("match", filename=query_text)
        query_datafile_oacl = Q("term", **{'dataset.experiments.objectacls.entityId': user.id}) | \
            Q("term", **{'dataset.experiments.public_access': 100})
        for group in groups:
            query_datafile_oacl = query_datafile_oacl | \
                                 Q("term", **{'dataset.experiments.objectacls.entityId': group.id})
        ms = ms.add(
            Search(index='datafile').extra(
                size=MAX_SEARCH_RESULTS,
                min_score=MIN_CUTOFF_SCORE).query(query_datafile).query(
                    'nested',
                    path='dataset.experiments',
                    query=query_datafile_oacl))
        results = ms.execute()
        result_dict = {k: [] for k in ["experiments", "datasets", "datafiles"]}
        for item in results:
            for hit in item.hits.hits:
                if hit["_index"] == "dataset":
                    result_dict["datasets"].append(hit)

                elif hit["_index"] == "experiments":
                    result_dict["experiments"].append(hit)

                elif hit["_index"] == "datafile":
                    result_dict["datafiles"].append(hit)

        return [SearchObject(id=1, hits=result_dict)]

    def obj_get_list(self, bundle, **kwargs):
        return self.get_object_list(bundle.request)
Esempio n. 22
0
class TractorRegFormResource(ModelResource):
    event = fields.ForeignKey(OutfitEventResource, 'event', full=True)
    works = fields.ManyToManyField(TractorRegFormWorkResource,
                                   'works',
                                   full=True)
    organization = fields.ForeignKey(OrganizationResource,
                                     'organization',
                                     full=True)
    driver = fields.ForeignKey(WorkerResource, 'driver', full=True)
    car = fields.ForeignKey(CarResource, 'car', full=True)
    trailerman = fields.ForeignKey(WorkerResource,
                                   'trailerman',
                                   full=True,
                                   null=True)
    station = fields.ForeignKey(StationResource, 'station', full=True)
    brigadier = fields.ForeignKey(WorkerResource, 'brigadier', full=True)
    author = fields.ForeignKey(UserResource, 'author', full=True)
    departament_full = fields.ApiField('get_departament_display')
    fuel_distribution = fields.ForeignKey(
        'primary_docs.api.resources.FuelDistributionResource',
        'fuel_distribution',
        null=True)

    class Meta:
        queryset = models.TractorRegForm.objects.all()
        resource_name = 'tractor-regform'
        list_allowed_methods = ['get', 'post', 'put', 'delete']
        detail_allowed_methods = ['get', 'post', 'put', 'delete']
        collection_name = 'regforms'
        authorization = Authorization()
        authentication = MultiAuthentication(SessionAuthentication(),
                                             ApiKeyAuthentication())
        filtering = {
            'id': ALL,
            'date': ALL,
            'brigadier': ALL_WITH_RELATIONS,
            'driver': ALL_WITH_RELATIONS,
            'car': ALL_WITH_RELATIONS,
            'station': ALL_WITH_RELATIONS,
            'departament': ALL,
            'event': ALL_WITH_RELATIONS,
            'conducted': ALL,
            'fuel_distribution': ALL_WITH_RELATIONS,
        }

    def post_list(self, request, **kwargs):
        errors = []
        works_list = []
        data = json.loads(request.body.decode('utf-8'))
        data['author'] = request.user.pk
        for work in data['works']:
            work_form = prd_forms.TractorRegFormWorkForm(work)
            if work_form.is_valid():
                new_work = work_form.save()
                works_list.append(new_work.pk)
            else:
                errors.append(work_form.errors)
        data['works'] = works_list
        form = prd_forms.TractorRegFormForm(data)
        if form.is_valid():
            tractor_regform = form.save()
            tractor_regform.car.update_data(fuel=tractor_regform.fuel_ret)
            return self.get_detail(request, **{'pk': tractor_regform.pk})
        else:
            errors.append(form.errors)
        if len(errors):
            return self.error_response(request, errors)
Esempio n. 23
0
class OutfitResource(ModelResource):
    event = fields.ForeignKey(OutfitEventResource, 'event', full=True)
    works = fields.ToManyField(OutfitWorkResource, 'works', full=True)
    tables = fields.ToManyField(OutfitTableResource, 'tables', full=True)
    expenses = fields.ToManyField(
        'primary_docs.api.resources.OutfitExpenseResource',
        'expenses',
        full=True,
        null=True)
    postings = fields.ToManyField(
        'primary_docs.api.resources.OutfitPostingResource',
        'postings',
        full=True,
        null=True)
    brigadier = fields.ForeignKey(WorkerResource, 'brigadier', full=True)
    issued = fields.ForeignKey(WorkerResource, 'issued', full=True)
    accepted = fields.ForeignKey(WorkerResource, 'accepted', full=True)
    work_passed = fields.ForeignKey(WorkerResource, 'work_passed', full=True)
    work_accept = fields.ForeignKey(WorkerResource, 'work_accept', full=True)
    responsible = fields.ForeignKey(WorkerResource, 'responsible', full=True)
    calculated = fields.ForeignKey(WorkerResource, 'calculated', full=True)
    deposited = fields.ForeignKey(WorkerResource,
                                  'deposited',
                                  full=True,
                                  null=True)
    organization = fields.ForeignKey(OrganizationResource,
                                     'organization',
                                     full=True)
    station = fields.ForeignKey(StationResource, 'station', full=True)
    departament_full = fields.ApiField('get_departament_display')
    quality_display = fields.ApiField('get_quality_display')
    recycling_list = fields.ForeignKey(
        'primary_docs.api.resources.RecyclingListResource',
        'recycling_list',
        null=True)
    act_spisanya = fields.ForeignKey(
        'primary_docs.api.resources.ActSpisanyaResource',
        'act_spisanya',
        null=True)
    fuel_distribution = fields.ForeignKey(
        'primary_docs.api.resources.FuelDistributionResource',
        'fuel_distribution',
        null=True)
    total_fuel = fields.ApiField('get_total_fuel')

    class Meta:
        queryset = models.Outfit.objects.all()
        resource_name = 'outfit'
        list_allowed_methods = ['get', 'post', 'put', 'delete']
        detail_allowed_methods = ['get', 'post', 'put', 'delete']
        always_return_data = True
        collection_name = 'outfits'
        limit = 200
        authorization = Authorization()
        authentication = MultiAuthentication(SessionAuthentication(),
                                             ApiKeyAuthentication())
        filtering = {
            'id': ALL,
            'place': ALL,
            'date': ALL,
            'begin': ALL,
            'end': ALL,
            'event': ALL_WITH_RELATIONS,
            'brigadier': ALL_WITH_RELATIONS,
            'station': ALL_WITH_RELATIONS,
            'departament': ALL,
            'forestry': ALL,
            'conducted': ALL,
            'postings': ALL_WITH_RELATIONS,
            'expenses': ALL_WITH_RELATIONS,
            'recycling_list': ALL_WITH_RELATIONS,
            'total_fuel': ALL,
            'act_spisanya': ALL_WITH_RELATIONS,
            'fuel_distribution': ALL_WITH_RELATIONS,
        }

    def post_list(self, request, **kwargs):
        errors = []
        forms = dict(works=prd_forms.OutfitWorkForm,
                     tables=prd_forms.OutfitTableForm,
                     expenses=prd_forms.OutfitExpenseForm,
                     postings=prd_forms.OutfitPostingForm)
        lists = dict(
            works=[],
            tables=[],
            expenses=[],
            postings=[],
        )

        data = json.loads(request.body.decode('utf-8'))
        data['author'] = request.user.pk
        data['organization'] = request.user.organization.pk
        outfit_form = prd_forms.OutfitForm(data)
        if outfit_form.is_valid():
            outfit = outfit_form.save()

            for lst in lists:
                for obj in data[lst]:
                    obj['outfit'] = outfit.pk
                    form = forms[lst](obj)
                    if form.is_valid():
                        form.save()
                    else:
                        errors.append(form.errors)
        else:
            errors.append(outfit_form.errors)

        if len(errors):
            return self.error_response(request, errors)
        return self.create_response(request, {'id': outfit.pk})

    def apply_filters(self, request, applicable_filters):
        filtered = super(OutfitResource,
                         self).apply_filters(request, applicable_filters)
        if 'postings__isnull' in applicable_filters:
            filtered = filtered.distinct()
        if 'expenses__isnull' in applicable_filters:
            filtered = filtered.distinct()
        if 'gsm' in request.GET:
            if request.GET.get('gsm') == 'false':
                filtered = filtered.exclude(
                    expenses__material__category__name='ГСМ')
            elif request.GET.get('gsm') == 'true':
                filtered = filtered.filter(
                    expenses__material__category__name='ГСМ')
            filtered = filtered.distinct()
        return filtered
Esempio n. 24
0
class WayBillResource(ModelResource):
    event = fields.ForeignKey(OutfitEventResource,
                              'event',
                              full=True,
                              null=True)
    tasks = fields.ToManyField(DriverTaskResource, 'tasks', full=True)
    driver = fields.ForeignKey(WorkerResource, 'driver', full=True)
    dispatcher = fields.ForeignKey(WorkerResource,
                                   'dispatcher',
                                   full=True,
                                   null=True)
    car_took = fields.ForeignKey(WorkerResource, 'car_took', full=True)
    auto_accept = fields.ForeignKey(WorkerResource, 'auto_accept', full=True)
    auto_passed = fields.ForeignKey(WorkerResource, 'auto_passed', full=True)
    check_out_allow = fields.ForeignKey(WorkerResource,
                                        'check_out_allow',
                                        full=True)
    car = fields.ForeignKey(CarResource, 'car', full=True)
    organization = fields.ForeignKey(OrganizationResource,
                                     'organization',
                                     full=True)
    station = fields.ForeignKey(StationResource, 'station', full=True)
    departament_full = fields.ApiField('get_departament_display')
    type_display = fields.ApiField('get_type_of_display')
    author = fields.ForeignKey(UserResource, 'author', full=True)
    fuel_distribution = fields.ForeignKey(
        'primary_docs.api.resources.FuelDistributionResource',
        'fuel_distribution',
        null=True)

    class Meta:
        queryset = models.Waybill.objects.all()
        limit = 200
        resource_name = 'waybill'
        list_allowed_methods = ['get', 'post', 'put', 'delete']
        detail_allowed_methods = ['get', 'post', 'put', 'delete']
        always_return_data = True
        collection_name = 'waybills'
        authorization = Authorization()
        authentication = MultiAuthentication(SessionAuthentication(),
                                             ApiKeyAuthentication())
        filtering = {
            'number': ALL,
            'date': ALL,
            'station': ALL_WITH_RELATIONS,
            'departament': ALL,
            'car': ALL_WITH_RELATIONS,
            'is_completed': ALL,
            'conducted': ALL,
            'driver': ALL_WITH_RELATIONS,
            'fuel_issued': ALL,
            'fuel_distribution': ALL_WITH_RELATIONS,
        }

    def put_detail(self, request, **kwargs):
        errors = []
        try:
            data = json.loads(request.body.decode('utf-8'))
        except Exception as e:
            return self.error_response(request, e)
        if data.get('id'):
            try:
                waybill = models.Waybill.objects.get(id=data['id'])
            except Exception as e:
                return self.error_response(request, e)
            data['author'] = request.user.pk
            for task in data['tasks']:
                task['waybill'] = waybill.pk
                task_form = prd_forms.DriverTaskForm(task)
                if task_form.is_valid():
                    new_task, created = models.DriverTask.objects.get_or_create(
                        **task_form.cleaned_data)
                else:
                    errors.append(task_form.errors)
            form = prd_forms.WayBillForm(data, instance=waybill)
            if form.is_valid():
                waybill = form.save()
                if waybill.is_completed:
                    waybill.complete()
                else:
                    waybill.car.available = False
                    waybill.car.save()
                return self.create_response(request, {'id': waybill.pk})
            else:
                errors.append(form.errors)
        return self.error_response(request, errors)

    def post_list(self, request, **kwargs):
        errors = []
        try:
            data = json.loads(request.body.decode('utf-8'))
        except Exception as e:
            return self.error_response(request, e)
        data['author'] = request.user.pk
        form = prd_forms.WayBillForm(data)
        if form.is_valid():
            waybill = form.save()

            for task in data['tasks']:
                task['waybill'] = waybill.pk
                task_form = prd_forms.DriverTaskForm(task)
                if task_form.is_valid():
                    new_task = task_form.save()
                else:
                    errors.append(task_form.errors)

            if waybill.is_completed:
                waybill.complete()
            else:
                waybill.car.available = False
                waybill.car.save()
            return self.create_response(request, {'id': waybill.pk})
        else:
            errors.append(form.errors)
        return self.error_response(request, errors)