简体   繁体   中英

django // Raw query must include the primary key

Python 3.6

Django 2.2.3

Mariadb


I am developing a web program using Django that displays various statistics.

Created "models.py" by "inspectdb" from an existing MariaDB database.

I'm trying to use "Raw" queries because of mixed queries from many tables

However, the following error occurs.

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

Mariadb tables

# 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;

query resulit

查询结果

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;
        '''
    )

When I searched for this error, people says put '1 as id' or 'each table's primary colunm' in each 'Select', but the same error occurred.

What should I do?

As soon as I fill out the question, I solve it and share the result.

hint from https://docs.djangoproject.com/en/2.2/topics/db/sql/#deferring-model-fields

I added a 'PK column' of 'table' to each 'Select' and put one of them into first 'Select'.

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;
        '''
    )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM