Dies ist ein Material für Lernsitzungen. In diesem Tutorial finden Sie eine ergänzende Erklärung zu Djangos Modell und Ich werde eine Bibliothek vorstellen, die die Funktionen von Django erweitert und verschiedene Operationen an der Shell ausprobiert.
Es gab eine Meinung, dass die Beziehung zwischen Modell, Feld und Instanz schwer zu verstehen ist, deshalb werde ich sie ergänzen.
Das Modell repräsentiert eine DB-Tabelle. Sie kann geändert werden, indem Sie den Tabellennamen auf Meta setzen. Standardmäßig heißt sie jedoch "app name_model name". Für das Fragenmodell in der Umfrage-App lautet der Tabellenname "polls_question".
Die im Modell definierten Modelle. ~ Feld entsprechen den Spalten in der Tabelle. Die ID-Spalte wird automatisch hinzugefügt, wenn kein Feld vorhanden ist, für das PrimaryKey festgelegt ist.
Eine Instanz von Model bedeutet einen Datensatz in der DB-Tabelle.
polls/models.py
class Question(models.Model):
class Meta:
verbose_name = 'Frage'
verbose_name_plural = 'Multiple Form der Frage'
ordering = ['-pub_date']
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
Es ist erforderlich, eine SQL-Anweisung auszugeben, um einen Datensatz aus einer Tabelle in der Datenbank abzurufen. Zu diesem Zweck verfügt Model über eine Manager-Klasse. Die QuerySet-Klasse ist für die tatsächliche Ausgabe und Generierung von SQL verantwortlich und gibt die Basismodellinstanz nach der SQL-Ausgabe zurück. Vorgänge wie das Erfassen und Erstellen von Datensätzen werden über diese QuerySet-Klasse ausgeführt. Die Manager-Klasse fungiert als Relay zwischen Model und QuerySet und ist besonders eng mit QuerySet verwandt.
QuerySet verfügt auch über Methoden wie "get" und "create", um Datensätze genau abzurufen und zu erstellen. Da ein Iterator bereitgestellt wird, können die zu erfassenden Datensätze (= Instanzen) der Reihe nach erfasst werden, indem sie sich in eine for-Schleife drehen.
qs = Question.objects.all()
for q in qs:
# q <---Dies ist der erfasste Datensatz und wird zu einer Instanz der Frage
Quelle → 8a9d88559ae94bea8bb706468eaa6459127c6f59
Da Modell = Tabelle und Instanz = Datensatz, wird die Verarbeitung, die Sie für den Datensatz ausführen möchten, durch die Instanzmethode definiert. Umgekehrt ist die Verarbeitung, die Sie für die Tabelle selbst ausführen möchten, als Klassenmethode definiert.
Zum Beispiel das im Tutorial erstellte "was_published_recently" Es handelt sich um eine Instanzmethode, da "festgestellt wird, ob der Datensatz (= Instanz) kürzlich veröffentlicht wurde".
Abgesehen davon machen Sie die Methode "Von der Fragentabelle veröffentlichen" zu einer Klassenmethode.
polls/models/py
class Question(models.Model):
...
@classmethod
def get_published_data(cls):
return cls.objects.filter(pub_date__lte=timezone.now())
Im Fall eines Filters, der wie im Beispiel gezeigt "veröffentlicht" wird Es ist etwas redundant, aber es ist auch eine gute Idee, das QuerySet zu erweitern.
polls/models.py(QuerySet-Erweiterung)
import datetime
from django.db import models
from django.utils import timezone
class QuestionQuerySet(models.query.QuerySet):
def is_published(self):
return self.filter(pub_date__lte=timezone.now())
class Question(models.Model):
...
objects = models.Manager.from_queryset(QuestionQuerySet)()
...
@classmethod
def get_published_data(cls):
return cls.objects.is_published()
In beiden Fällen Sie können das veröffentlichte Abfrageset erhalten, indem Sie "Question.get_published_data ()" ausführen.
Wenn das Modell jedoch direkt erweitert wird, ist "pk 10 oder weniger und wurde veröffentlicht". Sie können keine Bedingung in die Mitte stellen.
Question.get_published_date().filter(pk__lte=10)
Wenn die Bedingung "veröffentlicht, pk ist 10 oder weniger" lautet, wird sie angewendet.
Auf der anderen Seite können Sie bei der Erweiterung von QuerySet einen Filter anwenden, um "veröffentlichte" zu erhalten, wo immer Sie möchten.
Question.objects.filter(pk__lte=10).is_published()
In Django können Sie Model usw. direkt bedienen, indem Sie mit dem Befehl manage.py shell
arbeiten.
Ich werde eine Bibliothek vorstellen, um die Shell etwas bequemer zu nutzen.
Zuallererst ipython
. Wenn Sie dies eingeben, wird die Shell eingefärbt und die Befehle ergänzt.
Als nächstes "Django-Erweiterungen".
Dies bietet nicht nur Shell, sondern, wie der Name schon sagt, verschiedene Erweiterungen für Django.
Beide können einfach mit pip installiert werden, versuchen Sie es also bitte.
$ pip install ipython
$ pip install django-extensions
Führen Sie für ipython einfach $ ./manage.py shell
aus und das Erscheinungsbild ändert sich automatisch.
Django-Erweiterungen müssen in den Einstellungen zu INSTALL_APPS hinzugefügt werden.
tutorial/settings.py
...
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_extensions', #←←← Fügen Sie dies hinzu
'bootstrap3',
'polls',
)
...
Bei der Einstellung "INSTALLED_APPS" kann der Befehl "manage.py" den Befehl für django_extensions ausführen.
$ ./manage.py
Type 'manage.py help <subcommand>' for help on a specific subcommand.
Available subcommands:
...
[django_extensions]
admin_generator
clean_pyc
clear_cache
compile_pyc
create_app
create_command
create_jobs
create_template_tags
describe_form
drop_test_database
dumpscript
export_emails
find_template
generate_secret_key
graph_models
mail_debug
notes
passwd
pipchecker
print_settings
print_user_for_session
reset_db
runjob
runjobs
runprofileserver
runscript
runserver_plus
set_default_site
set_fake_emails
set_fake_passwords
shell_plus
show_template_tags
show_templatetags
show_urls
sqlcreate
sqldiff
sqldsn
sync_s3
syncdata
unreferenced_files
update_permissions
validate_templates
...
Dieses Mal verwenden wir shell_plus
, eine Erweiterung des Befehls shell
.
Durch Hinzufügen der Option "--print-sql" beim Start können Sie auch die SQL-Anweisung zum Zeitpunkt der Instanzerfassung anzeigen. Fügen Sie sie also hinzu.
$ ./manage.py shell_plus --print-sql
# Shell Plus Model Imports
from django.contrib.admin.models import LogEntry
from django.contrib.auth.models import Group, Permission, User
from django.contrib.contenttypes.models import ContentType
from django.contrib.sessions.models import Session
from polls.models import Choice, Question
# Shell Plus Django Imports
from django.db import transaction
from django.core.urlresolvers import reverse
from django.utils import timezone
from django.core.cache import cache
from django.db.models import Avg, Count, F, Max, Min, Sum, Q, Prefetch, Case, When
from django.conf import settings
Python 3.5.1 (default, Jan 23 2016, 02:16:23)
Type "copyright", "credits" or "license" for more information.
IPython 4.2.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]:
In der Shell musste ich das Modell, das ich verwenden wollte, manuell importieren. shell_plus lädt das Modell automatisch, wenn Sie es starten.
Führen Sie den zuvor erstellten Befehl get_published_data
aus.
In [1]: Question.get_published_data()
Out[1]: SELECT "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date" FROM "polls_question" WHERE "polls_question"."pub_date" <= '2016-06-23 06:45:46.716854' ORDER BY "polls_question"."pub_date" DESC LIMIT 21
Execution time: 0.001740s [Database: default]
[<Question:Zweite Frage>, <Question: what's up?>, <Question:Dritte Frage>]
In [2]:
Dieses Mal wird die Option "--print-sql" hinzugefügt, damit Sie die auf diese Weise ausgeführte SQL-Anweisung überprüfen können.
Es gibt zwei Möglichkeiten, Daten zu registrieren: Die eine stammt vom Manager (Abfragesatz) und die andere besteht darin, die Instanz direkt zu betreiben.
Versuchen wir es zuerst mit "erstellen".
Da das Datum in pub_date eingefügt werden muss, importieren Sie django.utils.timezone
im Voraus und geben Sie das heutige Datum und die heutige Uhrzeit in pud_date an.
In [3]: from django.utils import timezone
In [4]: Question.objects.create(pub_date=timezone.now())
BEGIN
Execution time: 0.000028s [Database: default]
INSERT INTO "polls_question" ("question_text", "pub_date") VALUES ('', '2016-06-23 07:02:01.013534')
Execution time: 0.000638s [Database: default]
Out[4]: <Question: >
Dadurch wird ein neuer Datensatz in der Datenbank registriert.
In [5]: Question.objects.count()
SELECT COUNT(*) AS "__count" FROM "polls_question"
Execution time: 0.000154s [Database: default]
Out[5]: 4
Als nächstes versuchen wir, aus einer Instanz zu erstellen. Wenn eine Instanz nur erstellt wird, wird sie nicht im DB-Datensatz angezeigt. Durch Ausführen von save () der Instanz wird der Datensatz aktualisiert, wenn er vorhanden ist, und wenn er nicht vorhanden ist, wird er eingefügt.
In [6]: ins = Question(pub_date=timezone.now(), question_text='Aus Instanz erstellen')
In [7]: ins
Out[7]: <Question:Aus Instanz erstellen>
In [8]: Question.objects.count()
SELECT COUNT(*) AS "__count" FROM "polls_question"
Execution time: 0.000177s [Database: default]
Out[8]: 4 #←←←←←←← Noch nicht gemacht.
In [9]: ins.save() #←←←←←← Führen Sie hier die Datensatzaktualisierungsmethode aus
BEGIN
Execution time: 0.000032s [Database: default]
INSERT INTO "polls_question" ("question_text", "pub_date") VALUES ('Aus Instanz erstellen', '2016-06-23 07:07:46.485479')
Execution time: 0.001240s [Database: default]
In [10]: Question.objects.count()
SELECT COUNT(*) AS "__count" FROM "polls_question"
Execution time: 0.000167s [Database: default]
Out[10]: 5 #←←←←←←← eingefügt
Nachdem Sie einige Daten registriert haben, versuchen wir verschiedene Dinge, indem wir Datensätze abrufen. Es gibt verschiedene Methoden, aber vorerst gibt es kein Problem, wenn Sie sich an "Filter" und "Ausschluss" erinnern, um die Bedingungen einzugrenzen. Der Filter hinterlässt Datensätze, die den Bedingungen entsprechen. Ausschließen ist das Gegenteil, und Datensätze, die nicht den Bedingungen entsprechen, bleiben erhalten.
Übergeben Sie "Feldname = Bedingung" als Argument des Filters. Wenn Sie nach dem Feldnamen ein Zeichen wie "__lte" einfügen, ist dies keine exakte Übereinstimmung, und die Bedingungen können wie folgt geändert werden. Informationen zu den Bedingungen, die verwendet werden können, finden Sie unter Offizielles Dokument.
Schließlich wird das Verfahren zum Spezifizieren der ODER-Bedingung beschrieben. Da alle Filter (ausschließen) UND sind, verwenden Sie die Q-Klasse, um eine ODER-Suche nach Bedingungen durchzuführen. Q erstellt eine Instanz mit "Feldname = Bedingung" auf die gleiche Weise wie vom Filter angegeben. Die ODER-Suche kann realisiert werden, indem die dort erstellten Bedingungen an den Filter von QuerySet übergeben werden. Für Q können die logischen Symbole "&" (und) "|" (oder) "~" (nicht) verwendet werden.
In [12]: from django.db.models import Q
In [13]: q1 = Q(pk=1)
In [14]: q2 = Q(pk=2)
In [15]: Question.objects.filter(q1|q2)
Out[15]: SELECT "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date" FROM "polls_question" WHERE ("polls_question"."id" = 1 OR "polls_question"."id" = 2) ORDER BY "polls_question"."pub_date" DESC LIMIT 21
Execution time: 0.000390s [Database: default]
[<Question:Zweite Frage>, <Question: what's up?>]
Recommended Posts