Ich habe diesen Artikel geschrieben, als ich an [Tokyo Django Meetup # 3] teilgenommen habe (http://django.connpass.com/event/14219/).
Neue Funktion in Django 1.8 [Bedingte Ausdrücke] hinzugefügt (https://docs.djangoproject.com/de/1.8/ref/models/conditional-expressions/ ), Sie können jetzt bedingte Ausdrücke an die beim Betrieb des Modells verwendeten Methoden "Annotation", "Aggregation" und "Update" übergeben.
Die folgenden Modelle sind verfügbar. [^ 1]
models.py
# -*- coding: utf-8 -*-
from django.db import models
class Sponsor(models.Model):
u"""
Sponsor der PyCon JP 2015
"""
DIAMOND = 'D'
PLATINUM = 'P'
GOLD = 'G'
SILVER = 'S'
PLAN_CHOICES = (
(DIAMOND, 'Diamond'),
(PLATINUM, 'Platinum'),
(GOLD, 'Gold'),
(SILVER, 'Silver'),
)
name = models.CharField(max_length=50)
registered_on = models.DateField()
plan = models.CharField(
max_length=1,
choices=PLAN_CHOICES,
default=SILVER,
)
Die Testdaten sind wie folgt.
>>> from datetime import date, timedelta
>>> Sponsor.objects.create(
... name='Crazy Inc.',
... plan=Sponsor.DIAMOND,
... registered_on=date.today() - timedelta(days=19))
<Sponsor: Sponsor object>
>>> Sponsor.objects.create(
... name='Star Inc.',
... plan=Sponsor.PLATINUM,
... registered_on=date.today() - timedelta(days=36))
<Sponsor: Sponsor object>
>>> Sponsor.objects.create(
... name='Experience Inc.',
... plan=Sponsor.GOLD,
... registered_on=date.today() - timedelta(days=11))
<Sponsor: Sponsor object>
>>> Sponsor.objects.create(
... name='Giorno co., ltd.',
... plan=Sponsor.GOLD,
... registered_on=date.today() - timedelta(days=6))
<Sponsor: Sponsor object>
>>> Sponsor.objects.create(
... name='Chariot Inc.',
... plan=Sponsor.SILVER,
... registered_on=date.today() - timedelta(days=1))
<Sponsor: Sponsor object>
>>> Sponsor.objects.create(
... name='Polnareff co., ltd.',
... plan=Sponsor.SILVER,
... registered_on=date.today() - timedelta(days=2))
<Sponsor: Sponsor object>
Bedingte Ausdrücke werden durch Kombinieren der folgenden zwei Klassen geschrieben.
Die Klasse "When" gibt zuerst die "Bedingung" und am Ende das "Ergebnis" an. Die Methode zum Angeben der "Bedingung" entspricht der Methode filter.
>>> from django.db.models import When, F, Q
>>> #Beziehen Sie sich auf das Namensfeld, wenn der Plan Gold ist
>>> When(plan=Sponsor.GOLD, then='name')
>>> When(plan=Sponsor.GOLD, then=F('name'))
>>> from datetime import date
>>> # registered_am ist 2015/2/1 bis 2015/9/Beziehen Sie sich auf das Planfeld, wenn es zwischen 1 liegt
>>> When(registered_on__gt=date(2015, 2, 1),
... registered_on__lt=date(2015, 9, 1),
... then='plan')
>>> #Sie können im Q-Objekt auch ODER-Bedingungen angeben
>>> When(Q(name__startswith="Crazy") | Q(name__startswith="Giorno"),
... then='name')
Kombinieren Sie die oben genannte "Wann" -Klasse mit der "Fall" -Klasse und fordern Sie die Sponsorengebühr für jeden Sponsor an.
>>> from django.db.models import Case, When, Value, CharField
>>> Sponsor.objects.annotate(
... fee=Case(
... When(plan=Sponsor.DIAMOND, then=Value(u'1,000,000 Yen(Steuer nicht inbegriffen)')),
... When(plan=Sponsor.PLATINUM, then=Value(u'500,000 Yen(Steuer nicht inbegriffen)')),
... When(plan=Sponsor.GOLD, then=Value(u'300,000 Yen(Steuer nicht inbegriffen)')),
... When(plan=Sponsor.SILVER, then=Value(u'100,000 Yen(Steuer nicht inbegriffen)')),
... output_field=CharField(),
... ),
... ).values_list('name', 'fee')
[(u'Crazy Inc.', u'1,000,000\u5186 (\u7a0e\u629c\u304d)'), (u'Star Inc.', u'500,000\u5186 (\u7a0e\u629c\u304d)'), (u'Experience Inc.', u'300,000\u5186 (\u7a0e\u629c\u304d)'), (u'Giorno co., ltd.', u'300,000\u5186 (\u7a0e\u629c\u304d)'), (u'Chariot Inc.', u'100,000\u5186 (\u7a0e\u629c\u304d)'), (u'Polnareff co., ltd.', u'100,000\u5186 (\u7a0e\u629c\u304d)')]
Lassen Sie uns plan
entsprechend dem Wert von register_on
aktualisieren.
>>> from django.db.models import Case, When, Value
>>> from datetime import date,timedelta
>>> a_week_ago = date.today() - timedelta(weeks=1)
>>> a_month_ago = date.today() - timedelta(days=30)
>>> Sponsor.objects.update(
... plan=Case(
... When(registered_on__lte=a_week_ago ,
... then=Value(Sponsor.PLATINUM)),
... When(registered_on__lte=a_month_ago,
... then=Value(Sponsor.GOLD)),
... default=Value(Sponsor.SILVER)
... ),
... )
>>> Sponsor.objects.values_list('name', 'plan')
[(u'Crazy Inc.', u'P'), (u'Star Inc.', u'P'), (u'Experience Inc.', u'P'), (u'Giorno co., ltd.', u'S'), (u'Chariot Inc.', u'S'), (u'Polnareff co., ltd.', u'S')]
Finden Sie heraus, wie viele Unternehmen sich für jeden "Plan" beworben haben.
>>> from django.db.models import Case, When, Value, IntegerField, Sum
>>> Sponsor.objects.aggregate(
... silver=Sum(
... Case(When(plan=Sponsor.SILVER, then=1),
... output_field=IntegerField())
... ),
... gold=Sum(
... Case(When(plan=Sponsor.GOLD, then=1),
... output_field=IntegerField())
... ),
... platinum=Sum(
... Case(When(plan=Sponsor.PLATINUM, then=1),
... output_field=IntegerField())
... )
... )
{'platinum': 3, 'silver': 3, 'gold': None}
Werfen wir einen Blick auf das tatsächliche SQL, das mit dem Befehl debugsqlshell
in djnago-debug-toolbar erstellt wurde. [^ 2]
>>> Sponsor.objects.annotate(
... fee=Case(
... When(plan=Sponsor.DIAMOND, then=Value(u'1,000,000 Yen(Steuer nicht inbegriffen)')),
... When(plan=Sponsor.PLATINUM, then=Value(u'500,000 Yen(Steuer nicht inbegriffen)')),
... When(plan=Sponsor.GOLD, then=Value(u'300,000 Yen(Steuer nicht inbegriffen)')),
... When(plan=Sponsor.SILVER, then=Value(u'100,000 Yen(Steuer nicht inbegriffen)')),
... output_field=CharField(),
... ),
... ).values_list('name', 'fee')
SELECT `sponsors_sponsor`.`name`,
CASE
WHEN `sponsors_sponsor`.`plan` = 'D' THEN '1,000,000 Yen(Steuer nicht inbegriffen)'
WHEN `sponsors_sponsor`.`plan` = 'P' THEN '500,000 Yen(Steuer nicht inbegriffen)'
WHEN `sponsors_sponsor`.`plan` = 'G' THEN '300,000 Yen(Steuer nicht inbegriffen)'
WHEN `sponsors_sponsor`.`plan` = 'S' THEN '100,000 Yen(Steuer nicht inbegriffen)'
ELSE NULL
END AS `fee`
FROM `sponsors_sponsor` LIMIT 21 [0.23ms]
>>> Sponsor.objects.update(
... plan=Case(
... When(registered_on__lte=a_week_ago ,
... then=Value(Sponsor.PLATINUM)),
... When(registered_on__lte=a_month_ago,
... then=Value(Sponsor.GOLD)),
... default=Value(Sponsor.SILVER)
... ),
... )
UPDATE `sponsors_sponsor`
SET `plan` = CASE
WHEN `sponsors_sponsor`.`registered_on` <= '2015-04-22' THEN 'P'
WHEN `sponsors_sponsor`.`registered_on` <= '2015-03-30' THEN 'G'
ELSE 'S'
END [0.62ms]
>>> Sponsor.objects.aggregate(
... silver=Sum(
... Case(When(plan=Sponsor.SILVER, then=1),
... output_field=IntegerField())
... ),
... gold=Sum(
... Case(When(plan=Sponsor.GOLD, then=1),
... output_field=IntegerField())
... ),
... platinum=Sum(
... Case(When(plan=Sponsor.PLATINUM, then=1),
... output_field=IntegerField())
... )
... )
SELECT SUM(CASE WHEN `sponsors_sponsor`.`plan` = 'P' THEN 1 ELSE NULL END) AS `platinum`,
SUM(CASE WHEN `sponsors_sponsor`.`plan` = 'S' THEN 1 ELSE NULL END) AS `silver`,
SUM(CASE WHEN `sponsors_sponsor`.`plan` = 'G' THEN 1 ELSE NULL END) AS `gold`
FROM `sponsors_sponsor` [0.32ms]
[^ 1]: Beispielcode des Originaldokuments [PyCon JP 2015 Sponsorship Information](https :: Geändert mit Bezug auf (/ pycon.jp/2015/sponsors/prospectus.html). [^ 2]: Die Datenbank verwendet MySQL 5.5.43.
Recommended Posts