Django 3.2 - raw-SQL-Query with same table (Model)
Django 3.2 - raw-SQL-Query with same table (Model)
我们已经将一些数据库表从我们的生产环境迁移到 django ORM 并在 django 之外自动同步这些表。 → 到目前为止效果很好,但我们在 django 中遇到问题无法将这些表(模型)正确地相互连接。
models.py
class SsdaSdgadr(models.Model):
sda_sdgid = models.ForeignKey(SsdgSendung, on_delete=models.CASCADE, blank=True, null=True)
sda_satid = models.CharField(max_length=4, blank=True, null=True)
sda_adrid = models.ForeignKey(SadrAdresse, on_delete=models.CASCADE, blank=True, null=True)
sda_ref = models.CharField(max_length=35, blank=True, null=True)
sda_termbis = models.DateField(blank=True, null=True)
sda_termvon = models.DateField(blank=True, null=True)
class Meta:
db_table = 'ssda_sdgadr'
unique_together = (('sda_sdgid', 'sda_satid'),)
class SsdgSendung(models.Model):
sdg_sdgid = models.CharField(primary_key=True, max_length=30)
sdg_konz = models.CharField(max_length=12, blank=True, null=True)
class Meta:
db_table = 'ssdg_sendung'
class SadrAdresse(models.Model):
adr_adrid = models.IntegerField(primary_key=True)
adr_name1 = models.CharField(max_length=35, blank=True, null=True)
adr_name2 = models.CharField(max_length=35, blank=True, null=True)
class Meta:
db_table = 'sadr_adresse'
示例数据
SsdaSdgadr:
sdg_sdgid
sda_satid
sda_adrid
sda_ref
sda_termvon
sda_termbis
BL-1237781-BL-1
IV
169550
'00123/4539999'
''
''
BL-1237781-BL-1
SU
555555
''
01.12.2021
02.12.2021
BL-1237781-BL-1
CN
999999
'00123'
02.12.2021
13.12.2021
views.py
我使用了以下原始 SQL
Sendungen = SsdaSdgadr.objects.raw('''
SELECT
IV.id,
IV.sda_sdgid_id,
IV.sda_ref,
SU.id,
SU.sda_adrid_id as ABS,
SU.sda_termvon,
CN.id,
CN.sda_adrid_id as EMPF,
CN.sda_termbis
FROM
ssda_sdgadr IV
INNER JOIN ssdg_sendung on sdg_sdgid = IV.sda_sdgid_id
INNER JOIN ssda_sdgadr SU on SU.sda_sdgid_id = IV.sda_sdgid_id and SU.sda_satid="SU"
INNER JOIN ssda_sdgadr CN on CN.sda_sdgid_id = IV.sda_sdgid_id and CN.sda_satid="CN"
WHERE IV.sda_satid="IV"
GROUP BY
IV.id,
IV.sda_sdgid_id,
IV.sda_ref,
SU.id,
SU.sda_adrid_id,
SU.sda_termvon,
CN.id,
CN.sda_adrid_id,
CN.sda_termbis
ORDER BY
sdg_datum desc
''')
...
response = render(request, 'cust/home.html', {
'Sendungen': Sendungen,
})
return response
模板上的结果适用于字段“SU.sda_termvon”和“CN.sda_termbis”,但不适用于字段“sda_adrid”(→ 只有显示 IV.sda_adrid_id 的结果。
模板代码
{% for la_item in Sendungen %}
<tr>
<td>{{ la_item.sda_sdgid.sdg_sdgid }}</td>
<td>{{ la_item.sda_ref }}</td> <!-- IV.sda_ref OKAY -->
<td>{{ la_item.sda_adrid.adr_adrid }}</td> <!-- is IV.sda_adrid NOT OKAY -->
<td>{{ la_item.sda_adrid.adr_adrid }}</td> <!-- is IV.sda_adrid NOT OKAY -->
<td>{{ la_item.sda_termvon|date }}</td> <!-- SU.sda_termvon OKAY -->
<td>{{ la_item.sda_termbis|date }}</td> <!-- CN.sda_termbis OKAY -->
</tr>
{% endfor %}
如何访问模板上的结果“CN.sda_adrid_id”和“SU.sda_adrid_id”?
→ 看起来 ORM 解释 raw-SQL 与数据库不同:
数据库结果和预期结果应如下所示:
sda_sdgid_id
IV.sda_ref
SU.sda_adrid_id
CN.sda_adrid
SU.termvon
CN.termbis
BL-1237781-BL-1
1920192/4530210220/0881760357
555555
999999
01.12.2021
13.12.2021
我的实际结果是这样的:
sda_sdgid_id
IV.sda_ref
IV.sda_adrid_id
IV.sda_adrid_id
SU.termvon
CN.termbis
BL-1237781-BL-1
1920192/4530210220/0881760357
169550
169550
01.12.2021
13.12.2021
我使用了这个解决方法(模型 属性 用于“SsdaSdgadr”),它给了我想要的结果:
models.py
class SsdaSdgadr(models.Model):
sda_sdgid = models.ForeignKey(SsdgSendung, on_delete=models.CASCADE, blank=True, null=True)
sda_satid = models.CharField(max_length=4, blank=True, null=True)
sda_adrid = models.ForeignKey(SadrAdresse, on_delete=models.CASCADE, blank=True, null=True)
sda_ref = models.CharField(max_length=35, blank=True, null=True)
sda_termbis = models.DateField(blank=True, null=True)
sda_termvon = models.DateField(blank=True, null=True)
class Meta:
db_table = 'ssda_sdgadr'
unique_together = (('sda_sdgid', 'sda_satid'),)
@property
def is_adr_su(self):
return SsdaSdgadr.objects.filter(sda_sdgid = self.sda_sdgid, sda_satid = "SU")
@property
def is_adr_cn(self):
return SsdaSdgadr.objects.filter(sda_sdgid = self.sda_sdgid, sda_satid = "CN")
views.py
Sendungen = SsdaSdgadr.objects.filter(Q(sda_satid__in=["IV"])).order_by('-sda_sdgid__sdg_datum')
...
response = render(request, 'cust/home.html', {
'Sendungen': Sendungen,
})
return response
模板代码home.html
{% for la_item in Sendungen %}
<tr>
<td>{{ la_item.sda_sdgid.sdg_sdgid }}</td>
<td>{{ la_item.sda_ref }}</td> <!-- IV.sda_ref OKAY -->
{% for adr in la_item.is_adr_su %}
<td>{{ adr.sda_adrid.adr_adrid }}</td> <!-- SU.sda_adrid OKAY -->
<td>{{ adr.sda_termvon|date }}</td> <!-- SU.sda_termvon OKAY -->
{% endfor %}
{% for adr in la_item.is_adr_cn %}
<td>{{ adr.sda_adrid.adr_adrid }}</td> <!-- CN.sda_adrid OKAY -->
<td>{{ adr.sda_termbis|date }}</td> <!-- CN.sda_termbis OKAY -->
{% endfor %}
</tr>
{% endfor %}
我们已经将一些数据库表从我们的生产环境迁移到 django ORM 并在 django 之外自动同步这些表。 → 到目前为止效果很好,但我们在 django 中遇到问题无法将这些表(模型)正确地相互连接。
models.py
class SsdaSdgadr(models.Model):
sda_sdgid = models.ForeignKey(SsdgSendung, on_delete=models.CASCADE, blank=True, null=True)
sda_satid = models.CharField(max_length=4, blank=True, null=True)
sda_adrid = models.ForeignKey(SadrAdresse, on_delete=models.CASCADE, blank=True, null=True)
sda_ref = models.CharField(max_length=35, blank=True, null=True)
sda_termbis = models.DateField(blank=True, null=True)
sda_termvon = models.DateField(blank=True, null=True)
class Meta:
db_table = 'ssda_sdgadr'
unique_together = (('sda_sdgid', 'sda_satid'),)
class SsdgSendung(models.Model):
sdg_sdgid = models.CharField(primary_key=True, max_length=30)
sdg_konz = models.CharField(max_length=12, blank=True, null=True)
class Meta:
db_table = 'ssdg_sendung'
class SadrAdresse(models.Model):
adr_adrid = models.IntegerField(primary_key=True)
adr_name1 = models.CharField(max_length=35, blank=True, null=True)
adr_name2 = models.CharField(max_length=35, blank=True, null=True)
class Meta:
db_table = 'sadr_adresse'
示例数据
SsdaSdgadr:
sdg_sdgid | sda_satid | sda_adrid | sda_ref | sda_termvon | sda_termbis |
---|---|---|---|---|---|
BL-1237781-BL-1 | IV | 169550 | '00123/4539999' | '' | '' |
BL-1237781-BL-1 | SU | 555555 | '' | 01.12.2021 | 02.12.2021 |
BL-1237781-BL-1 | CN | 999999 | '00123' | 02.12.2021 | 13.12.2021 |
views.py
我使用了以下原始 SQL
Sendungen = SsdaSdgadr.objects.raw('''
SELECT
IV.id,
IV.sda_sdgid_id,
IV.sda_ref,
SU.id,
SU.sda_adrid_id as ABS,
SU.sda_termvon,
CN.id,
CN.sda_adrid_id as EMPF,
CN.sda_termbis
FROM
ssda_sdgadr IV
INNER JOIN ssdg_sendung on sdg_sdgid = IV.sda_sdgid_id
INNER JOIN ssda_sdgadr SU on SU.sda_sdgid_id = IV.sda_sdgid_id and SU.sda_satid="SU"
INNER JOIN ssda_sdgadr CN on CN.sda_sdgid_id = IV.sda_sdgid_id and CN.sda_satid="CN"
WHERE IV.sda_satid="IV"
GROUP BY
IV.id,
IV.sda_sdgid_id,
IV.sda_ref,
SU.id,
SU.sda_adrid_id,
SU.sda_termvon,
CN.id,
CN.sda_adrid_id,
CN.sda_termbis
ORDER BY
sdg_datum desc
''')
...
response = render(request, 'cust/home.html', {
'Sendungen': Sendungen,
})
return response
模板上的结果适用于字段“SU.sda_termvon”和“CN.sda_termbis”,但不适用于字段“sda_adrid”(→ 只有显示 IV.sda_adrid_id 的结果。
模板代码
{% for la_item in Sendungen %}
<tr>
<td>{{ la_item.sda_sdgid.sdg_sdgid }}</td>
<td>{{ la_item.sda_ref }}</td> <!-- IV.sda_ref OKAY -->
<td>{{ la_item.sda_adrid.adr_adrid }}</td> <!-- is IV.sda_adrid NOT OKAY -->
<td>{{ la_item.sda_adrid.adr_adrid }}</td> <!-- is IV.sda_adrid NOT OKAY -->
<td>{{ la_item.sda_termvon|date }}</td> <!-- SU.sda_termvon OKAY -->
<td>{{ la_item.sda_termbis|date }}</td> <!-- CN.sda_termbis OKAY -->
</tr>
{% endfor %}
如何访问模板上的结果“CN.sda_adrid_id”和“SU.sda_adrid_id”? → 看起来 ORM 解释 raw-SQL 与数据库不同:
数据库结果和预期结果应如下所示:
sda_sdgid_id | IV.sda_ref | SU.sda_adrid_id | CN.sda_adrid | SU.termvon | CN.termbis |
---|---|---|---|---|---|
BL-1237781-BL-1 | 1920192/4530210220/0881760357 | 555555 | 999999 | 01.12.2021 | 13.12.2021 |
我的实际结果是这样的:
sda_sdgid_id | IV.sda_ref | IV.sda_adrid_id | IV.sda_adrid_id | SU.termvon | CN.termbis |
---|---|---|---|---|---|
BL-1237781-BL-1 | 1920192/4530210220/0881760357 | 169550 | 169550 | 01.12.2021 | 13.12.2021 |
我使用了这个解决方法(模型 属性 用于“SsdaSdgadr”),它给了我想要的结果:
models.py
class SsdaSdgadr(models.Model):
sda_sdgid = models.ForeignKey(SsdgSendung, on_delete=models.CASCADE, blank=True, null=True)
sda_satid = models.CharField(max_length=4, blank=True, null=True)
sda_adrid = models.ForeignKey(SadrAdresse, on_delete=models.CASCADE, blank=True, null=True)
sda_ref = models.CharField(max_length=35, blank=True, null=True)
sda_termbis = models.DateField(blank=True, null=True)
sda_termvon = models.DateField(blank=True, null=True)
class Meta:
db_table = 'ssda_sdgadr'
unique_together = (('sda_sdgid', 'sda_satid'),)
@property
def is_adr_su(self):
return SsdaSdgadr.objects.filter(sda_sdgid = self.sda_sdgid, sda_satid = "SU")
@property
def is_adr_cn(self):
return SsdaSdgadr.objects.filter(sda_sdgid = self.sda_sdgid, sda_satid = "CN")
views.py
Sendungen = SsdaSdgadr.objects.filter(Q(sda_satid__in=["IV"])).order_by('-sda_sdgid__sdg_datum')
...
response = render(request, 'cust/home.html', {
'Sendungen': Sendungen,
})
return response
模板代码home.html
{% for la_item in Sendungen %}
<tr>
<td>{{ la_item.sda_sdgid.sdg_sdgid }}</td>
<td>{{ la_item.sda_ref }}</td> <!-- IV.sda_ref OKAY -->
{% for adr in la_item.is_adr_su %}
<td>{{ adr.sda_adrid.adr_adrid }}</td> <!-- SU.sda_adrid OKAY -->
<td>{{ adr.sda_termvon|date }}</td> <!-- SU.sda_termvon OKAY -->
{% endfor %}
{% for adr in la_item.is_adr_cn %}
<td>{{ adr.sda_adrid.adr_adrid }}</td> <!-- CN.sda_adrid OKAY -->
<td>{{ adr.sda_termbis|date }}</td> <!-- CN.sda_termbis OKAY -->
{% endfor %}
</tr>
{% endfor %}