Как построить набор запросов в определенном порядке в Django - PullRequest
1 голос
/ 04 ноября 2019

Я пытаюсь перечислить профили пользователей. Я хочу перечислить их так, чтобы сначала приходили профили с тем же городом пользователя, затем следующим приоритетом должно быть государство, затем страна и, наконец, остальные профили. Это то, что я пытался. модель

class Profile(models.Model):
    uuid = UUIDField(auto=True)
    user = models.OneToOneField(User)
    country = models.ForeignKey(Country, null=True)
    state = models.ForeignKey(State, null=True)
    city = models.ForeignKey(City, null=True)

views.py current_user = Profile.objects.filter (user = request.user)

profiles_city = Profile.objects.filter(city=current_user.city)
profiles_state = Profile.objects.filter(state=current_user.state)
profiles_country = Profile.objects.filter(country=current_user.country)
profiles_all = Profile.objects.all()
profiles = (profiles_city | profiles_state | profiles_country | profiles_all).distinct()

Но он дает тот же результат, что и Profile.objects.all ()

Пожалуйста, помогите мне. заранее спасибо

1 Ответ

3 голосов
/ 04 ноября 2019

Вам необходим order_by метод QuerySet, который упорядочивает объекты на основе переданных параметров;это делается в базе данных:

Profile.objects.order_by(
    'current_user__city',
    'current_user__state',
    'current_user__country',
)

Редактировать:

Если вы хотите отсортировать по city, state и countryИмена вошедшего в систему пользователя, вы можете сделать это на уровне Python, используя sorted, и пользовательский key callable:

from functools import partial


def get_sort_order(profile, logged_in_profile):
    # This is a simple example, you need to filter against
    # the city-state-country combo to match precisely. For
    # example, multiple countries can have the same city/
    # state name.

    if logged_in_profile.city == profile.city: 
        return 1 
    if logged_in_profile.state == profile.state: 
        return 2 
    if logged_in_profile.country == profile.country: 
        return 3
    return 4 

logged_in_profile = request.user.profile  # logged-in user's profile
get_sort_order_partial = partial(get_sort_order, logged_in_profile=logged_in_profile)

sorted(
    Profile.objects.all(),
    key=get_sort_order_partial,
)

Делая то же самое на уровне базы данных, используяCase и When, чтобы иметь Python if - elif - else подобную конструкцию:

from django.db.models import Case, When, IntegerField

Profile.objects.order_by( 
    Case( 
        When(city=logged_in_profile.city, then=1), 
        When(state=logged_in_profile.state, then=2), 
        When(country=logged_in_profile.country, then=3), 
        default=4, 
        output_field=IntegerField(), 
    ) 
)         

Это приведет к созданию набора запросов, а также будет иметь дополнительное преимущество:все операции будут выполняться в базе данных (SELECT CASE WHEN ...).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...