【问题标题】:django // Raw query must include the primary keydjango // 原始查询必须包含主键
【发布时间】:2020-05-09 06:03:28
【问题描述】:

Python 3.6

Django 2.2.3

玛丽亚数据库


我正在使用 Django 开发一个显示各种统计信息的 Web 程序。

由“inspectdb”从现有的 MariaDB 数据库创建“models.py”。

由于来自许多表的混合查询,我正在尝试使用“原始”查询

但是,出现以下错误。

django.db.models.query_utils.InvalidQuery: Raw query must include the primary key

Mariadb 表

# table : user
uid(int(10), primary, auto_increment)
email(varchar(100))
created_at(timestamp)

# table : user_logs
seq(int(11), primary, auto_increment)
uid(int(10))
acct_type(tinyint(2))
log_type(varchar(20))
created_at(timestamp)

#query
SELECT
       years,
       months,
       sum(download) AS download,
       sum(countin) AS user_regist,
       sum(countout) AS user_login
FROM (
        SELECT
               YEAR(DATE_ADD(created_at, INTERVAL 9 HOUR)) AS years,
               MONTH(DATE_ADD(created_at, INTERVAL 9 HOUR)) AS months,
               count(1) AS `countin`,0  AS `countout`, 0 AS 'download'
        FROM user `in`
        WHERE (
                  DATE_ADD(created_at, INTERVAL 9 HOUR) >= '2019-09-01 00:00:00' AND
                  DATE_ADD(created_at, INTERVAL 9 HOUR) < '2020-01-20 00:00:00')
        GROUP BY `years`, `months`
        UNION
        SELECT
               YEAR(DATE_ADD(created_at, INTERVAL 9 HOUR)) AS years,
               MONTH(DATE_ADD(created_at, INTERVAL 9 HOUR)) AS months,
               0 `countin`,
               count(1)  AS `countout`,
               0 AS 'download'
        FROM user_logs `out`
        WHERE (
                  acct_type = 1 AND
                  log_type = 'login' AND
                  DATE_ADD(created_at, INTERVAL 9 HOUR) >= '2019-09-01 00:00:00' AND
                  DATE_ADD(created_at, INTERVAL 9 HOUR) < '2020-01-20 00:00:00')
        GROUP BY `years`, `months`
) `regist_and_login_monthly`
GROUP BY years, months;

查询结果

models.py

class User(models.Model):
    uid = models.AutoField(primary_key=True)
    email = models.CharField(max_length=100, blank=True, null=True)
    created_at = models.DateTimeField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'user'
        ordering = ['-created_at']


class UserLogs(models.Model):
    seq = models.AutoField(primary_key=True)
    uid = models.PositiveIntegerField(primary_key=True)
    acct_type = models.IntegerField(blank=True, null=True)
    log_type = models.CharField(max_length=20, blank=True, null=True)
    created_at = models.DateTimeField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'user_logs'
        ordering = ['-created_at']

views.py

# same as query
user_monthly_status = User.objects.raw(
        '''
        SELECT
               years,
               months,
               sum(download) AS download,
               sum(countin) AS user_regist,
               sum(countout) AS user_login
        FROM (
                SELECT
                       YEAR(DATE_ADD(created_at, INTERVAL 9 HOUR)) AS years,
                       MONTH(DATE_ADD(created_at, INTERVAL 9 HOUR)) AS months,
                       count(1) AS `countin`,0  AS `countout`, 0 AS 'download'
                FROM user `in`
                WHERE (
                          DATE_ADD(created_at, INTERVAL 9 HOUR) >= '2019-09-01 00:00:00' AND
                          DATE_ADD(created_at, INTERVAL 9 HOUR) < '2020-01-20 00:00:00')
                GROUP BY `years`, `months`
                UNION
                SELECT
                       YEAR(DATE_ADD(created_at, INTERVAL 9 HOUR)) AS years,
                       MONTH(DATE_ADD(created_at, INTERVAL 9 HOUR)) AS months,
                       0 `countin`,
                       count(1)  AS `countout`,
                       0 AS 'download'
                FROM user_logs `out`
                WHERE (
                          acct_type = 1 AND
                          log_type = 'login' AND
                          DATE_ADD(created_at, INTERVAL 9 HOUR) >= '2019-09-01 00:00:00' AND
                          DATE_ADD(created_at, INTERVAL 9 HOUR) < '2020-01-20 00:00:00')
                GROUP BY `years`, `months`
        ) `regist_and_login_monthly`
        GROUP BY years, months;
        '''
    )

当我搜索此错误时,人们说在每个“选择”中输入“1 作为 id”或“每个表的主列”,但发生了同样的错误。

我该怎么办?

【问题讨论】:

    标签: python mysql django mariadb


    【解决方案1】:

    我一填完问题,我就解决它并分享结果。

    提示来自 https://docs.djangoproject.com/en/2.2/topics/db/sql/#deferring-model-fields

    我为每个“选择”添加了一个“表”的“PK 列”,并将其中一个放入第一个“选择”中。

    user_monthly_status = User.objects.raw(
            '''
            SELECT
                  uid, # add !!!!!!!
                   years,
                   months,
                   sum(download) AS download,
                   sum(countin) AS user_regist,
                   sum(countout) AS user_login
            FROM (
                    SELECT
                            uid,# add !!!!!!!
                           YEAR(DATE_ADD(created_at, INTERVAL 9 HOUR)) AS years,
                           MONTH(DATE_ADD(created_at, INTERVAL 9 HOUR)) AS months,
                           count(1) AS `countin`,0  AS `countout`, 0 AS 'download'
                    FROM user `in`
                    WHERE (
                              DATE_ADD(created_at, INTERVAL 9 HOUR) >= '2019-09-01 00:00:00' AND
                              DATE_ADD(created_at, INTERVAL 9 HOUR) < '2020-01-20 00:00:00')
                    GROUP BY `years`, `months`
                    UNION
                    SELECT
                           seq,# add !!!!!!!!
                           YEAR(DATE_ADD(created_at, INTERVAL 9 HOUR)) AS years,
                           MONTH(DATE_ADD(created_at, INTERVAL 9 HOUR)) AS months,
                           0 `countin`,
                           count(1)  AS `countout`,
                           0 AS 'download'
                    FROM user_logs `out`
                    WHERE (
                              acct_type = 1 AND
                              log_type = 'login' AND
                              DATE_ADD(created_at, INTERVAL 9 HOUR) >= '2019-09-01 00:00:00' AND
                              DATE_ADD(created_at, INTERVAL 9 HOUR) < '2020-01-20 00:00:00')
                    GROUP BY `years`, `months`
            ) `regist_and_login_monthly`
            GROUP BY years, months;
            '''
        )
    

    【讨论】:

    • 现在,您的GROUP BY 无效,因为uid 不能从years, months 派生。
    猜你喜欢
    • 2014-01-21
    • 1970-01-01
    • 1970-01-01
    • 2021-10-30
    • 2021-02-19
    • 1970-01-01
    • 2017-06-29
    • 2018-11-14
    • 2010-10-20
    相关资源
    最近更新 更多