There is a Clan model that has a CharField (string) title field. I need to sort all the objects of this model according to this field, but according to the given condition - it is necessary to sort the objects according to the frequency of meeting this substring in the title (title) of the clan (Clan)

The following method sorts by default, as I remember in lexicographical order:

Clan.objects.order_by('title') 

I need to sort all models of the clan by the frequency of meeting a given substring in them -> in this case, let this string be 'clan' . That is, it should be something like this (but it does not work, in this case a double underderskor indicates sorting by the model field, after which it is used - and we mean the line)

 Clan.objects.order_by("title__contains='clan'") 

I would also like to know how to sort / filter clan objects by the absence of a given substring in them

  • According to the frequency of the meeting in them given a substring? That is something like ['Clan spam clan eggs clan', 'clan qwerty clan', 'clan foo', 'bar'] ? - Sergey Gornostaev
  • Well, yes, that in the resulting list were the names of all the clans, sorted by the frequency of the meeting in them given a substring. Accordingly, if the title contains the word 'clan' it should be in the list completely, and not just the part with this word. And if there is no word in the title, it should still be on the list, only somewhere at the end - fedotsoldier
  • So far, there is an idea of ​​only merging two lists: the first is a filtered queryset by the meeting condition in the name of a given substring, the second is all elements of the original queryset that are not found in the first list. I now wanted to know if there is already a ready-made sorting function - fedotsoldier

1 answer 1

I hope that I understood the conditions correctly.

When saving each record, I would automatically count the number of words in the title and put this value in a separate field, "word_occurrence", for example.

Then sorting would be very easy to do with a simple query:

 Clan.objects.order_by('word_occurrence') 

To do this, rewrite the save() method of the model. Example from documentation

If interested, then I will try to add sample code later.

The advantage is that you do not need to build complex queries or count something every time you query the database.

As for custom sorting. I do not know how to make such a request using Django ORM. But you can get a list of objects and sort it using the sorted () function

Example with a list:

 clan_titles = ['111', 'clan vvv clan', 'clan'] # Функция для подсчета количества слов "clan" в строке def word_count(clan_title): return sum([1 for word in clan_title.split() if word == 'clan']) # Просто проверяем, что считает правильно for title in clan_titles: print(word_count(title)) # Используем функцию подсчета слов в качестве ключа для сортировки srtd = sorted(clan_titles, key=word_count, reverse=True) print(srtd) 

I do not have the opportunity now to test the same with querysets. But it might look like this:

 clans_qs = list(Clan.objects.all()) def word_count(clan_obj): return sum([1 for word in clan_obj.title.split() if word == 'clan']) srtd = sorted(clan_qs, key=word_count, reverse=True) print(srtd) 
  • Thanks for the suggested method, but I needed to find out if there is any built-in function in Django. In addition, your method is not fully functional - a good search query will result not just by dividing words into groups: a substring is included in the name / not included. That is, first the names must appear in which there are three substrings "clan" at once, then two, then one and after that the other results must be sorted and the other results - the names which include the substring "cla" must go earlier than those in which is found only "cl". And at the end there are matches only with one "c" - fedotsoldier