Ceci est un matériel pour les sessions d'étude. Dans ce tutoriel, une explication supplémentaire du modèle de Django et Je vais introduire une bibliothèque qui étend les fonctions de django et essayer diverses opérations sur le shell.
Il y avait une opinion que la relation entre le modèle, le champ et l'instance est difficile à comprendre, je vais donc la compléter.
Le modèle représente une table DB.
Il peut être modifié en définissant le nom de la table sur Meta, mais par défaut, il sera nommé ʻapp name_model name. Pour le modèle Question dans l'application polls, le nom de la table sera
polls_question`.
Les modèles. ~ Le champ défini dans le modèle correspond aux colonnes du tableau. La colonne id est automatiquement ajoutée s'il n'y a pas de champ pour lequel PrimaryKey est défini.
Une instance de Model signifie un enregistrement sur la table DB.
polls/models.py
class Question(models.Model):
class Meta:
verbose_name = 'Question'
verbose_name_plural = 'Forme multiple de question'
ordering = ['-pub_date']
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
Il est nécessaire d'émettre une instruction SQL pour obtenir un enregistrement d'une table sur la base de données. Pour ce faire, Model a une classe Manager. La classe QuerySet est responsable de l'émission et de la génération réelles de SQL et retourne l'instance de modèle de base après l'émission de SQL. Les opérations telles que l'acquisition et la création d'enregistrements sont effectuées via cette classe QuerySet. La classe Manager agit comme un relais entre Model et QuerySet, et est particulièrement étroitement liée à QuerySet.
QuerySet a également des méthodes comme «get» et «create» pour obtenir et créer des enregistrements de manière précise. Puisque l'itérateur est fourni, les enregistrements (= instances) à acquérir peuvent être acquis dans l'ordre en se tournant dans une boucle for.
qs = Question.objects.all()
for q in qs:
# q <---Ceci est l'enregistrement acquis et devient une instance de Question
Source → 8a9d88559ae94bea8bb706468eaa6459127c6f59
Puisque Model = table et instance = record, le traitement que vous voulez effectuer sur l'enregistrement est défini par la méthode d'instance. Inversement, le traitement que vous souhaitez effectuer sur la table elle-même est défini comme une méthode de classe.
Par exemple, le was_published_recently
créé dans le tutoriel
Il s'agit d'une méthode d'instance car il s'agit de «déterminer si l'enregistrement (= instance) a été publié récemment».
En dehors de cela, dans le cas de la méthode "Get published from Question table", faites-en une méthode de classe.
polls/models/py
class Question(models.Model):
...
@classmethod
def get_published_data(cls):
return cls.objects.filter(pub_date__lte=timezone.now())
Dans le cas d'un filtre qui est "publié" comme indiqué dans l'exemple C'est un peu redondant, mais c'est aussi une bonne idée d'étendre le QuerySet.
polls/models.py(Extension QuerySet)
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()
Dans tous les cas
Vous pouvez obtenir l'ensemble de requêtes publié en faisant Question.get_published_data ()
.
Cependant, lorsque Model est étendu directement, «pk est inférieur ou égal à 10 et a été publié». Vous ne pouvez pas mettre une condition au milieu.
Question.get_published_date().filter(pk__lte=10)
Par exemple, si la condition est "publiée, pk est de 10 ou moins", elle sera appliquée.
Par contre, dans le cas de l'extension de QuerySet, vous pouvez appliquer un filtre pour obtenir les "publiés" où vous le souhaitez.
Question.objects.filter(pk__lte=10).is_published()
Dans django, vous pouvez directement utiliser Model etc. en utilisant la commande manage.py shell
.
Je vais vous présenter une bibliothèque pour utiliser le shell un peu plus commodément.
Tout d'abord, ʻipython. Si vous le mettez, cela colorisera le shell et complétera les commandes. Ensuite,
django-extensions`.
Cela fournit diverses extensions à django comme son nom l'indique, pas seulement shell.
Les deux peuvent être facilement installés avec pip, veuillez donc les essayer.
$ pip install ipython
$ pip install django-extensions
Pour ipython, exécutez simplement $ ./manage.py shell
et l'apparence changera automatiquement.
django-extensions doit être ajouté à INSTALL_APPS dans les paramètres.
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', #←←← Ajouter ceci
'bootstrap3',
'polls',
)
...
ʻS'il est réglé sur INSTALLED_APPS, la commande
manage.py` sera capable d'exécuter des commandes pour django_extensions.
$ ./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
...
Cette fois, nous utiliserons shell_plus
, qui est une extension de la commande shell
.
En ajoutant l'option --print-sql
au démarrage, vous pouvez également voir l'instruction SQL au moment de l'acquisition de l'instance, donc ajoutons-la.
$ ./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]:
En shell, j'ai dû importer manuellement le modèle que je voulais utiliser, shell_plus chargera automatiquement le modèle lorsque vous le démarrerez.
Exécutons la commande get_published_data
créée précédemment.
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:Deuxième question>, <Question: what's up?>, <Question:Troisième question>]
In [2]:
Cette fois, l'option --print-sql
est ajoutée, vous pouvez donc vérifier l'instruction SQL exécutée de cette manière.
Il existe deux façons d'enregistrer des données, l'une provient du gestionnaire (jeu de requêtes) et l'autre consiste à faire fonctionner directement l'instance.
Essayons d'abord de create
.
Puisqu'il est nécessaire de mettre la date dans pub_date, importez django.utils.timezone
à l'avance et spécifiez la date et l'heure du jour dans pud_date.
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: >
Cela enregistrera un nouvel enregistrement dans la base de données.
In [5]: Question.objects.count()
SELECT COUNT(*) AS "__count" FROM "polls_question"
Execution time: 0.000154s [Database: default]
Out[5]: 4
Ensuite, essayons de créer à partir d'une instance. Dans le cas d'une instance, la simple création de celle-ci ne sera pas reflétée dans l'enregistrement DB. En exécutant save () de l'instance, si l'enregistrement existe, il sera mis à jour, et s'il n'existe pas, il sera inséré.
In [6]: ins = Question(pub_date=timezone.now(), question_text='Créer à partir de l'instance')
In [7]: ins
Out[7]: <Question:Créer à partir de l'instance>
In [8]: Question.objects.count()
SELECT COUNT(*) AS "__count" FROM "polls_question"
Execution time: 0.000177s [Database: default]
Out[8]: 4 #←←←←←←← Pas encore fait à ce stade.
In [9]: ins.save() #←←←←←← Exécutez la méthode de mise à jour des enregistrements ici
BEGIN
Execution time: 0.000032s [Database: default]
INSERT INTO "polls_question" ("question_text", "pub_date") VALUES ('Créer à partir de l'instance', '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 #←←←←←←← inséré
Après avoir enregistré certaines données, essayons diverses choses en obtenant des enregistrements.
Il existe plusieurs méthodes, mais pour le moment, il n'y a pas de problème si vous vous souvenez de filter
et ʻexclude` pour affiner par conditions.
Le filtre laissera des enregistrements qui correspondent aux conditions.
Exclure est le contraire et les enregistrements qui ne correspondent pas aux conditions resteront.
Passez field name = condition
comme argument du filtre.
En ajoutant un caractère tel que «__lte» après le nom du champ, il ne s'agit pas d'une correspondance exacte et les conditions peuvent être modifiées comme suit.
Veuillez vous référer au Document officiel pour connaître les conditions qui peuvent être utilisées.
Enfin, la méthode de spécification de la condition OR est décrite.
Étant donné que tous les filtres (exclure) sont AND, utilisez la classe Q pour effectuer une recherche OR pour les conditions.
Q crée une instance avec nom de champ = condition
de la même manière que celle spécifiée par le filtre.
La recherche OU peut être réalisée en passant les conditions qui y sont créées au filtre de QuerySet.
Pour Q, les symboles logiques &
(et) |
(ou) ~
(non) peuvent être utilisés.
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:Deuxième question>, <Question: what's up?>]
Recommended Posts