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)
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())
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()
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)
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())
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
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])
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
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())
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
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
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, 'Не достаточно прав!')
class AgoraPermissionsResource(TinyAgoraResource): agora_permissions = fields.ApiField() def dehydrate_agora_permissions(self, bundle): return bundle.obj.get_perms(bundle.request.user)
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
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
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
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
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)
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)
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
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)
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)
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
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)