标签: django-orm

Django 从所有查询中排除字段

我正在 Heroku 上运行 Django,具有零停机功能。这意味着在部署期间,同一数据库上运行两个版本的代码(旧版和新版)。这就是为什么我们需要避免任何向后不兼容的迁移。

是否有可能从给定模型上的 Django 查询中排除字段?

假设我们有一个模型(版本 1):

class Person(models.Model):
    name = models.CharField()
    address = models.TextField()
Run Code Online (Sandbox Code Playgroud)

在未来的某个时间,我们希望将地址移动到单独的表中。我们知道我们不应该删除旧代码要工作的字段,因此 Person 模型可能看起来像(版本 2):

class Person(models.Model):
    name = models.CharField()
    address = models.ForeignKey(Address)
    _address = models.TextField(db_name='address')
Run Code Online (Sandbox Code Playgroud)

这样,如果旧代码查询地址,即使数据库已迁移,它也会从 Person 表中获取地址(这将是旧值,但假设这不是一个大问题)。

现在我如何才能安全地删除_address字段?如果我们部署版本 3 并_address删除字段,则版本 2 的代码仍将尝试_address在 select 上获取,即使它没有在任何地方使用,并且会失败并出现“无此类列”异常。

有没有办法防止这种情况,并在版本 2 的代码中将某些字段标记为“不可获取”?所以版本 2 不会删除字段,但不会再获取它,版本 3 将删除字段。

python django database-migration django-orm django-migrations

2
推荐指数
1
解决办法
7459
查看次数

如何使用 Django ORM 将注释字符串转换为 Bool

我的问题如下。有一个请求

Thread.objects.all().annotate(is_marked=Count('mark', Q(mark__username='gou')))

在 SQL 中它看起来像这样

SELECT "api_thread"."id",
       "api_thread"."conference_id",
       "api_thread"."title",
       "api_thread"."description",
       "api_thread"."is_closed",
       "api_thread"."is_hidden",
       "api_thread"."is_pinned",
       "api_thread"."has_voting",
       "api_thread"."creator_uid",
       "api_thread"."created_at",
       "api_thread"."expired",
       COUNT("api_thread_mark"."user_id") FILTER (WHERE "auth_user"."username" = 'gou') AS "is_marked"
FROM "api_thread"
         LEFT OUTER JOIN "api_thread_mark" ON ("api_thread"."id" = "api_thread_mark"."thread_id")
         LEFT OUTER JOIN "auth_user" ON ("api_thread_mark"."user_id" = "auth_user"."id")
GROUP BY "api_thread"."id"
Run Code Online (Sandbox Code Playgroud)

我需要做什么才能将数字转换为布尔值。在 SQL 中它看起来像

COUNT("api_thread_mark"."user_id") FILTER (WHERE "auth_user"."username" = 'gou') > 0 AS "is_marked"
Run Code Online (Sandbox Code Playgroud)

django postgresql django-orm django-queryset django-annotate

2
推荐指数
1
解决办法
1323
查看次数

是否可以使用 Django 的 ORM 查询表而无需在模型中为其创建类?

这个问题是不言自明的。我有一个数据库,我知道其中有一个名为 的表Customer,但该表不存在于models.py. 因此,我不能简单地执行以下操作:

customers = Customer.objects.filter(age__gte=25)
Run Code Online (Sandbox Code Playgroud)

是否可以编写此查询并获取数据,而无需为其创建类models.py并迁移整个项目?

django django-orm

2
推荐指数
1
解决办法
863
查看次数

如何排除具有空 prefetch_lated 字段的行

prefetch_related用过Prefetch

prefetch_qs = Offer.objects.filter(price__gt=1000)
prefetch = Prefetch('offers', queryset=prefetch_qs)
Run Code Online (Sandbox Code Playgroud)

如何排除包含空报价的行?它不起作用,因为注释计算了所有报价(未在 中过滤prefetch):

filtered_qs = Product.objects.annotate(
    offers_count=Count('offers')
).filter(
    offers_count__gt=0
).prefetch_related(
    prefetch      
)
Run Code Online (Sandbox Code Playgroud)

python django django-orm

2
推荐指数
1
解决办法
1386
查看次数

Django 反向查找以获取最新版本

我有一个模型结构如下,

ACTIVE_STATUS = ['waiting', 'loading', 'starting', 'running', 'stopping']
INACTIVE_STATUS = ['stopped', 'finished', 'failed', 'lost']
ALL_STATUS = ACTIVE_STATUS + INACTIVE_STATUS


class Task(models.Model):
    name = models.CharField(max_length=20)


class Job(models.Model):
    task = models.ForeignKey(Task, related_name='jobs')
    timestamp = models.DateTimeField(auto_now_add=True)
    status = models.CharField(choices=zip(ALL_STATUS, ALL_STATUS), max_length=20)
Run Code Online (Sandbox Code Playgroud)

如何将“最新时间戳及其状态”注释到任务查询集中?

我已经设法获得最新的时间戳,

Task.objects.annotate(latest_ts=models.Max(models.F('job__timestamp')))
Run Code Online (Sandbox Code Playgroud)

那么,怎样才能得到对应的status呢?

更新1

该查询的最大目的是对Task查询集进行排序

  1. 零工作(比如说Task.objects.filter(job__isnull=True)
  2. 最新作业=='正在运行'

更新2

用于获取排序查询集的 TaskManager 类

class TaskManager(models.Manager):

    def get_queryset(self):
        qs = super().get_queryset()
        latest_job = models.Max(models.F('job__timestamp'))

        latest_status = models.Subquery(
            Job.objects.filter(
                task_id=models.OuterRef('pk')
            ).values('status').order_by('-timestamp')[:1]
        )

        qs_order = models.Case(
            models.When(job__isnull=True, then=models.Value(2)),
            models.When(latest_status='running', then=models.Value(1)), …
Run Code Online (Sandbox Code Playgroud)

python django django-orm

2
推荐指数
1
解决办法
809
查看次数

使用 Django 查询集获取每个组的前 n 条记录

我有一个如下表所示的模型,

create table `mytable`
(
  `person` varchar(10),
  `groupname` int,
  `age` int
);
Run Code Online (Sandbox Code Playgroud)

我想从每组中选出 2 个最年长的人。原始的 SQL 问题和答案在这里StackOverflow,有效的解决方案之一是

SELECT
    person,
    groupname,
    age
FROM
(
    SELECT
        person,
        groupname,
        age,
        @rn := IF(@prev = groupname, @rn + 1, 1) AS rn,
        @prev := groupname
    FROM mytable
    JOIN (SELECT @prev := NULL, @rn := 0) AS vars
    ORDER BY groupname, age DESC, person
) AS T1
WHERE rn <= 2
Run Code Online (Sandbox Code Playgroud)

您也可以在此处检查 SQL 输出以及SQLFIDLE

我只是想知道如何在 Django 视图中将这个查询实现为查询集。

django django-orm

2
推荐指数
1
解决办法
1403
查看次数

一天和一周的总用户数

我想获得一天和一周内加入的用户总数,我尝试如下

member_in_day = User.objects.exclude(is_staff=True)\
    .annotate(day=TruncDay('date_joined')).values('date_joined') \
    .annotate(total_members=Count('date_joined')) \
    .order_by('-date_joined')
member_in_week = User.objects.exclude(is_staff=True)\
    .annotate(week=TruncWeek('date_joined')).values('date_joined') \
    .annotate(total_members=Count('date_joined')) \
    .order_by('-date_joined')
Run Code Online (Sandbox Code Playgroud)

该模型是用户,我得到的两个查询的输出是相同的,而不是一天它也给出其他查询集。如何将今天的总计和本周的总计添加到模板中

<QuerySet [{'date_joined': datetime.datetime(2020, 12, 28, 16, 47, 40, 509134, tzinfo=<UTC>), 'total_members': 1}, {'date_joined': datetime.datetime(2020, 12, 23, 11, 8, 19, 241355, tzinfo=<UTC>), 'total_members': 1}, {'date_joined': datetime.datetime(2020, 12, 23, 11, 6, 14, 20673, tzinfo=<UTC>), 'total_members': 1}, {'date_joined': datetime.datetime(2020, 12, 22, 9, 25, 45, 14632, tzinfo=<UTC>), 'total_members': 1}, {'date_joined': datetime.datetime(2020, 12, 22, 9, 24, 25, 819750, tzinfo=<UTC>), 'total_members': 1}, {'date_joined': datetime.datetime(2020, 12, 20, 12, 7, …
Run Code Online (Sandbox Code Playgroud)

django django-orm django-queryset

2
推荐指数
1
解决办法
551
查看次数

如何用天数计算注释 Django 查询?

如何使用自创建记录以来的天数计算来注释表的 Django 查询?

我想根据优先级乘以记录创建以来的天数的组合指标来排序表。

为了获得日期注释,我正在尝试执行以下操作:

qs = qs.annotate(days=(ExtractDay(Now()-F('created_datetime'))))
Run Code Online (Sandbox Code Playgroud)

但是,这会引发错误:

django.db.utils.ProgrammingError: function pg_catalog.timezone(unknown, interval) does not exist
LINE 1: ...EMENT_TIMESTAMP() - "myapp_mymodel"."created_timestamp") AT TIME ZO...
                                                         ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
Run Code Online (Sandbox Code Playgroud)

我尝试过类似的Extract()功能,但它也会产生类似的错误。

我究竟做错了什么?

表面上,我只需要执行与 Django 等效的操作EXTRACT(DAY FROM NOW() - created_timestamp),但 Django 的Extract(..., 'days')ExtractDay()函数似乎与 PostgreSQL 的等效项实际上并不匹配。

看起来 Django 的返回值Now()和我的时间戳字段都是时区感知时间戳,那么为什么数据库会抱怨类型不兼容呢?

我的数据库后端是 PostgreSQL。

python django django-orm

2
推荐指数
1
解决办法
1431
查看次数

Django ORM:两个日期之间的天数 timedelta 差异

在此输入图像描述

我有一个数据库表,表示与给定产品相关的费用。

这些费用,假设它们是每天的,有一个from_date(开始日期)和to_date(结束日期)。to_date可以为空,因为这些费用可能仍在继续。

给定 2 个 Pythondatetimestart_dateend_date我需要在 ORM 中生成 期间花费的总费用my_product

>>> start_date
datetime.datetime(2021, 8, 20, 0, 0)

>>> end_date
datetime.datetime(2021, 9, 21, 0, 0)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,预期输出应该是:

(-104 * (days between 08/20 and 08/25)) + (-113 * (days between 08/26 and 09/21)
Run Code Online (Sandbox Code Playgroud)

这是我到目前为止所得到的:

(
my_product.income_streams
    .values("product")
    .filter(type=IncomeStream.Types.DAILY_EXPENSE)
    .filter(add_to_commission_basis=True)
    .annotate(period_expenses=Case(
        When(Q(from_date__lte=start_date) & Q(to_date__lte=end_date),
 then=ExpressionWrapper( start_date - F('to_date'), output_field=IntegerField()))
    ), # Other When cases...
)
) # Sum all period_expenses results …
Run Code Online (Sandbox Code Playgroud)

django django-orm

2
推荐指数
1
解决办法
2037
查看次数

使用循环过滤查询集

我有初始查询集,我循环这个

stats = {}
queryset = Item.objects.all()
for sub in Subject.objects.all():
        stats[str(sub.id)] = queryset.filter(subjects=sub.id).count()
Run Code Online (Sandbox Code Playgroud)

如何在不经常点击数据库的情况下做到这一点?

django django-models django-orm

1
推荐指数
1
解决办法
1103
查看次数