【问题标题】:How to build a queryset in a specific order in Django如何在 Django 中按特定顺序构建查询集
【发布时间】:2020-02-29 19:37:22
【问题描述】:

我正在尝试列出用户的个人资料。我想以这样一种方式列出它们,即具有相同用户城市的个人资料应该首先出现,然后下一个优先级应该是州,然后是国家/地区,最后是其余的个人资料。这是我尝试过的。 型号

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() 相同

请帮助我。提前致谢

【问题讨论】:

    标签: python django django-models orm django-queryset


    【解决方案1】:

    您需要QuerySetorder_by 方法,该方法根据传递的参数对对象进行排序;这是在数据库上完成的:

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

    编辑:

    如果您想按登录用户的citystatecountry 名称进行排序,您可以在 Python 级别执行此操作,使用 sorted 和自定义的 key 可调用:

    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,
    )
    

    在数据库级别上做同样的事情,使用CaseWhen 有一个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 ...)。

    【讨论】:

    • 给出字段错误无法将关键字“current_user”解析为字段。这是 current_user current_user = Profile.objects.filter(user=request.user)
    • @ArunLaxman 将current_user 替换为您拥有的实际字段名称;如果是user,则使用Profile.objects.order_by('user__city'),依此类推。
    • 仍然错误。我已经用更多细节更新了这个问题。我正在尝试按登录用户个人资料的城市、州、国家/地区的顺序对查询集进行排序
    • 嗯..这会返回一个列表。有没有办法将它作为查询集检索?
    • @ArunLaxman 您要将这些数据传递到哪里?除非您对此进行进一步的类似查询集的操作,否则非常好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-06
    • 2019-04-12
    • 1970-01-01
    • 2016-08-28
    • 2017-11-19
    相关资源
    最近更新 更多