J'ai une exigence, c'est-à-dire que du côté client, j'obtiendrai un tableau d'objets qui auront des noms de champ, des conditions de filtrage et des valeurs de filtrage comme celle-ci.
Exemple de tableau d'objets:
def assign_filter_condition(self, request, filter_condition, field_name, filter_value): if filter_condition == "contains": kwargs = { '{0}__icontains'.format(field_name): filter_value } return kwargs ...
et je dois filtrer en fonction de toutes les conditions ci-dessus. Considérez que j'ai un modèle avec le nom Book et les champs qui sont là dans le tableau des objets (ie book_name, book_category, book_author, book_price). Pour filter_condition, j'ai écrit une fonction qui compare la filter_condition et assigne l'API Django queryset. Par exemple.
[ {field_name: "book_name", filter_condition: "contains", filter_value: "some book name"}, {field_name: "book_category", filter_condition: "not_equal", filter_value: "category value"}, {field_name: "book_author", filter_condition: "starts_with", filter_value: "authoer name"}, {field_name: "book_price", filter_condition: "equal", filter_value: 100} ]
Ici, je ne sais pas comment appliquer des conditions d'exclusion et NON de requête.
Je ne comprends vraiment pas comment écrire la logique de cela. Quelqu'un peut-il s'il vous plaît aider avec la logique.
Merci d'avance.
3 Réponses :
Vous pouvez le faire en utilisant le déballage de dict. Veuillez noter que vous n'avez pas besoin de conditions donc soyez un dict, le tableau est suffisant. Le code suivant vous mènera là où vous voulez.
conditions = [ ("book_name", "contains", "some book name"), ("book_category", "not_equal", "category value"), ("book_author", "starts_with", "authoer name"), ("book_price", "equal", 100) ] def get_filter(values): name,condition,value = values key = f"{name}__{condition}" return key, value filters = dict(map(get_filter,conditions)) qs = qs.filter(**filters)
Après avoir parcouru quelques publications StackOverflow, j'ai compris la logique. Voici donc la logique.
def get_filter(self, field_name, filter_condition, filter_value): # thanks to the below post # https://stackoverflow.com/questions/310732/in-django-how-does-one-filter-a-queryset-with-dynamic-field-lookups # the idea to this below logic is very similar to that in the above mentioned post if filter_condition.strip() == "contains": kwargs = { '{0}__icontains'.format(field_name): filter_value } return Q(**kwargs) if filter_condition.strip() == "not_equal": kwargs = { '{0}__iexact'.format(field_name): filter_value } return ~Q(**kwargs) if filter_condition.strip() == "starts_with": kwargs = { '{0}__istartswith'.format(field_name): filter_value } return Q(**kwargs) if filter_condition.strip() == "equal": kwargs = { '{0}__iexact'.format(field_name): filter_value } return Q(**kwargs) if filter_condition.strip() == "not_equal": kwargs = { '{0}__iexact'.format(field_name): filter_value } return ~Q(**kwargs) def get(self, request): # getting the array of objects data to filter. The array of objects data # example is in the question filter_data = request.query_params.getlist('filterData[]') all_books = Books.objects.all() # Creating initial Q object filter_objects = Q() # Looping through the array of objects for data in filter_data: # The main part. Calling get_filter and passing the filter object data. filter_objects &= self.get_filter( data["fieldName"], data["filterCondition"], data["filterValue"]) filtered_data = all_books.filter(filter_objects)
J'espère que ça aide quelqu'un. :)
créer une classe qui hérite de DjangoFilterBackends et utiliser à la place de ceci
class MyFilterBackend(DjangoFilterBackend): def get_filterset_kwargs(self, request, queryset, view): data = request.query_params data._mutable = True for item in data: try: print(item) field = getattr(queryset.model, item) field: DeferredAttribute data[item] = [x for x in list(field.field.choices) if x[1] == data[item]][0][0] except: pass return { 'data': request.query_params, 'queryset': queryset, 'request': request, }
Je ne connais pas votre cas d'utilisation ou les conditions dans lesquelles vous travaillez, mais vous devriez au moins avoir une raison de refuser d'utiliser Django-filter django-filter.readthedocs.io/en/master/index.html
@ nigel222 L'exemple de tableau d'objets ci-dessus que j'ai mentionné dans la question, tout comme je vais envoyer une requête à DRF. puisque vous pouvez voir la condition du filtre et le nom du champ changera. Donc, je ne sais pas comment m'y attaquer ou écrire la logique dans le backend.
OK, Django-filter n'est probablement pas le bon outil pour votre utilisation (DRF). Espérons que le commentaire informera les personnes qui arrivent ici à la recherche d'un "filtre dynamique" ou autre.