简体   繁体   English

加入外键表 Django QuerySet

[英]Join Foreign Key Table Django QuerySet

I'm learning Django Queryset, but i get confused when I want to use queryset Django to join table, instead of using Django raw query I want to learn Django queryset. I'm learning Django Queryset, but i get confused when I want to use queryset Django to join table, instead of using Django raw query I want to learn Django queryset.

In my case I want to fetch RiskIdentification data.就我而言,我想获取 RiskIdentification 数据。

class Activity(models.Model):
    act_name           =  models.CharField(max_length = 40)
    created_at          =   models.DateTimeField(auto_now_add=True)
    updated_at          =   models.DateTimeField(auto_now = True)
  

class ActivityDetail(models.Model):
    act_risk_assessment = models.ForeignKey(RiskAssessment, on_delete=models.CASCADE)
    act          = models.ForeignKey(Activity, on_delete=models.CASCADE)
    created_at          = models.DateTimeField(auto_now_add=True)
    updated_at          = models.DateTimeField(auto_now = True)


class RiskAssessment(models.Model):
    name                = models.CharField(max_length = 30)
    date                = models.DateField()
    email_date          = models.DateField()
    created_at          = models.DateTimeField(auto_now_add=True)
    updated_at          = models.DateTimeField(auto_now = True)

class  RiskIdentification (models.Model):
  
    idn_description          = models.CharField(max_length = 30)
    idn_risk_assessment     = models.ForeignKey(RiskAssessment, on_delete=models.CASCADE)
    risk_type             = models.ForeignKey(RiskType, on_delete=models.CASCADE)

class RiskMitigation (models.Model):
  
    mtg_description         = models.CharField(max_length = 30)
    identification_risk     = models.ForeignKey(RiskIdentification, on_delete=models.CASCADE)

It will look like this in raw query在原始查询中看起来像这样

SELECT  idn_description
FROM RiskAsessment RA 
JOIN RiskIdentification RI on RA.id = RI.idn_riskAsessment 
JOIN ActivityDetail AD on AD.act_risk_assessment = RA.id 
JOIN Activity A on A.id = AD.act

Please help me how Django query will looks like, and describe it.请帮助我 Django 查询的外观并描述它。

A queryset equivalent to your SQL is:与您的 SQL 等效的查询集是:

qs = (RiskIdentification.objects
      .exclude(idn_risk_assessment__activity_detail_set=None)
      .values('idn_description'))

It is usually not necassary to restrict output fields by .values(...) .通常不需要通过.values(...)来限制 output 字段。

It is always useful in a question to express the expected result also in human language although it could be not as accurate as SQL or queryset, but there is less risk of mistake or misconception.在问题中用人类语言表达预期结果总是有用的,尽管它可能不如 SQL 或查询集准确,但出错或误解的风险较小。

An advantage of writing querysets instead of raw SQL is that the correctness of queryset can be verified by compiling to SQL and reading.编写查询集而不是原始 SQL 的一个优点是可以通过编译为 SQL 并读取来验证查询集的正确性。 Many mistakes can be found by this, while the correctness of raw SQL can't be checked no independent way:这样可以发现很多错误,而原始SQL的正确性无法通过独立的方式进行检查:

>>> print(str(queryset.query))
SELECT ... FROM ...

I'm trying to guess your intention from your SQL:我试图从您的 SQL 中猜测您的意图:

I want to know all idn_description from RiskIdentification that are used in any ActivityDetail .我想知道RiskIdentification中用于任何ActivityDetail的所有idn_description I want to see them so many time how much they are used in any ActivityDetail .我想多次看到它们在任何ActivityDetail中使用了多少。

(The part of SQL JOIN Activity A on A.id = AD.act is useless if no Activity field is used for output or for WHERE conditions and the database has been created correctly with integrity rules (automatically by Django) then a missing or invalid value is always rejected by database because that foreign key is required.) (如果没有 Activity 字段用于 output 或 WHERE 条件并且数据库已使用完整性规则正确创建(由 Django 自动创建),则 SQL JOIN Activity A on A.id = AD.act的部分是无用的,然后丢失或无效值总是被数据库拒绝,因为需要该外键。)

It is useful to define a related_name for act_risk_assessment field, eg "activity_details", or expect for now that it is the default name activity_detail_set for now.act_risk_assessment字段定义一个act_risk_assessment很有用,例如“activity_details”,或者现在期望它是默认名称activity_detail_set

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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