Letztes Mal Zweimal zuvor Erstes Schreiben
Letztes Mal habe ich die Funktion der "Umfragen" -Anwendung hinzugefügt und sie funktioniert als Abstimmungsanwendung. Schließlich haben wir den Fehler getestet und behoben, und das letzte Mal war vorbei.
Dieses Mal werde ich mir den Inhalt der Django-Tutorials 5-7 ansehen.
Ich habe den Fehler "was_published_recently" in dem Test behoben, den ich das letzte Mal erstellt habe. Da diese Fehlerbehebung jedoch keinen Ursprung oder kein Kind hat, das andere Teile beeinflusst, werde ich sie testen. Fügen Sie Folgendes neu unter der Klasse "QuestionModelTests" in "tests.py" hinzu.
mysite/polls/tests.py
def test_was_published_recently_with_old_question(self):
#Repräsentiert gestern
time = timezone.now() - datetime.timedelta(days=1, seconds=1)
old_question = Question(pub_date=time)
self.assertIs(old_question.was_published_recently(), False)
def test_was_published_recently_with_recent_question(self):
#Stellt die letzte Minute dar
time = timezone.now() - datetime.timedelta(hours=23, minutes=59, seconds=59)
recent_question = Question(pub_date=time)
self.assertIs(recent_question.was_published_recently(), True)
was_published_recently ()
ist mehr als gestern und gibt jetzt Folgendes mit True
zurück, sodasstest_was_published_recently_with_old_question ()
False sein sollte und
test_was_published_recently_with_recent_question () mit
Truezurückkommen sollte. Diese Vorhersage ist in
self.assertIs` enthalten, daher werde ich prüfen, ob sie wahr ist.
cmd
(Django) C:\User\mysite>python manage.py test polls
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
...
----------------------------------------------------------------------
Ran 3 tests in 0.002s
OK
Destroying test database for alias 'default'...
Es wird also "Ran 3 Tests in 0,002s" angezeigt, und Sie können sehen, dass 3 Tests erfolgreich waren, einschließlich der Tests, die ich zuletzt geschrieben habe.
Laut dem Tutorial hat diese Abstimmungs-App immer noch Fehler. Es überschneidet sich mit dem problematischen Teil von "was_published_recently", aber es bedeutet, dass auch Fragen, die zu einem späteren Zeitpunkt "pub_date" waren, in der Ansicht angezeigt werden. Dieses Mal erstellen wir eine Testumgebung mit einer interaktiven Shell.
cmd
>>> from django.test import Client
>>> # create an instance of the client for our use
>>> client = Client()
>>> from django.urls import reverse
>>> response = client.get(reverse('polls:index'))
Damit ist die Installation des Testclients abgeschlossen. Im Tutorial wird vorher "client.get (" / ")" ausgeführt, um den Fehler zu erkennen, aber hier wird er weggelassen. Und was ist in der "Antwort" ...
cmd
>>> response.status_code
200
>>> response.content </ul>\n'
b'\n <ul>\n \n <li><a href="/polls/1/">What's new?</a></li>\n \n </ul>\n'
>>> response.context['latest_question_list']
<QuerySet [<Question: What's new?>]>
Es ist so.
Woher stammt der Inhalt von response.content
?
Ich habe die offizielle Dokumentation gelesen, aber nicht verstanden.
Ich weiß, dass ich irgendwo etwas ziehe, das wie "HTML" aussieht, aber umgekehrt weiß ich das nur.
Lassen Sie uns einen zweiten Blick darauf werfen und die Ansicht verbessern. Wir werden es verbessern, damit Fragen, die zu einem späteren Zeitpunkt registriert werden, nicht angezeigt werden.
mysite/polls/views.py
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'
#Umschreiben dieser Funktion
def get_queryset(self):
#Unterhalb des Unterschieds
return Question.objects.filter(
pub_date__lte=timezone.now()
).order_by('-pub_date')[:5]
pub_date__lte = timezone.now ()
zeigt auf ein pub_date
, das vor dem aktuellen Datum und der aktuellen Uhrzeit liegt.
__lte
bedeutet weniger als gleich, was so etwas wie pub_date <= timezone.now ()
bedeutet.
Wir werden einen Testcode erstellen, wie wir ihn zum Zeitpunkt von "was_published_recently" geschrieben haben, und ihn für einfache Tests vorbereiten.
mysite/polls/tests.py
def create_question(question_text, days):
time = timezone.now() + datetime.timedelta(days=days)
return Question.objects.create(question_text=question_text, pub_date=time)
class QuestionIndexViewTests(TestCase):
def test_no_questions(self):
response = self.client.get(reverse('polls:index'))
self.assertEqual(response.status_code, 200)
self.assertContains(response, "No polls are available.")
self.assertQuerysetEqual(response.context['latest_question_list'], [])
def test_past_question(self):
create_question(question_text="Past question.", days=-30)
response = self.client.get(reverse('polls:index'))
self.assertQuerysetEqual(
response.context['latest_question_list'],
['<Question: Past question.>']
)
def test_future_question(self):
create_question(question_text="Future question.", days=30)
response = self.client.get(reverse('polls:index'))
self.assertContains(response, "No polls are available.")
self.assertQuerysetEqual(response.context['latest_question_list'], [])
def test_future_question_and_past_question(self):
create_question(question_text="Past question.", days=-30)
create_question(question_text="Future question.", days=30)
response = self.client.get(reverse('polls:index'))
self.assertQuerysetEqual(
response.context['latest_question_list'],
['<Question: Past question.>']
)
def test_two_past_questions(self):
create_question(question_text="Past question 1.", days=-30)
create_question(question_text="Past question 2.", days=-5)
response = self.client.get(reverse('polls:index'))
self.assertQuerysetEqual(
response.context['latest_question_list'],
['<Question: Past question 2.>', '<Question: Past question 1.>']
)
Der Code ist länger, enthält jedoch "test_no_question ()", wenn keine Fragen vorhanden sind, "test_past_question", wenn die Frage in der vergangenen Zeit hinzugefügt wurde, und "wenn die Frage in der zukünftigen Zeit hinzugefügt wurde". Test_future_question () ,
test_future_question_and_past_question, wenn in der Vergangenheit und Zukunft zwei Fragen hinzugefügt wurden, und
test_two_past_questions (), wenn beide Fragen in der Vergangenheit hinzugefügt wurden. Es ist geschrieben in.
create_question` definiert den Prozess des Erstellens einer Frage in einem Test als Funktion.
Hoffentlich gelingt es wie folgt: Sobald ich "FAIL" bekam, funktionierte es nicht im selben Terminal, auch wenn ich den Code danach korrigierte. Wenn Sie also einen Fehler machen und von vorne beginnen möchten, ist es möglicherweise besser, ein anderes Terminal anzuheben.
cmd
(Django) C:\User\mysite>python manage.py test polls
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
..........
----------------------------------------------------------------------
Ran 8 tests in 0.044s
OK
Destroying test database for alias 'default'...
Die Verbesserung gegenüber dem vorherigen Test besteht darin, dass die in Zukunft gestellten Fragen nicht in "IndexView" angezeigt werden. Wenn Sie sie jedoch per URL abrufen, wird "DetailView" weiterhin angezeigt. Also werde ich dieses Problem lösen.
Fügen Sie zunächst die get_queryset ()
-Methode zur DetailView
-Klasse hinzu, genauso wie Sie IndexView
hinzufügen.
mysite/polls/views.py
class DetailView(generic.DetailView):
model = Question
template_name = 'polls/detail.html'
def get_queryset(self):
return Question.objects.filter(pub_date__lte=timezone.now())
Danach ist das Tutorial aus irgendeinem Grund auf Englisch, aber während es geschrieben ist, habe ich einen Test hinzugefügt, um zu überprüfen, ob pub_date
die vergangenen und nicht die zukünftigen anzeigt. Es bedeutet, dass Sie müssen.
mysite/polls/test.py
class QuestionDetailViewTests(TestCase):
def test_future_question(self):
future_question = create_question(question_text='Future question.', days=5)
url = reverse('polls:detail', args=(future_question.id,))
response = self.client.get(url)
self.assertEqual(response.status_code, 404)
def test_past_question(self):
past_question = create_question(question_text='Past Question.', days=-5)
url = reverse('polls:detail', args=(past_question.id,))
response = self.client.get(url)
self.assertContains(response, past_question.question_text)
Dies kann auf die gleiche Weise wie für "IndexView" interpretiert werden. test_future_question
prüft, ob pub_date
zukünftige nicht als DetailView
anzeigt, und test_past_question
prüft, ob pub_date
vergangene in DetailView
anzeigt.
Dies wird ebenfalls getestet und sieht folgendermaßen aus: Da die Gesamtzahl der Tests bisher 10 erreicht hat, sollte das Testergebnis 10 Tests sein, daher sollte das Ergebnis "Ran 10 Tests" sein.
cmd
(Django) C:\User\mysite>python manage.py test polls
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
..........
----------------------------------------------------------------------
Ran 10 tests in 0.058s
OK
Destroying test database for alias 'default'...
Wenn Sie es bisher betrachten, scheint es, dass Sie einen Test für "ResultView" machen können, wie es ist. Das Tutorial war auf Vorschläge beschränkt, aber schreiben wir hier einen.
mysite/polls/test.py
class QuestionResultViewTests(TestCase):
def test_future_question(self):
future_question = create_question(question_text='Future question.', days=5)
url = reverse('polls:results', args=(future_question.id,))
response = self.client.get(url)
self.assertEqual(response.status_code, 404)
def test_past_question(self):
past_question = create_question(question_text='Past Question.', days=-5)
url = reverse('polls:results', args=(past_question.id,))
response = self.client.get(url)
self.assertContains(response, past_question.question_text)
Eigentlich ist es fast das gleiche wie bei "DetailView". Die einzige Änderung ist bei "url = reverse (" polls: results ", args = ..)".
Lassen Sie uns außerdem get_queryset
richtig in ResultsView
von views.py
einfügen.
So was
mysite/polls/views.py
class ResultsView(generic.DetailView):
model = Question
template_name = 'polls/results.html'
def get_queryset(self):
return Question.objects.filter(pub_date__lte=timezone.now())
Dies ist das Ende des Tutorial-Tests, aber es scheint, dass Django auch eine Funktion zum Testen des von HTML erstellten Bildschirmverhaltens hat. Es ist wirklich raffiniert.
Von hier aus können Sie Tutorial 6 aufrufen.
Bisher habe ich kein CSS oder JavaScript verwendet, das beim Erstellen von Webseiten häufig vorkommt, aber Django kann sie gut verwenden. Django behandelt diese Dateien als statische Dateien.
Es scheint, dass django.contrib.staticfiles
diese statischen Dateien für jede Anwendung zentral verwalten kann.
Erstellen Sie einen "statischen" Ordner unter "Umfragen", damit Django statische Dateien verarbeiten kann. Erstellen Sie einen weiteren "Polls" -Ordner unter "Static", wie Sie es beim Erstellen des "Template" -Ordners getan haben. Dann werde ich folgendes CSS schreiben.
mysite/polls/static/polls/style.css
li a {
color: green;
}
Fügen Sie dann auch in index.html
einen Verweis auf CSS hinzu.
mysite/polls/templates/polls/index.html
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}">
Schreiben Sie diese Anweisung oben in die Datei. {% static%}
ist ein Django-Vorlagen-Tag, das den Speicherort statischer Dateien angibt.
Wenn ich es überprüfe, ...
Es ist definitiv grün, aber der Unterschied ist zu subtil (lacht)
Wir werden style.css
Einstellungen hinzufügen, um ein Hintergrundbild hinzuzufügen.
mysite/polls/static/polls/style.css
body {
background: white url("images/background.png ") no-repeat;
}
Wie Sie dem Link entnehmen können, bezieht es sich auf das Bild "background.png " im Ordner "mysite / polls / static / polls / image /". Legen Sie also die entsprechende Datei im Voraus ab. Das Bild wird ohne es nicht angezeigt. Hier ist das Ergebnis des Einbringens eines geeigneten Bildes aus Irasutoya. Es wurde schön angezeigt!
Ich habe vor ein paar Mal bestätigt, dass Sie "Frage" über den Administratorbildschirm hinzufügen können (EP1-2), aber in Django diesen Bildschirm Sie können es sogar anpassen. Versuchen Sie im Tutorial den Code, um mit dem Bildschirm zur Anpassung der Fragen zu spielen.
mysite/polls/admin.py
from django.contrib import admin
from .models import Question
# Register your models here
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date']}),
]
admin.site.register(Question, QuestionAdmin)
Die Änderungen sind das Hinzufügen der Klasse "QuestionAdmin" und das Hinzufügen von "QuestionAdmin" zum Argument von "admin.site.register ()". Wenn Sie sich jetzt als Administrator anmelden und den Bildschirm zum Ändern von Fragen aufrufen, werden die Felder wie unten gezeigt getrennt. Im Moment können Sie nur die Frage sehen, aber Sie können auch jede Option sehen, die mit der Frage geliefert wird.
mysite/polls/admin.py
from .models import Choice, Question
admin.site.register(Choice)
Die Änderungen sind, dass "Choice" auch aus "Models" importiert und "admin.site.register (Choice)" hinzugefügt wird. Wenn ich es überprüfe, können Sie zunächst am Anfang so "Auswahl" auswählen Wählen Sie dann "Auswahl", um den Auswahlbildschirm aufzurufen. Dann gelangen Sie zum folgenden Einstellungsbildschirm. Dies ist immer noch gut genug, aber da "Auswahl" an "Frage" gebunden ist, scheint es einfacher zu sein, es zu verwenden, wenn Sie es zusammen bearbeiten können? Beenden Sie daher "admin.site.register (Choice)" und ändern Sie es weiter.
mysite/polls/admin.py
class ChoiceInline(admin.StackedInline):
model = Choice
extra = 3
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
]
inlines = [ChoiceInline]
Fügen Sie die Klasse "ChoiceInline" hinzu und fügen Sie den Teil, der sie empfängt, in die Klasse "QuestionAdmin" ein. Löschen Sie admin.site.register (Choice)
.
Dann können Sie "Auswahl" auf dem Bildschirm "Frage" wie unten gezeigt bearbeiten.
Als nächstes werden wir diesen Bildschirm, der der vorherige Punkt des Einstellungsbildschirms "Frage" ist, benutzerfreundlicher machen. Ich fand es nicht umständlich zu verwenden, aber ich werde "admin.py" und "models.py" neuen Code hinzufügen, um es noch bequemer zu machen.
mysite/polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
]
inlines = [ChoiceInline]
#Der folgende zusätzliche Satz
list_display = ('question_text', 'pub_date', 'was_published_recently')
list_filter = ['pub_date']
search_fields = ['question_text']
mysite/polls/models.py
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self) -> str:
return self.question_text
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
#Der folgende zusätzliche Satz
was_published_recently.admin_order_field = 'pub_date'
was_published_recently.boolean = True
was_published_recently.short_description = 'Published recently?'
Der von "list_display" angezeigte Inhalt wurde erweitert, und der Seitenleistenfilter ist jetzt mit "list_filter" wirksam. Sie können auch mit "search_fields" suchen. (Die wichtigsten Änderungen sind in der Box)
Der Administratorbildschirm kann mithilfe der HTML-Datei wie im Fall von IndexView angepasst werden.
Um ehrlich zu sein, ist die Standardeinstellung ausreichend, aber es kann zweckmäßig sein, sie eines Tages zu verwenden.
Teilen Sie settings.py
zunächst den Pfad der Vorlage
mit, auf die sich dieses Projekt bezieht.
mysite/mysite/setting.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], #Diese Linie! !! !!
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
Das Kopieren und Einfügen des Codes in diesem Lernprogramm ist fehlgeschlagen.
Im Tutorial heißt es "DIRS": [BASE_DIR / "templates"], aber dies wird als Berechnung des Zeichenkettentyps angesehen, und natürlich kann die Zeichenkette nicht geteilt werden, sodass ein Fehler auftritt.
Durch Setzen von os.path.join (BASE_DIR, 'templates')],
wird der Pfad angegeben und der Fehler vermieden.
Das Lesen des englischen Tutorials gab mir hier keine Antwort. Stimmt etwas mit dem Tutorial nicht? Ich denke, es ist mein Versehen, aber ...
Ziehen Sie dann die Vorlage auf dem Administratorbildschirm aus der Django-Quelldatei. Es gibt auch ein Beispiel für eine Vorlage im Django-Paket. freundlich. Mit dem folgenden Code können Sie überprüfen, wo sich die Django-Quelldatei befindet.
cmd
(Django) C:\Users\mysite> python -c "import django; print(django.__path__)"
Wenn Sie den Speicherort kennen, öffnen Sie ihn mit dem Explorer und fügen Sie "base_site.html" unter "mysite / templates / admin" ein.
Erstellen Sie hier einen neuen Ordner "Vorlagen" und den Ordner "Admin" darunter.
(Base_site.html
befindet sich in django / contrib / admin / templates / admin
in der Quelldatei)
Dann bearbeiten Sie base_site.html
ein wenig.
mysite/templates/admin/base_site.html
{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Administratorbildschirm</a></h1>
{% endblock %}
Wenn Sie nur das geänderte Teil extrahieren, wird es hier sein. Wenn Sie ein Zeichen in das Tag " <\ a>" einfügen, wird es oben auf der Seite angezeigt.
Standardmäßig ist {{site_header | default: _ ('Django-Administration')}}
enthalten.
Und lassen Sie uns überprüfen, ob sich die Änderung wie folgt widerspiegelt. Es ist richtig geändert! !!
Damit ist das Django-Tutorial abgeschlossen. Es gab ziemlich viel. Um ehrlich zu sein, selbst wenn Sie hierher kommen, ist es immer noch unmöglich loszulassen (lacht) Wenn Sie jedoch die Grundlagen verstehen, denke ich, dass weitere Studien große Fortschritte machen werden. Es war so ein zäher Inhalt. Danach gibt es ein fortgeschrittenes Tutorial, aber ich habe es noch nicht gemacht (lacht) Wenn du es brauchst ...
Das nächste Mal werde ich Git lernen, während ich Django ein bisschen mehr drehe, also danke.
Recommended Posts