mixi Group Adventskalender Dies ist der zweite Tag.
"Ticket Camp", das von Mixy Group betrieben wird, wird mit Python und Django auf der Serverseite entwickelt.
Ich verwende derzeit Django Version 1.7.11, aber dies ist ein Hinweis darauf, was ich beim Update auf Django 1.8 getan habe.
Ich bin mir sicher, dass es einige Teile gibt, die nur für Ticketcamps gelten, aber ich hoffe, dass sie jedem helfen werden, der über eine Aktualisierung von Django nachdenkt.
Erstens hängt die Richtlinie zum Aktualisieren der Ticketcamp-Framework-Bibliothek etwas von meiner Intuition ab, und es ist schwierig zu klären, aber im Allgemeinen werden die folgenden drei Regeln verwendet. Ich kann erklären.
Das dritte "es sei denn, es gibt einen bestimmten Grund" ist nicht eindeutig, und der Grund ist in Fällen wie "Ich möchte die Funktion X verwenden, aber in diesem Fall muss ich die Bibliothek Y aktualisieren" klar. Es gibt jedoch Fälle, in denen es keinen tieferen Grund gibt als "Ich habe versucht, ihn zu erhöhen", z. B. "Ich habe einen Fall, in dem die API zum Hochladen von Bildern geändert werden muss, damit ich auch Pillow aktualisiere".
Wie auch immer, ich möchte betonen, dass wir nicht mit einer Richtlinie wie "Versions-Upgrade verbieten" entwickeln.
Das zweite "Hauptaktualisierungen so weit wie möglich verfolgen" bedeutet, dass es für eine Person, die Django vor 1.0 verwendet hat, besser ist, immer die neueste Version zu befolgen, um den Zustand der Anwendung zu erhalten, und beim Aktualisieren Es basiert auf der empirischen Regel, dass es doch einfach ist, wenn es wird.
Unter diesem Gesichtspunkt wollte ich von Django 1.8 Beta Stage aktualisieren, jedoch mit einigen Aktualisierungsfehlern Es gab einen Punkt, den ich lange nicht berührt hatte. Dabei kam Django 1.9 RC heraus, das ist also schlecht. Schließlich begann ich ernsthaft an dem Versions-Upgrade zu arbeiten.
Als ich dann die Django-Site überprüfte, als ich den Veröffentlichungsknopf dieses Artikels drücken wollte, wurde [Django 1.9 bereits veröffentlicht](https://www.djangoproject.com/weblog/2015/dec/01/] django-19-veröffentlicht /) ・ ・ ・
Im Ticketcamp verwendet die Jobwarteschlange den Standard Sellerie in Python und die Verarbeitung, für die externe Netzwerk-E / A erforderlich sind, z. B. Push-Benachrichtigung über AWS SNS Die Verarbeitung von Ticketlisten / Anforderungsabgleichen usw., die einige Zeit in Anspruch nimmt, wird vom Arbeitsprozess von Celery verarbeitet.
Als ich zu Django 1.8 wechselte, trat ein Fehler in dem Sellerie == 3.1.7
auf, den ich bisher verwendet habe, also habe ich auf die neueste Version von Sellerie == 3.1.9
aktualisiert.
pip install --upgrade celery==3.1.9
Sellerie ist sehr stabil und hat viele Benutzer, daher sehe ich kein großes Risiko, wenn es um kleinere Updates geht.
Der Unit-Test-Testläufer ist nicht der Standard-Django-Testläufer, sondern der django_nose
-Testläufer.
Da dies auch auf eine etwas ältere Version behoben wurde, ist ein Fehler aufgetreten, sodass ich auf die neueste Version django_nose == 1.4.2
aktualisiert habe.
pip install --upgrade django_nose==1.4.2
TEST_NAME
in TEST
Ab Django 1.7 wurde die Methode zum Festlegen der Testdatenbank vom Präfix "TEST_" in ein unabhängiges Diktat namens "TEST" geändert (https://docs.djangoproject.com/de/1.8/ref/settings). / # test), also behebe es zu diesem Zeitpunkt.
Vor der Korrektur.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'USER': 'root',
'NAME': 'ticketcamp_dev',
'TEST_NAME': 'test_ticketcamp_dev',
},
}
Überarbeitet.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'USER': 'root',
'NAME': 'ticketcamp_dev',
'TEST': {
'NAME': 'test_ticketcamp_dev',
},
},
}
loader.get_template_from_string
ist verschwundenEs gab nur einen Ort im Ticketcamp, an dem die Methode "django.template.loader.get_template_from_string" verwendet wurde.
Zumindest sieht der Code so aus:
from django.template import loader, Context
tmpl = loader.get_template_from_string(content)
output = tmpl.render(Context(ctxt))
Code wie dieser
AttributeError: 'module' object has no attribute 'get_template_from_string'
Ich fing an, den Fehler zu bekommen.
Anscheinend wurde "django.template.loader.get_template_from_string" in Django 1.8 entfernt.
Diese Art des plötzlichen Löschens von Methoden ist in Django selten und kommt in öffentlichen APIs nie vor. Normalerweise wird eine "DeprecatedWarning" ausgegeben, die in Django 1.x abgeschafft wird, sodass Sie sie während der normalen Entwicklung bemerken werden.
Dies bedeutet, dass diese Methode als private Methode behandelt wurde, nicht als öffentliche Methode.
Glücklicherweise war es in diesem Fall eine einfache Lösung, loader.get_template_from_string
durch Template
zu ersetzen.
from django.template import Template, Context
tmpl = Template(content)
output = tmpl.render(Context(ctxt))
Ticket Camp verwendet django.contrib.auth
für die Benutzerregistrierung und Benutzerauthentifizierung, ist jedoch ein Überbleibsel der Entwicklung seit den Tagen von Django 1.4, Muster, das das Profilobjekt verwendet, um Benutzern zusätzliche Informationen zu geben bleibt weiterhin bestehen.
Der Code sieht folgendermaßen aus:
# -*- coding: utf-8 -*-
#Dieser Code hat eine Falle, also kopieren Sie ihn nicht!
from django.conf import settings
from django.db import models
class Profile(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, unique=True)
#Kürzung
Nach dem Update auf Django 1.8 und dem Ausführen von Sellerie-Arbeitern wurde folgende Warnung angezeigt:
myapp.Profile.user: (fields.W342) Setting unique=True on a ForeignKey has the same effect as using a OneToOneField.
HINT: ForeignKey(unique=True) is usually better served by a OneToOneField.
Ich wusste es zum ersten Mal zu diesem Zeitpunkt, aber der obige Code ist an erster Stelle
# -*- coding: utf-8 -*-
from django.conf import settings
from django.db import models
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
#Kürzung
Es scheint, dass Sie "OneToOneField ()" anstelle von "ForeignKey (unique = True)" wie hätten verwenden sollen. Da ich in der ersten Phase einen Fehler gemacht habe, gab es außerdem einige Stellen, an denen ähnliche Warnungen ausgegeben wurden.
Es schien, als sollte ich es wie im Hinweis in der Warnung in "OneToOneField ()" ändern, damit ich bei dieser Gelegenheit alles reparieren konnte.
default
, auto_now
, auto_now_add
von DateTimeField
sind jetzt exklusivAb hier werden schwierige Updates erstellt.
Die Definition des Ticketcamp-Modells weist das folgende Muster auf, und das Datum und die Uhrzeit der Modellerstellung sowie das Aktualisierungsdatum und die Aktualisierungszeit werden automatisch als "created_at" und "aktualisiertes_at" aktualisiert.
from django.db import models
class Ticket(models.Model):
price = models.IntegerField()
count = models.IntegerField()
created_at = models.DateTimeField(default=timezone.now, auto_now_add=True)
updated_at = models.DateTimeField(default=timezone.now, auto_now=True)
Als ich versuchte, Code mit einer solchen Modelldefinition auf Django 1.8 auszuführen, wurde der Sellerie-Worker aufgrund des folgenden Fehlers nicht mehr gestartet:
myapp.Ticket.created_at: (fields.E160) The options auto_now, auto_now_add, and default are mutually exclusive. Only one of these options may be present.
myapp.Ticket.updated_at: (fields.E160) The options auto_now, auto_now_add, and default are mutually exclusive. Only one of these options may be present.
Die Ursache ist, dass, wie in der Fehlermeldung gezeigt, "auto_now", "auto_now_add" und "default" sich gegenseitig ausschließen und nicht gleichzeitig angegeben werden können.
Um dieses Problem zu lösen, dachte ich an die folgenden Lösungen.
Die erste Option ist, dass Sie den Code nicht so oft wie möglich selbst schreiben möchten und dass Django solche Änderungen vorgenommen hat, was bedeutet, dass Sie gleichzeitig "auto_now", "auto_now_add" und "default" angeben können. Ich gab auf, weil ich vermutete, dass es schwierig sein würde, eine solche Implementierung durchzuführen.
Es wurde vorausgesagt, dass die zweite Option weniger Codeänderungen und weniger Auswirkungen auf die Anwendung hat, aber ich habe es so weit gebracht, dass "keine Schemas definiert werden, die vom Django-Modell nicht dargestellt werden können". Ich habe es vom Designprinzip auf Eis gelegt.
Wir testen das Update derzeit mit einem dritten Fix.
Zunächst kann created_at
im obigen Modellbeispiel die Option auto_now_add = True
sicher entfernen.
Wenn Sie eine Instanz des Modells erstellen, wird die Option default
timezone.now ausgewertet und der Wert von
created_at wird zur aktuellen Zeit. Dieser Wert wird in der Datenbank gespeichert, wenn Sie
save () aufrufen. Weil es so sein wird. (Wenn ich darüber nachdenke, denke ich, dass
auto_now_add = True` überhaupt nicht notwendig war.)
Das Problem ist mit updated_at
updated_at = models.DateTimeField(default=timezone.now)
Oder
updated_at = models.DateTimeField(auto_now=True)
Du musst auswählen.
Im ersteren Fall ist "update_at" beim Erstellen der Instanz nicht "Noone", aber "save ()" aktualisiert nicht die Spalte "updated_at" der Datenbank.
$ python manage.py shell
>>> from myapp.models import Ticket
>>> ticket = Ticket(price=1000, count=1)
>>> ticket.updated_at is not None
True
>>> ticket.save()
>>> ticket.price = 1500
>>> ticket.save() #Ich habe es geändert, aber die Datenbank wurde aktualisiert_at wird nicht aktualisiert
Ich habe über eine Möglichkeit nachgedacht, update_at
mithilfe von [ post_save
-Signalen] zu aktualisieren (https://docs.djangoproject.com/de/1.8/ref/signals/#post-save). Ich dachte, es würde ein Problem verursachen, dass es schwierig ist, die Ursache zu finden, also beschloss ich, darauf zu verzichten.
Letzteres ist der Nachteil der Auswahl von "DateTimeField (auto_now = True)", dass "aktualisierte_at" beim Erstellen der Instanz "Keine" ist und die aktuelle Zeit die Instanz ist, wenn "save ()" zum ersten Mal aufgerufen wird. Dies bedeutet, dass sich das Verhalten in der Eigenschaft updated_at` widerspiegelt.
$ python manage.py shell
>>> from myapp.models import Ticket
>>> ticket = Ticket(price=1000, count=1)
>>> ticket.updated_at is not None
False # updated_at ist noch keiner
>>> ticket.save()
>>> ticket.updated_at is not None
True # save()Werden Sie nach dem Anruf zum ersten Mal Nicht-Keine
Dies bedeutet, dass wenn Sie Code haben, der auf update_at
der Instanz vor save ()
verweist, diese möglicherweise nicht mehr funktioniert.
Jede Methode hat jedoch Vor- und Nachteile, und am Ende schien die letzte Methode der vom Framework-Ersteller angenommenen Verwendung zu folgen. Daher habe ich die letzte Methode und die folgende Methode übernommen. Ich beschloss, es mit Gefühl zu ändern.
from django.db import models
class Ticket(models.Model):
price = models.IntegerField()
count = models.IntegerField()
created_at = models.DateTimeField(default=timezone.now)
updated_at = models.DateTimeField(auto_now=True)
Da der offensichtliche Fehler verschwunden ist, als ich anfing, den Betrieb zu überprüfen, scheint es, dass er normal funktioniert. Danach dachte ich, wenn ich vor "save ()" auf "updated_at" verwies und den Teil verschob, in dem der Fehler auftrat, dachte ich, dass das Update abgeschlossen war, aber es gab immer noch Fallstricke ...
Eigentlich wollte ich den Punkt erreichen, an dem das Update zum Zeitpunkt der Veröffentlichung dieses Adventskalenders abgeschlossen war, aber es gibt immer noch einige ungelöste und ungeklärte Probleme.
Wenn Sie den Komponententest ausführen,
$ python manage.py test myapp
#Abkürzung
django.db.utils.IntegrityError: (1215, 'Cannot add foreign key constraint')
Ich habe den Fehler bekommen.
Die Untersuchung der Ursache hat viel Zeit in Anspruch genommen, aber es scheint, dass die Ursache darin besteht, dass das Schema beim Erstellen der Unit-Test-Datenbank nicht korrekt wiedergegeben wird, da "Migrationen" nicht in jedem Django-App-Verzeichnis vorhanden sind.
Das Ticketcamp wurde entwickelt, bevor Migrations in Django 1.7 eingeführt wurde, und selbst bei der Aktualisierung auf Django 1.7, "Migrations" Ich habe manage.py make migrations
nicht gemacht, weil ich nicht vorhatte, es zu verwenden, aber es scheint, dass ich endlich Migrations verwenden muss.
Kehren Sie zum Django-Standardtestläufer zurück, erstellen Sie manuell eine Testdatenbank und dann
$ python manage.py test myapp --keepdb
Als ich den Test mit der Option "--keepdb" ausführte, konnte ich den Test ausführen.
Wie ich im Voraus erwartet hatte, änderte sich jedoch die Definition des Modells für "aktualisierte_at", so dass ich versuchte, "NULL" in "aktualisierte_at" einzufügen und keine Geräte laden konnte.
In Bezug auf dieses Problem
update_at
nur während des Testens im pre_save
-Signal nicht-NULL.Wir erwägen eine Korrekturmethode wie.
Mit Django 1.8 gibt es viele Warnungen für Funktionen, die in 1.9 entfernt werden, daher zerdrücke ich sie nacheinander.
Warnung für django.core.cache.get_cache
.
RemovedInDjango19Warning: 'get_cache' is deprecated in favor of 'caches'
Vor der Korrektur.
from django.core.cache improt get_cache
get_cache('default').get('key')
Überarbeitet. Dies wurde mechanisch ersetzt.
from django.core.cache improt caches
caches['default'].get('key')
Warnung für django.utils.functional.memoize
.
RemovedInDjango19Warning: memoize wrapper is deprecated and will be removed in Django 1.9. Use django.utils.lru_cache instead.
Warnung für django.utils.datastructures.SortedDict
. Dies geschieht, weil die Version von django-redis, die ich verwende, ziemlich alt ist und nicht der Code, den ich selbst geschrieben habe, also aktualisiere ich. Scheint notwendig zu sein.
RemovedInDjango19Warning: SortedDict is deprecated and will be $
emoved in Django 1.9.
Eine Warnung, die beim "Beizen" eines Django-Modells auftritt.
RuntimeWarning: Pickled model instance's Django version is not specified.
Es scheint, dass wir uns noch in der Aktualisierungsphase befinden, aber gemäß der Release-Richtlinie von Django wird die derzeit verwendete Version 1.7 die Wartung beenden, wenn 2.0 herauskommt. Daher ist es unbedingt erforderlich, auf die nächste LTS-Version 1.8 umzusteigen. Es gibt.
Wir untersuchen auch, ob es möglich ist, von Python 2.7 auf Python 3.5 zu migrieren, und ich habe das Bedürfnis, die neueste Version von Django für die Migration auf Python 3.5 zu befolgen.
Ich hoffe, die Angelegenheit bis Ende des Jahres zu regeln und das neue Jahr bequem zu begrüßen.
Als nächstes wird akkuma über den Aktionsmodus für Android schreiben.
Recommended Posts