coderholic / django-cities

Countries and cities of the world for Django projects
MIT License
920 stars 374 forks source link

City QuerySet with alternative names and needed language code #176

Closed vladimirmyshkovski closed 6 years ago

vladimirmyshkovski commented 6 years ago

Checklist

Steps to reproduce

    def get_queryset(self):

        qs = City.objects.prefetch_related('alt_names')

        if self.q:

            qs = qs.filter(alt_names__name__istartswith=self.q, alt_names__language_code='ru')

        return qs

Realizing that I really need a query in alternative names, I did this:

    def get_queryset(self):

        qs = AlternativeName.objects.filter(language_code=self.request.LANGUAGE_CODE).all()

        if self.q:

            qs = qs.filter(city__isnull=False, name__istartswith=self.q).all()[:10]

        return qs

But now I get alternative names with a prefix in the form of the language code.

If you save the form, I will have to receive the city of this alternative name (since the model is connected with the city).

But how do I get alternative names without a prefix in the form of a language code?

I want to get a list of cities in the language I need.

Expected behavior

<QuerySet [<City: Митарлам>, <City: Миттерзиль>, <City: Миттерзилль>, <City: Мистель-Бах>, <City: Михельдорф>

Or, in the worst case scenario:

<QuerySet [<AlternativeName: Митарлам >, <AlternativeName: Миттерзиль >, <AlternativeName: Миттерзилль >

Actual behavior

Result of first reproduce:

<QuerySet [<City: Mehtar Lām>, <City: Mittersill>, <City: Mittersill>, <City: Mistelbach>, <City: Micheldorf in Oberösterreich>, <City: Micheldorf in Oberösterreich>, <City: Millicent>, <City: Mildura>, <City: Mincivan>, <City: Mingelchaur>, <City: Mirzāpur>, <City: Mirandopólis>, <City: Miranda>, <City: Miracema>, <City: Mimoso do Sul>, <City: Myory>, <City: Minsk>, <City: Mikashevichy>, <City: Milton>, <City: Mirabel>, '...(remaining elements truncated)...']> Result of second reproduce:

<QuerySet [<AlternativeName: Митарлам (ru)>, <AlternativeName: Миттерзиль (ru)>, <AlternativeName: Миттерзилль (ru)>, <AlternativeName: Мистель-Бах (ru)>, <AlternativeName: Михельдорф (Верхняя Австрия) (ru)>, <AlternativeName: Михельдорф (ru)>, <AlternativeName: Миллисент (ru)>, <AlternativeName: Милдьюра (ru)>, <AlternativeName: Миндживан (ru)>, <AlternativeName: Мингечаур (ru)>]>

blag commented 6 years ago

Your queryset is correct, but the __str__ function on the model is returning information you do not want. In your presentation layer, instead of relying on the internal __str__ function to convert the model instances to strings, use the name attribute directly.

Alternatively, you can use .values_list('name', flat=True) if you want to return just the list of names without the language code.

Closing, but please reopen if I have misunderstood the actual issue here.

vladimirmyshkovski commented 6 years ago

Best of all, it would be to return the desired alt_names in the queryset of the City. AlternativeName filtered by get_language.

I understand how to do it to one city, but I do not understand how to do it within the query_set of cities.