def dynamic_type(): if input_flag and not nested_field: return DjangoListField( ID, required=is_required(field) if input_flag == "create" else not field.null, ) else: _type = registry.get_type_for_model(model, for_input=input_flag) if not _type: return elif input_flag and nested_field: return DjangoListField(_type) elif _type._meta.filter_fields or _type._meta.filterset_class: return DjangoFilterListField( _type, required=is_required(field) if input_flag == "create" else not field.null, filterset_class=_type._meta.filterset_class, ) else: return DjangoListField( _type, required=is_required(field) if input_flag == "create" else not field.null, )
def dynamic_type(): if input_flag and not nested_field: return DjangoListField(graphene.ID) else: _type = registry.get_type_for_model(model, for_input=input_flag) # get list type of the object if it has one if hasattr(_type, "get_list_type"): _type = _type.get_list_type() if not _type: return elif input_flag and nested_field: return DjangoListField(_type) elif _type._meta.filter_fields or _type._meta.filterset_class: # return nested relations as a field with pagination return DjangoNestableListObjectPermissionsField( _type, required=is_required(field) and input_flag == "create", filterset_class=_type._meta.filterset_class, ) else: return DjangoListField(_type, required=is_required(field) and input_flag == "create")
def dynamic_type(): if input_flag and not nested_fields: return DjangoListField(ID) _type = registry.get_type_for_model(model, for_input=input_flag) if not _type: return if _type._meta.filter_fields and input_flag: return DjangoFilterListField(_type) return DjangoListField(_type)
def dynamic_type(): if input_flag and not nested_fields: return DjangoListField(ID, required=is_required(field) and input_flag == 'create') _type = registry.get_type_for_model(model, for_input=input_flag) if not _type: return if _type._meta.filter_fields: return DjangoFilterListField(_type, required=is_required(field) and input_flag == 'create') return DjangoListField(_type, required=is_required(field) and input_flag == 'create')
def dynamic_type(): if input_flag: return _type = registry.get_type_for_model(model) if not _type: return return DjangoListField(_type)
class SummitEventNode(DjangoObjectType): speaker_count = Int() attendee_count = Int() unique_metric_count = Int() unique_metrics = DjangoListField(MetricRowType, metricType=String(), fromDate=String(), toDate=String(), search=String()) def resolve_speaker_count(self, info): return self.presentation.speakers.count() if hasattr(self, 'presentation') and self.presentation is not None else 0 def resolve_attendee_count(self, info): return self.presentation.attendees.count() if hasattr(self, 'presentation') and self.presentation is not None else 0 def resolve_unique_metric_count(self, info): metrics = self.metrics.filter(type="EVENT", event__id=self.id) distinct_members = metrics.values("member__id").distinct() return distinct_members.count() def resolve_unique_metrics(self, info, metricType='', fromDate="", toDate="", search=""): type_filter = "Met.Type = 'EVENT' AND MetE.SummitEventID = {id}".format(id=self.id) return getUniqueMetrics(self, type_filter, fromDate, toDate, search, self.summit.id) class Meta: model = SummitEvent filter_fields = ['id', 'title', 'summit__id', 'published', 'sponsors__id']
def convert_django_field_with_choices(field, registry=None, input_flag=None, nested_field=False): choices = getattr(field, 'choices', None) if choices: meta = field.model._meta name = '{}_{}_{}'.format(meta.object_name, field.name, 'Enum') if input_flag: name = '{}_{}'.format(name, input_flag) name = to_camel_case(name) enum = registry.get_type_for_enum(name) if not enum: choices = list(get_choices(choices)) named_choices = [(c[0], c[1]) for c in choices] named_choices_descriptions = {c[0]: c[2] for c in choices} class EnumWithDescriptionsType(object): @property def description(self): return named_choices_descriptions[self.name] enum = Enum(name, list(named_choices), type=EnumWithDescriptionsType) registry.register_enum(name, enum) if type(field).__name__ == 'MultiSelectField': return DjangoListField( enum, description=field.help_text or field.verbose_name, required=is_required(field) and input_flag == 'create' ) return enum( description=field.help_text or field.verbose_name, required=is_required(field) and input_flag == 'create' ) return convert_django_field(field, registry, input_flag, nested_field)
class UserCreateMutation(Mutation): """ This class creates new users """ class Arguments: # The input arguments for this mutation username = String(required=True) email = String(required=True) password = String(required=True) first_name = String() last_name = String() new_user = DjangoListField(UserNode) def mutate(self, info, username, email, password, first_name, last_name): # validate input information first try: validate_email(email) validate_password(password) user = User.objects.create_user(username, email, password, first_name=first_name, last_name=last_name) except (ValidationError, IntegrityError) as message: raise GraphQLError(str(message)) else: # if ok return new user return UserCreateMutation(new_user=[user])
class SummitNode(DjangoObjectType): unique_metrics = DjangoListField(MetricRowType, metricType=String(), fromDate=String(), toDate=String(), search=String()) def resolve_unique_metrics(self, info, metricType="", fromDate="", toDate="", search=""): type_filter = "Met.Type = '{type}'".format(type=metricType) if metricType else '' return getUniqueMetrics(self, type_filter, fromDate, toDate, search, self.id) class Meta: model = Summit filter_fields = ['id', 'title', 'metrics', 'order_extra_questions']
def __init_subclass_with_meta__(cls, model=None, results_field_name=None, pagination=None, only_fields=(), exclude_fields=(), filter_fields=None, queryset=None, **options): assert is_valid_django_model(model), ( 'You need to pass a valid Django Model in {}.Meta, received "{}".' ).format(cls.__name__, model) if not DJANGO_FILTER_INSTALLED and filter_fields: raise Exception("Can only set filter_fields if Django-Filter is installed") assert isinstance(queryset, QuerySet) or queryset is None, ( 'The attribute queryset in {} needs to be an instance of ' 'Django model queryset, received "{}".' ).format(cls.__name__, queryset) results_field_name = results_field_name or 'results' baseType = get_global_registry().get_type_for_model(model) if not baseType: baseType = object_type_factory(DjangoObjectType, new_model=model, new_exclude_fields=exclude_fields, new_filter_fields=filter_fields) filter_fields = filter_fields or baseType._meta.filter_fields if pagination: result_container = pagination.get_pagination_field(baseType) else: global_paginator = graphql_api_settings.DEFAULT_PAGINATION_CLASS if global_paginator: global_paginator = global_paginator() description = '{} list, paginated by {}'.format(model.__name__, global_paginator.__name__) result_container = global_paginator.get_field(baseType, description=description) else: result_container = DjangoListField(baseType) _meta = DjangoObjectOptions(cls) _meta.model = model _meta.queryset = queryset _meta.baseType = baseType _meta.results_field_name = results_field_name _meta.filter_fields = filter_fields _meta.exclude_fields = exclude_fields _meta.only_fields = only_fields _meta.fields = OrderedDict([ (results_field_name, result_container), ('count', Field(Int, name='totalCount', required=True, description="Total count of matches elements")) ]) super(DjangoListObjectType, cls).__init_subclass_with_meta__(_meta=_meta, **options)
class SponsorNode(DjangoObjectType): company_name = String() unique_metrics = DjangoListField(MetricRowType, metricType=String(), fromDate=String(), toDate=String(), search=String()) def resolve_unique_metrics(self, info, metricType='', fromDate="", toDate="", search=""): type_filter = "Met.Type = 'SPONSOR' AND MetS.SponsorID = {id}".format(id=self.id) return getUniqueMetrics(self, type_filter, fromDate, toDate, search, self.summit.id) def resolve_company_name(self, info): return self.company.name class Meta: model = Sponsor filter_fields = ['id', 'company', 'type']
class UserUpdateMutation(Mutation): """ This class updates exciting users by ID """ class Arguments: # The input arguments for this mutation id = ID(required=True) email = String() password = String() username = String() first_name = String() last_name = String() updated_user = DjangoListField(UserNode) def mutate(self, info, id, email, password, **kwargs): try: # get a user which is not a superadmin user = User.objects.get(id=id, is_superuser=False) # check pass if password: validate_password(password) user.set_password(password) # check email if email: validate_email(email) user.email = email # set other user attributes for key, value in kwargs.items(): setattr(user, key, value) # save user.save() except (ValidationError, IntegrityError, ObjectDoesNotExist) as message: raise GraphQLError(str(message)) else: return UserUpdateMutation(updated_user=[user])
def __init_subclass_with_meta__( cls, model=None, registry=None, results_field_name=None, pagination=None, only_fields=(), exclude_fields=(), filter_fields=None, queryset=None, filterset_class=None, **options, ): assert is_valid_django_model(model), ( 'You need to pass a valid Django Model in {}.Meta, received "{}".' ).format(cls.__name__, model) if not DJANGO_FILTER_INSTALLED and filter_fields: raise Exception( "Can only set filter_fields if Django-Filter is installed") assert isinstance(queryset, QuerySet) or queryset is None, ( "The attribute queryset in {} needs to be an instance of " 'Django model queryset, received "{}".').format( cls.__name__, queryset) results_field_name = results_field_name or "results" baseType = get_global_registry().get_type_for_model(model) if not baseType: factory_kwargs = { "model": model, "only_fields": only_fields, "exclude_fields": exclude_fields, "filter_fields": filter_fields, "filterset_class": filterset_class, "pagination": pagination, "queryset": queryset, "registry": registry, "skip_registry": False, } baseType = factory_type("output", DjangoObjectType, **factory_kwargs) filter_fields = filter_fields or baseType._meta.filter_fields if pagination: result_container = pagination.get_pagination_field(baseType) else: global_paginator = graphql_api_settings.DEFAULT_PAGINATION_CLASS if global_paginator: assert issubclass( global_paginator, BaseDjangoGraphqlPagination ), ('You need to pass a valid DjangoGraphqlPagination class in {}.Meta, received "{}".' ).format(cls.__name__, global_paginator) global_paginator = global_paginator() result_container = global_paginator.get_pagination_field( baseType) else: result_container = DjangoListField(baseType) _meta = DjangoObjectOptions(cls) _meta.model = model _meta.queryset = queryset _meta.baseType = baseType _meta.results_field_name = results_field_name _meta.filter_fields = filter_fields _meta.exclude_fields = exclude_fields _meta.only_fields = only_fields _meta.filterset_class = filterset_class _meta.fields = OrderedDict([ (results_field_name, result_container), ( "count", Field( Int, name="totalCount", description="Total count of matches elements", ), ), ]) super(DjangoListObjectType, cls).__init_subclass_with_meta__(_meta=_meta, **options)
class SpeakerNode(DjangoObjectType): presentations = DjangoListField(PresentationNode, summitId=Int()) presentation_count = Int() presentation_titles = String(summitId=Int()) feedback_count = Int(summitId=Int()) feedback_avg = Float(summitId=Int()) full_name = String() emails = String() current_job_title = String() current_company = String() def resolve_presentations(self, info, summitId): return self.presentations.filter(summit_id=summitId) def resolve_presentation_count(self, info): return self.presentations.count() def resolve_presentation_titles(self, info, summitId=0): presentations = list(self.presentations.filter(summit_id=summitId).values("title")) presentation_titles = ' || '.join(x.get("title") for x in presentations) return presentation_titles def resolve_feedback_count(self, info, summitId=0): queryset = EventFeedback.objects.filter(event__presentation__speakers__id=self.id) if (summitId): queryset = queryset.filter(event__summit__id=summitId) return queryset.count() def resolve_feedback_avg(self, info, summitId=0): queryset = EventFeedback.objects.filter(event__presentation__speakers__id=self.id) if (summitId): queryset = queryset.filter(event__summit__id=summitId) result = queryset.aggregate(models.Avg('rate')) avgRate = result.get('rate__avg') if avgRate: return round(avgRate, 2) else: return 0 def resolve_full_name(self, info): return self.full_name() def resolve_emails(self, info): emails = [] try: emails.append(self.member.email) except: pass try: emails.append(self.registration.email) except: pass return ', '.join(x for x in emails) def resolve_current_job_title(self, info): job_title = '' try: if self.title: job_title = self.title else: current_affiliation = self.member.affiliations.filter(current=True).first() if current_affiliation: job_title = current_affiliation.job_title except: pass return job_title def resolve_current_company(self, info): company = '' try: if self.company: company = self.company else: current_affiliation = self.member.affiliations.filter(current=True).first() if current_affiliation: company = current_affiliation.organization.name except: pass return company class Meta(object): model = Speaker
class PresentationNode(DjangoObjectType): speaker_count = Int() speaker_names = String() speaker_emails = String() speaker_companies = String() attendee_count = Int() rsvp_count = Int() feedback_count = Int() feedback_avg = Float() tag_names = String() youtube_id = String() external_url = String() all_media_uploads = String() media_upload_videos = String() media_upload_slides = String() unique_metrics = DjangoListField(String) unique_metric_count = Int() def resolve_speaker_count(self, info): return self.speakers.count() def resolve_speaker_names(self, info): speaker_names = ', '.join(x.full_name() for x in self.speakers.all()) if self.has_moderator() and self.moderator is not None: speaker_names = speaker_names + ', ' + self.moderator.full_name() return speaker_names def resolve_speaker_emails(self, info): speakers = self.speakers.exclude(member__email__isnull=True).all() speaker_emails = ', '.join(str(x.full_name() + ' (' + x.email() + ')') for x in speakers) if hasattr(self, 'moderator') and self.moderator is not None: speaker_emails = speaker_emails + ', ' + self.moderator.full_name() + ' (' + self.moderator.email() + ')' return speaker_emails def resolve_speaker_companies(self, info): speakers = self.speakers.exclude(company__isnull=True).all() speaker_companies = ', '.join(str(x.full_name() + " (" + x.company + ")") for x in speakers) if hasattr(self, 'moderator') and self.moderator is not None: speaker_companies = speaker_companies + ', ' + self.moderator.full_name() + ' (' + self.moderator.company + ')' return speaker_companies def resolve_attendee_count(self, info): return self.attendees.count() def resolve_rsvp_count(self, info): return self.rsvps.count() def resolve_feedback_count(self, info): return self.feedback.count() def resolve_feedback_avg(self, info): rateAvg = self.feedback.aggregate(models.Avg('rate')) return round(rateAvg.get('rate__avg', 0), 2) def resolve_tag_names(self, info): tags = list(self.tags.values()) tag_names = ', '.join(x.get("tag") for x in tags) return tag_names def resolve_youtube_id(self, info): video = self.materials.exclude(presentationvideo__isnull=True).first() if video and video.presentationvideo: return video.presentationvideo.youtube_id else: return 'N/A' def resolve_external_url(self, info): video = self.materials.exclude(presentationvideo__isnull=True).first() if video and video.presentationvideo: return video.presentationvideo.external_url else: return 'N/A' def resolve_all_media_uploads(self, info): materials = list( self.materials .exclude(mediaupload__isnull=True) .values("mediaupload__filename", "mediaupload__type__name")) files = ', '.join( m.get("mediaupload__filename") + " (" + m.get("mediaupload__type__name") + ")" for m in materials) return files def resolve_media_upload_videos(self, info): materials = list( self.materials .exclude(mediaupload__isnull=True) .filter(mediaupload__type__name__icontains="video") .values("mediaupload__filename")) videos = ', '.join(m.get("mediaupload__filename") for m in materials) return videos def resolve_media_upload_slides(self, info): materials = list( self.materials .exclude(mediaupload__isnull=True) .filter(mediaupload__type__name__icontains="slide") .values("mediaupload__filename")) slides = ', '.join(m.get("mediaupload__filename") for m in materials) return slides def resolve_unique_metrics(self, info): metrics = self.metrics.filter(type="EVENT", event__id=self.id) distinct_members = metrics.order_by("member__first_name").values("member__first_name", "member__last_name", "member__id").distinct() return [ str(m.get("member__first_name") + " " + m.get("member__last_name") + " (" + str(m.get("member__id")) + ")") for m in distinct_members] def resolve_unique_metric_count(self, info): metrics = self.metrics.filter(type="EVENT", event__id=self.id) distinct_members = metrics.values("member__id").distinct() return distinct_members.count() class Meta: model = Presentation
class Query: availability_levels = DjangoListField(AvailabilityLevelType) boat_types = DjangoListField(BoatTypeType) berth = relay.Node.Field(BerthNode) berths = DjangoConnectionField( BerthNode, harbor=graphene.ID(), pier=graphene.ID(), min_width=graphene.Float(), min_length=graphene.Float(), is_available=graphene.Boolean(), is_invoiceable=graphene.Boolean(), description= "If filtering by both pier and harbor and the pier does not belong to the given harbor, " "will return an empty list of edges." "\n\n**Requires permissions** to query `leases` field. " "Otherwise, everything is available", ) pier = relay.Node.Field(PierNode) piers = DjangoFilterConnectionField( PierNode, min_berth_width=graphene.Float(), min_berth_length=graphene.Float(), for_application=graphene.ID(), description= "`Piers` allows to filter, among other fields, by `minBerthWidth` and `minBerthLength`.\n\n" "This filter is recommended over the filter in `berths`, because it yields better results. " "It will only return the `pier`s which contain `berth`s matching the filter, when the other will " "return all the available `pier`s with an empty list of `berth`s in case there's no matches.\n\n" "If you use both filters in the same query, you might get some empty `berth` results where both " "queries overlap.\n\n" "To filter the piers suitable for an application, you can use the `forApplication` argument. " "**Requires permissions** to access applications." "\n\nErrors:" "\n* Filter `forApplication` with a user without enough permissions" "\n * Filter `forApplication` combined with either dimension (width, length) filter", ) harbor = relay.Node.Field(HarborNode) harbor_by_servicemap_id = graphene.Field( HarborNode, servicemap_id=graphene.String(required=True)) harbors = DjangoFilterConnectionField(HarborNode, servicemap_ids=graphene.List( graphene.String)) winter_storage_place = relay.Node.Field(WinterStoragePlaceNode) winter_storage_places = DjangoConnectionField(WinterStoragePlaceNode) winter_storage_place_type = relay.Node.Field(WinterStoragePlaceTypeNode) winter_storage_place_types = DjangoConnectionField( WinterStoragePlaceTypeNode) winter_storage_section = relay.Node.Field(WinterStorageSectionNode) winter_storage_sections = DjangoFilterConnectionField( WinterStorageSectionNode) winter_storage_area = relay.Node.Field(WinterStorageAreaNode) winter_storage_areas = DjangoFilterConnectionField(WinterStorageAreaNode) def resolve_availability_levels(self, info, **kwargs): return AvailabilityLevel.objects.all() def resolve_boat_types(self, info, **kwargs): return BoatType.objects.all() def resolve_berths(self, info, harbor: GlobalID = None, pier: GlobalID = None, min_width: Decimal = 0, min_length: Decimal = 0, **kwargs): if pier and harbor: raise VenepaikkaGraphQLError( _("Cannot pass both pier and harbor filters")) filters = Q() if harbor: filters &= Q(pier__harbor_id=from_global_id(harbor, HarborNode)) if pier: filters &= Q(pier_id=from_global_id(pier, PierNode)) if min_width: filters &= Q(berth_type__width__gte=min_width) if min_length: filters &= Q(berth_type__length__gte=min_length) if "is_available" in kwargs: filters &= Q(is_available=kwargs.get("is_available")) if "is_invoiceable" in kwargs: filters &= Q(is_invoiceable=kwargs.get("is_invoiceable")) return info.context.berth_loader.load_many( keys=Berth.objects.filter(filters).values_list("id", flat=True)) def resolve_piers(self, info, **kwargs): return resolve_piers(info, **kwargs) def resolve_harbor_by_servicemap_id(self, info, **kwargs): return Harbor.objects.filter( servicemap_id=kwargs.get("servicemap_id")).first() def resolve_harbors(self, info, **kwargs): # TODO: optimize this further # currently, still results in too many DB queries # although, django-graphene might introduce fixes for this # so, check the state of this against a newer version later servicemap_ids = kwargs.get("servicemap_ids", None) qs = (Harbor.objects.filter(servicemap_id__in=servicemap_ids) if servicemap_ids else Harbor.objects.all()) return qs.prefetch_related( "translations", Prefetch( "piers", queryset=Pier.objects.prefetch_related( Prefetch("berths", queryset=Berth.objects.all())), ), "piers__suitable_boat_types", ).select_related("availability_level", "municipality") def resolve_winter_storage_places(self, info, **kwargs): return WinterStoragePlace.objects.prefetch_related( "winter_storage_section__area__translations", "winter_storage_section__area__availability_level__translations", "winter_storage_section__area__municipality__translations", ).select_related( "winter_storage_section", "winter_storage_section__area", "winter_storage_section__area__availability_level", "winter_storage_section__area__municipality", ) def resolve_winter_storage_sections(self, info, **kwargs): return WinterStorageSection.objects.prefetch_related( "places", "area__translations", "area__availability_level__translations", "area__municipality__translations", ).select_related("area", "area__availability_level", "area__municipality") def resolve_winter_storage_areas(self, info, **kwargs): # TODO: optimize this further # currently, still results in too many DB queries # although, django-graphene might introduce fixes for this # so, check the state of this against a newer version later return WinterStorageArea.objects.prefetch_related( "translations", Prefetch( "sections", queryset=WinterStorageSection.objects.prefetch_related( Prefetch("places", queryset=WinterStoragePlace.objects.all())), ), ).select_related("availability_level", "municipality")