[PYTHON] Aktualisieren Sie Anwendungen, die unter Django 1.7 ausgeführt werden, auf Django 1.8

Was ist das?

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.

Upgrade-Richtlinie für die Ticketcamp-Version

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 /) ・ ・ ・

Korrekturen erforderlich, um auf Django 1.8 zu aktualisieren

Aktualisieren Sie Sellerie auf die neueste Version

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.

Django_nose wurde auf die neueste Version aktualisiert

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

Ändern Sie 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 verschwunden

Es 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))

Die Warnung von "ForeignKey (unique = True)" ist erschienen.

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 exklusiv

Ab 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 ...

Ungelöste Probleme

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.

Fügen Sie Migrationen hinzu

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.

Fix YAML für Fixtures

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

Wir erwägen eine Korrekturmethode wie.

Warnung für Funktionen, die in Django 1.9 veraltet sind

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.

Schließlich

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

Aktualisieren Sie Anwendungen, die unter Django 1.7 ausgeführt werden, auf Django 1.8
Migrieren Sie Django-Anwendungen, die unter Python 2.7 ausgeführt werden, auf Python 3.5
Aktualisieren Sie die Django-Version 1.11.1 auf 2.2
Aktualisieren Sie die Python, die Sie auf Ihrem Mac hatten, auf 3.7-> 3.8
Django-Update
Aktualisieren Sie Mac Python von 2 auf 3
Die Geschichte, dass "calendar.day_abbr" auf dem Admin-Bildschirm von django nicht aktualisiert werden konnte
So aktualisieren Sie PHP unter Amazon Linux 2
So aktualisieren Sie die Sicherheit unter CentOS Linux 8
So aktualisieren Sie die Sicherheit unter Ubuntu 19.10 Eoan Ermine
So aktualisieren Sie easy_install
Sellerie-Notizen zu Django
Führen Sie Django auf PythonAnywhere aus
So aktualisieren Sie Spyder
So erstellen Sie eine Django (Python) -Umgebung auf Docker
Memo zur Bereitstellung von Django × Postgresql auf Docker für Heroku
Django kann nicht importiert werden
Ausführung von MINST in TensorFlow 2.0 und Visualisierung in TensorBoard (Version 2019)
Hallo Welt mit Django
Verwendung von Django mit Google App Engine / Python
Aktualisieren Sie vscode unter Linux
Übergang zum Update-Bildschirm mit dem Django-Tag
So führen Sie Django unter IIS auf einem Windows-Server aus
Verliere nicht gegen Ruby! Wie man Python (Django) auf Heroku ausführt
Einführung in Python Django (2) Win
[Django] Hinweise zur Verwendung der Django-Debug-Symbolleiste
Shell zum Erstellen eines Django-Projekts
So registrieren Sie sich bei pypi
Wie aktualisiere ich mit SQLAlchemy?
Aktualisieren Sie python-social-auth von 0.1.x auf 0.2.x.
Entwicklung der Django-Umgebung unter Windows 10
Installieren Sie Django auf dem Mac
Übergeben Sie den Text an Django genericview
Stellen Sie das Django-Projekt für Heroku bereit
Hallo Welt (Anfänger) mit Django
So erstellen Sie AWS Lambda-Schichten, wenn Selen × Chrom auf AWS Lambda ausgeführt wird
Vorsichtsmaßnahmen beim Ausführen von Python unter EC2 über AWS Lambda (Befehl ausführen)
So stellen Sie eine Django-App in nur 5 Minuten für Heroku bereit
So aktualisieren Sie die Python-Version von Cloud Shell in GCP
Alles vom Erstellen einer Python-Umgebung bis zur Ausführung unter Windows