mirror of
https://github.com/django/django.git
synced 2025-07-05 10:19:20 +00:00
multi-auth: Merged to [3085]
git-svn-id: http://code.djangoproject.com/svn/django/branches/multi-auth@3086 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
0c341d780e
commit
e976ed1f79
@ -203,6 +203,16 @@ DATETIME_FORMAT = 'N j, Y, P'
|
|||||||
# http://www.djangoproject.com/documentation/templates/#now
|
# http://www.djangoproject.com/documentation/templates/#now
|
||||||
TIME_FORMAT = 'P'
|
TIME_FORMAT = 'P'
|
||||||
|
|
||||||
|
# Default formatting for date objects when only the year and month are relevant.
|
||||||
|
# See all available format strings here:
|
||||||
|
# http://www.djangoproject.com/documentation/templates/#now
|
||||||
|
YEAR_MONTH_FORMAT = 'F Y'
|
||||||
|
|
||||||
|
# Default formatting for date objects when only the month and day are relevant.
|
||||||
|
# See all available format strings here:
|
||||||
|
# http://www.djangoproject.com/documentation/templates/#now
|
||||||
|
MONTH_DAY_FORMAT = 'F j'
|
||||||
|
|
||||||
# Whether to enable Psyco, which optimizes Python code. Requires Psyco.
|
# Whether to enable Psyco, which optimizes Python code. Requires Psyco.
|
||||||
# http://psyco.sourceforge.net/
|
# http://psyco.sourceforge.net/
|
||||||
ENABLE_PSYCO = False
|
ENABLE_PSYCO = False
|
||||||
|
Binary file not shown.
@ -72,7 +72,7 @@ msgstr "Dit veld mag niet leeg zijn."
|
|||||||
|
|
||||||
#: db/models/fields/__init__.py:468 core/validators.py:132
|
#: db/models/fields/__init__.py:468 core/validators.py:132
|
||||||
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
|
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
|
||||||
msgstr "Geef geldige datum/tijd in JJJJ-MM-DD HH:MM formaat."
|
msgstr "Geef geldige datum/tijd in JJJJ-MM-DD UU:MM formaat."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:562
|
#: db/models/fields/__init__.py:562
|
||||||
msgid "Enter a valid filename."
|
msgid "Enter a valid filename."
|
||||||
@ -116,7 +116,7 @@ msgstr "Frans"
|
|||||||
|
|
||||||
#: conf/global_settings.py:46
|
#: conf/global_settings.py:46
|
||||||
msgid "Galician"
|
msgid "Galician"
|
||||||
msgstr "Galisisch"
|
msgstr "Galicisch"
|
||||||
|
|
||||||
#: conf/global_settings.py:47
|
#: conf/global_settings.py:47
|
||||||
msgid "Hungarian"
|
msgid "Hungarian"
|
||||||
@ -176,7 +176,7 @@ msgstr "Zweeds"
|
|||||||
|
|
||||||
#: conf/global_settings.py:61
|
#: conf/global_settings.py:61
|
||||||
msgid "Ukrainian"
|
msgid "Ukrainian"
|
||||||
msgstr "Ukraiens"
|
msgstr "Oekraïens"
|
||||||
|
|
||||||
#: conf/global_settings.py:62
|
#: conf/global_settings.py:62
|
||||||
msgid "Simplified Chinese"
|
msgid "Simplified Chinese"
|
||||||
@ -220,11 +220,11 @@ msgstr "Geef een geldig IP adres op."
|
|||||||
|
|
||||||
#: core/validators.py:103
|
#: core/validators.py:103
|
||||||
msgid "Empty values are not allowed here."
|
msgid "Empty values are not allowed here."
|
||||||
msgstr "Lege waarden niet toegestaan."
|
msgstr "Lege waarden zijn hier niet toegestaan."
|
||||||
|
|
||||||
#: core/validators.py:107
|
#: core/validators.py:107
|
||||||
msgid "Non-numeric characters aren't allowed here."
|
msgid "Non-numeric characters aren't allowed here."
|
||||||
msgstr "Niet-numerieke karakters niet toegestaan."
|
msgstr "Niet-numerieke karakters zijn hier niet toegestaan."
|
||||||
|
|
||||||
#: core/validators.py:111
|
#: core/validators.py:111
|
||||||
msgid "This value can't be comprised solely of digits."
|
msgid "This value can't be comprised solely of digits."
|
||||||
@ -244,7 +244,7 @@ msgstr "Geef een geldige datum in JJJJ-MM-DD formaat."
|
|||||||
|
|
||||||
#: core/validators.py:128
|
#: core/validators.py:128
|
||||||
msgid "Enter a valid time in HH:MM format."
|
msgid "Enter a valid time in HH:MM format."
|
||||||
msgstr "Geef een geldige tijd in HH:MM formaat."
|
msgstr "Geef een geldige tijd in UU:MM formaat."
|
||||||
|
|
||||||
#: core/validators.py:136
|
#: core/validators.py:136
|
||||||
msgid "Enter a valid e-mail address."
|
msgid "Enter a valid e-mail address."
|
||||||
@ -321,7 +321,7 @@ msgstr "Dit veld moet overeenkomen met het '%s' veld."
|
|||||||
|
|
||||||
#: core/validators.py:255
|
#: core/validators.py:255
|
||||||
msgid "Please enter something for at least one field."
|
msgid "Please enter something for at least one field."
|
||||||
msgstr "Geef in minimaal één veld een waarde."
|
msgstr "Voer tenminste één veld in."
|
||||||
|
|
||||||
#: core/validators.py:264 core/validators.py:275
|
#: core/validators.py:264 core/validators.py:275
|
||||||
msgid "Please enter both fields or leave them both empty."
|
msgid "Please enter both fields or leave them both empty."
|
||||||
@ -355,26 +355,26 @@ msgstr "Geef een geldig decimaal getal."
|
|||||||
msgid "Please enter a valid decimal number with at most %s total digit."
|
msgid "Please enter a valid decimal number with at most %s total digit."
|
||||||
msgid_plural ""
|
msgid_plural ""
|
||||||
"Please enter a valid decimal number with at most %s total digits."
|
"Please enter a valid decimal number with at most %s total digits."
|
||||||
msgstr[0] "Geef een geldig decimaal getal met maximaal %s cijfer."
|
msgstr[0] "Geef een geldig decimaal getal met hooguit %s cijfer."
|
||||||
msgstr[1] "Geef een geldig decimaal getal met maximaal %s cijfers."
|
msgstr[1] "Geef een geldig decimaal getal met hooguit %s cijfers."
|
||||||
|
|
||||||
#: core/validators.py:352
|
#: core/validators.py:352
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Please enter a valid decimal number with at most %s decimal place."
|
msgid "Please enter a valid decimal number with at most %s decimal place."
|
||||||
msgid_plural ""
|
msgid_plural ""
|
||||||
"Please enter a valid decimal number with at most %s decimal places."
|
"Please enter a valid decimal number with at most %s decimal places."
|
||||||
msgstr[0] "Geef een decimaal getal met maximaal %s cijfer achter de komma."
|
msgstr[0] "Geef een decimaal getal met hooguit %s cijfer achter de komma."
|
||||||
msgstr[1] "Geef een decimaal getal met maximaal %s cijfers achter de komma."
|
msgstr[1] "Geef een decimaal getal met hooguit %s cijfers achter de komma."
|
||||||
|
|
||||||
#: core/validators.py:362
|
#: core/validators.py:362
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Make sure your uploaded file is at least %s bytes big."
|
msgid "Make sure your uploaded file is at least %s bytes big."
|
||||||
msgstr "Zorg ervoor dat het bestand minimaal %s bytes groot is."
|
msgstr "Zorg ervoor dat het bestand minstens %s bytes groot is."
|
||||||
|
|
||||||
#: core/validators.py:363
|
#: core/validators.py:363
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Make sure your uploaded file is at most %s bytes big."
|
msgid "Make sure your uploaded file is at most %s bytes big."
|
||||||
msgstr "Zorg ervoor dat het bestand maximaal %s bytes groot is."
|
msgstr "Zorg ervoor dat het bestand hoogstens %s bytes groot is."
|
||||||
|
|
||||||
#: core/validators.py:376
|
#: core/validators.py:376
|
||||||
msgid "The format for this field is wrong."
|
msgid "The format for this field is wrong."
|
||||||
@ -456,7 +456,7 @@ msgid ""
|
|||||||
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
|
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
|
||||||
"required for logging in."
|
"required for logging in."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Het lijkt erop dat uw browser geen cookies accepteerd. Om u aan te melden "
|
"Het lijkt erop dat uw browser geen cookies accepteerd. Om aan te melden "
|
||||||
"moeten cookies worden geaccepteerd."
|
"moeten cookies worden geaccepteerd."
|
||||||
|
|
||||||
#: contrib/auth/forms.py:36 contrib/auth/forms.py:41
|
#: contrib/auth/forms.py:36 contrib/auth/forms.py:41
|
||||||
@ -465,7 +465,7 @@ msgid ""
|
|||||||
"Please enter a correct username and password. Note that both fields are case-"
|
"Please enter a correct username and password. Note that both fields are case-"
|
||||||
"sensitive."
|
"sensitive."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Geef een correcte gebruikersnaam en wachtwoord. Let op de velden zijn "
|
"Voer een correcte gebruikersnaam en wachtwoord in. Let op, de velden zijn "
|
||||||
"hoofdletter-gevoelig."
|
"hoofdletter-gevoelig."
|
||||||
|
|
||||||
#: contrib/auth/models.py:13 contrib/auth/models.py:26
|
#: contrib/auth/models.py:13 contrib/auth/models.py:26
|
||||||
@ -522,7 +522,7 @@ msgstr "staf status"
|
|||||||
|
|
||||||
#: contrib/auth/models.py:60
|
#: contrib/auth/models.py:60
|
||||||
msgid "Designates whether the user can log into this admin site."
|
msgid "Designates whether the user can log into this admin site."
|
||||||
msgstr "Bepaalt of de gebruiker kan inloggen op deze admin site"
|
msgstr "Bepaalt of de gebruiker kan inloggen op deze admin site."
|
||||||
|
|
||||||
#: contrib/auth/models.py:61
|
#: contrib/auth/models.py:61
|
||||||
msgid "active"
|
msgid "active"
|
||||||
@ -682,7 +682,7 @@ msgstr "Gebruikersnamen mogen geen '@' bevatten."
|
|||||||
#: contrib/admin/views/decorators.py:84
|
#: contrib/admin/views/decorators.py:84
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Your e-mail address is not your username. Try '%s' instead."
|
msgid "Your e-mail address is not your username. Try '%s' instead."
|
||||||
msgstr "Uw e-mail adres is niet uw gebruikersnaam. Probeer '%s' eens."
|
msgstr "Uw e-mailadres is niet uw gebruikersnaam. Probeer '%s' eens."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:226
|
#: contrib/admin/views/main.py:226
|
||||||
msgid "Site administration"
|
msgid "Site administration"
|
||||||
@ -734,13 +734,13 @@ msgstr "Geen velden gewijzigd."
|
|||||||
#: contrib/admin/views/main.py:346
|
#: contrib/admin/views/main.py:346
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(name)s \"%(obj)s\" was changed successfully."
|
msgid "The %(name)s \"%(obj)s\" was changed successfully."
|
||||||
msgstr "Wijzigen %(name)s \"%(obj)s\" is geslaagd."
|
msgstr "Het wijzigen van %(name)s \"%(obj)s\" is geslaagd."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:354
|
#: contrib/admin/views/main.py:354
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
|
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
|
||||||
msgstr "De %(name)s \"%(obj)s\" toegevoegd. U kunt het hieronder wijzigen."
|
msgstr "De %(name)s \"%(obj)s\" was toegevoegd. U kunt het hieronder wijzigen."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:392
|
#: contrib/admin/views/main.py:392
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -760,7 +760,7 @@ msgstr "Een of meer %(fieldname)s in %(name)s:"
|
|||||||
#: contrib/admin/views/main.py:508
|
#: contrib/admin/views/main.py:508
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
|
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
|
||||||
msgstr "Verwijdering %(name)s \"%(obj)s\" is geslaagd."
|
msgstr "De verwijdering van %(name)s \"%(obj)s\" is geslaagd."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:511
|
#: contrib/admin/views/main.py:511
|
||||||
msgid "Are you sure?"
|
msgid "Are you sure?"
|
||||||
@ -769,7 +769,7 @@ msgstr "Weet u het zeker?"
|
|||||||
#: contrib/admin/views/main.py:533
|
#: contrib/admin/views/main.py:533
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Change history: %s"
|
msgid "Change history: %s"
|
||||||
msgstr "Wijzigingshistorie: %s"
|
msgstr "Wijzigingsgeschiedenis: %s"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:565
|
#: contrib/admin/views/main.py:565
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -794,7 +794,7 @@ msgstr "Boolean (True of False)"
|
|||||||
#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
|
#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "String (up to %(maxlength)s)"
|
msgid "String (up to %(maxlength)s)"
|
||||||
msgstr "Karakterreeks (maximaal %(maxlength)s)"
|
msgstr "Karakterreeks (hooguit %(maxlength)s)"
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:280
|
#: contrib/admin/views/doc.py:280
|
||||||
msgid "Comma-separated integers"
|
msgid "Comma-separated integers"
|
||||||
@ -939,9 +939,9 @@ msgid ""
|
|||||||
"objects, but your account doesn't have permission to delete the following "
|
"objects, but your account doesn't have permission to delete the following "
|
||||||
"types of objects:"
|
"types of objects:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Verwijderen van %(object_name)s '%(object)s' zal ook gerelateerde objecten "
|
"Het verwijderen van %(object_name)s '%(object)s' zal ook gerelateerde "
|
||||||
"verwijderen. Echter u heeft geen rechten om de volgende typen objecten te "
|
"objecten verwijderen. Echter u heeft geen rechten om de volgende typen "
|
||||||
"verwijderen:"
|
"objecten te verwijderen:"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/delete_confirmation.html:21
|
#: contrib/admin/templates/admin/delete_confirmation.html:21
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -963,7 +963,7 @@ msgstr "Pagina niet gevonden"
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin/404.html:10
|
#: contrib/admin/templates/admin/404.html:10
|
||||||
msgid "We're sorry, but the requested page could not be found."
|
msgid "We're sorry, but the requested page could not be found."
|
||||||
msgstr "De gevraagde pagina komt niet voor."
|
msgstr "Onze excuses, maar de gevraagde pagina komt niet voor."
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/change_form.html:15
|
#: contrib/admin/templates/admin/change_form.html:15
|
||||||
#: contrib/admin/templates/admin/index.html:28
|
#: contrib/admin/templates/admin/index.html:28
|
||||||
@ -1073,8 +1073,8 @@ msgid ""
|
|||||||
"This object doesn't have a change history. It probably wasn't added via this "
|
"This object doesn't have a change history. It probably wasn't added via this "
|
||||||
"admin site."
|
"admin site."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Dit object heeft geen geschiedenis. Mogelijk niet via de admin site "
|
"Dit object heeft geen wijzigingsgeschiedenis. Het is mogelijk niet via de "
|
||||||
"toegevoegd."
|
"admin site toegevoegd."
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/500.html:4
|
#: contrib/admin/templates/admin/500.html:4
|
||||||
msgid "Server error"
|
msgid "Server error"
|
||||||
@ -1093,9 +1093,8 @@ msgid ""
|
|||||||
"There's been an error. It's been reported to the site administrators via e-"
|
"There's been an error. It's been reported to the site administrators via e-"
|
||||||
"mail and should be fixed shortly. Thanks for your patience."
|
"mail and should be fixed shortly. Thanks for your patience."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Er is een fout opgetreden. Dit is inmiddels doorgegevens aan de "
|
"Er is een fout opgetreden. Dit is inmiddels doorgegeven aan de sitebeheerder "
|
||||||
"sitebeheerder via e-mail en zal binnenkort worden gerepareerd. Bedankt voor "
|
"via e-mail en zal spoedig worden gerepareerd. Bedankt voor uw geduld."
|
||||||
"uw geduld"
|
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/search_form.html:8
|
#: contrib/admin/templates/admin/search_form.html:8
|
||||||
msgid "Go"
|
msgid "Go"
|
||||||
@ -1188,7 +1187,7 @@ msgstr "Bewerk dit object (nieuwe pagina)"
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:29
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:29
|
||||||
msgid "As above, but opens the admin page in a new window."
|
msgid "As above, but opens the admin page in a new window."
|
||||||
msgstr "Als boven, maar opent de beheerpagina in een nieuw venster."
|
msgstr "Zoals hierboven, maar opent de beheerpagina in een nieuw venster."
|
||||||
|
|
||||||
#: contrib/admin/templates/widget/date_time.html:3
|
#: contrib/admin/templates/widget/date_time.html:3
|
||||||
msgid "Date:"
|
msgid "Date:"
|
||||||
@ -1218,8 +1217,8 @@ msgid ""
|
|||||||
"Forgotten your password? Enter your e-mail address below, and we'll reset "
|
"Forgotten your password? Enter your e-mail address below, and we'll reset "
|
||||||
"your password and e-mail the new one to you."
|
"your password and e-mail the new one to you."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Wachtwoord vergeten? Geef u e-mail adres op en we herstellen uw wachtwoord "
|
"Uw wachtwoord vergeten? Geef uw e-mailadres op en er zal een nieuw "
|
||||||
"en zullen u het nieuwe wachtwoord per e-mail toesturen."
|
"wachtwoord worden toegekend en aan u worden toegezonden."
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_form.html:16
|
#: contrib/admin/templates/registration/password_reset_form.html:16
|
||||||
msgid "E-mail address:"
|
msgid "E-mail address:"
|
||||||
@ -1231,7 +1230,7 @@ msgstr "Herstel mijn wachtwoord"
|
|||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_email.html:2
|
#: contrib/admin/templates/registration/password_reset_email.html:2
|
||||||
msgid "You're receiving this e-mail because you requested a password reset"
|
msgid "You're receiving this e-mail because you requested a password reset"
|
||||||
msgstr "U krijgt een e-mail omdat u om een nieuw wachtwoord heeft gevraagd"
|
msgstr "U krijgt deze e-mail omdat u om een nieuw wachtwoord heeft gevraagd"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_email.html:3
|
#: contrib/admin/templates/registration/password_reset_email.html:3
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -1278,8 +1277,7 @@ msgid ""
|
|||||||
"We've e-mailed a new password to the e-mail address you submitted. You "
|
"We've e-mailed a new password to the e-mail address you submitted. You "
|
||||||
"should be receiving it shortly."
|
"should be receiving it shortly."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Een nieuw wachtwoord is per e-mail verstuurd. U zult het binnenkort "
|
"Een nieuw wachtwoord is per e-mail verstuurd. U zult het spoedig ontvangen."
|
||||||
"ontvangen."
|
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:4
|
#: contrib/admin/templates/registration/password_change_form.html:4
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:6
|
#: contrib/admin/templates/registration/password_change_form.html:6
|
||||||
@ -1293,8 +1291,8 @@ msgid ""
|
|||||||
"Please enter your old password, for security's sake, and then enter your new "
|
"Please enter your old password, for security's sake, and then enter your new "
|
||||||
"password twice so we can verify you typed it in correctly."
|
"password twice so we can verify you typed it in correctly."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Geef voor de veiligheid uw oude wachtwoord op en twee keer een nieuw "
|
"Vanwege de beveiliging moet u uw oude en twee keer een nieuw wachtwoord"
|
||||||
"wachtwoord, zodat we kunnen controleren of er geen typefouten zijn gemaakt."
|
"invoeren, zodat we kunnen controleren of er geen typefouten zijn gemaakt."
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:17
|
#: contrib/admin/templates/registration/password_change_form.html:17
|
||||||
msgid "Old password:"
|
msgid "Old password:"
|
||||||
@ -1340,7 +1338,8 @@ msgstr "sites"
|
|||||||
#: contrib/flatpages/models.py:8
|
#: contrib/flatpages/models.py:8
|
||||||
msgid ""
|
msgid ""
|
||||||
"Example: '/about/contact/'. Make sure to have leading and trailing slashes."
|
"Example: '/about/contact/'. Make sure to have leading and trailing slashes."
|
||||||
msgstr "Voorbeeld: '/about/contact/'. Zorg voor slashes aan begin en eind"
|
msgstr ""
|
||||||
|
"Voorbeeld: '/about/contact/'. Zorg voor slashes aan het begin en eind."
|
||||||
|
|
||||||
#: contrib/flatpages/models.py:9
|
#: contrib/flatpages/models.py:9
|
||||||
msgid "title"
|
msgid "title"
|
||||||
@ -1373,8 +1372,8 @@ msgstr "registratie verplicht"
|
|||||||
#: contrib/flatpages/models.py:14
|
#: contrib/flatpages/models.py:14
|
||||||
msgid "If this is checked, only logged-in users will be able to view the page."
|
msgid "If this is checked, only logged-in users will be able to view the page."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Alleen ingelogde gebruikers kunnen deze pagina zien, indien dit is "
|
"Indien dit is aangekruist kunnen alleen ingelogde gebruikers deze pagina "
|
||||||
"aangekruist."
|
"bekijken."
|
||||||
|
|
||||||
#: contrib/flatpages/models.py:18
|
#: contrib/flatpages/models.py:18
|
||||||
msgid "flat page"
|
msgid "flat page"
|
||||||
@ -1405,8 +1404,8 @@ msgid ""
|
|||||||
"This can be either an absolute path (as above) or a full URL starting with "
|
"This can be either an absolute path (as above) or a full URL starting with "
|
||||||
"'http://'."
|
"'http://'."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Dit kan een absoluut pad zijn (zoals boven) of een volledige URL beginnend "
|
"Dit kan een absoluut pad (zoals hierboven) zijn of een volledige URL "
|
||||||
"met 'http://'."
|
"beginnend met 'http://'."
|
||||||
|
|
||||||
#: contrib/redirects/models.py:12
|
#: contrib/redirects/models.py:12
|
||||||
msgid "redirect"
|
msgid "redirect"
|
||||||
@ -1471,7 +1470,7 @@ msgstr "datum/tijd toegevoegd"
|
|||||||
|
|
||||||
#: contrib/comments/models.py:84 contrib/comments/models.py:170
|
#: contrib/comments/models.py:84 contrib/comments/models.py:170
|
||||||
msgid "is public"
|
msgid "is public"
|
||||||
msgstr "is publiek"
|
msgstr "is openbaar"
|
||||||
|
|
||||||
#: contrib/comments/models.py:86
|
#: contrib/comments/models.py:86
|
||||||
msgid "is removed"
|
msgid "is removed"
|
||||||
@ -1518,7 +1517,7 @@ msgstr "ip adres"
|
|||||||
|
|
||||||
#: contrib/comments/models.py:173
|
#: contrib/comments/models.py:173
|
||||||
msgid "approved by staff"
|
msgid "approved by staff"
|
||||||
msgstr "goegekeurd door de staf"
|
msgstr "goedgekeurd door de staf"
|
||||||
|
|
||||||
#: contrib/comments/models.py:176
|
#: contrib/comments/models.py:176
|
||||||
msgid "free comment"
|
msgid "free comment"
|
||||||
@ -1604,14 +1603,14 @@ msgstr "Ongeldige opmerkingen ID"
|
|||||||
|
|
||||||
#: contrib/comments/views/karma.py:25
|
#: contrib/comments/views/karma.py:25
|
||||||
msgid "No voting for yourself"
|
msgid "No voting for yourself"
|
||||||
msgstr "Niet op jezelf stemmen"
|
msgstr "Niet op uzelf stemmen"
|
||||||
|
|
||||||
#: contrib/comments/views/comments.py:28
|
#: contrib/comments/views/comments.py:28
|
||||||
msgid ""
|
msgid ""
|
||||||
"This rating is required because you've entered at least one other rating."
|
"This rating is required because you've entered at least one other rating."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Deze waardering is verplicht omdat je op zijn minst een andere waardering "
|
"Deze waardering is verplicht omdat u tenminste één andere waardering hebt "
|
||||||
"hebt ingevoerd."
|
"ingevoerd."
|
||||||
|
|
||||||
#: contrib/comments/views/comments.py:112
|
#: contrib/comments/views/comments.py:112
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -1626,13 +1625,13 @@ msgid_plural ""
|
|||||||
"\n"
|
"\n"
|
||||||
"%(text)s"
|
"%(text)s"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
"Deze opmerking is gepost door een gebruiker welke minder dan %(count)s opmerking "
|
"Deze opmerking is gepost door een gebruiker die minder dan %(count)s "
|
||||||
"heeft gepost:\n"
|
"opmerking heeft gepost:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"%(text)s"
|
"%(text)s"
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
"Deze opmerking is gepost door een gebruiker welke minder dan %(count)s opmerkingen "
|
"Deze opmerking is gepost door een gebruiker die minder dan %(count)s "
|
||||||
"heeft gepost:\n"
|
"opmerkingen heeft gepost:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"%(text)s"
|
"%(text)s"
|
||||||
|
|
||||||
@ -1655,7 +1654,7 @@ msgstr "Alleen POSTs zijn toegestaan"
|
|||||||
#: contrib/comments/views/comments.py:193
|
#: contrib/comments/views/comments.py:193
|
||||||
#: contrib/comments/views/comments.py:284
|
#: contrib/comments/views/comments.py:284
|
||||||
msgid "One or more of the required fields wasn't submitted"
|
msgid "One or more of the required fields wasn't submitted"
|
||||||
msgstr "Een of meerdere verplichte velden is niet ingevuld"
|
msgstr "Een of meerdere verplichte velden zijn niet ingevuld"
|
||||||
|
|
||||||
#: contrib/comments/views/comments.py:197
|
#: contrib/comments/views/comments.py:197
|
||||||
#: contrib/comments/views/comments.py:286
|
#: contrib/comments/views/comments.py:286
|
||||||
@ -1710,7 +1709,7 @@ msgstr "Concept opmerking"
|
|||||||
|
|
||||||
#: contrib/comments/templates/comments/freeform.html:4
|
#: contrib/comments/templates/comments/freeform.html:4
|
||||||
msgid "Your name:"
|
msgid "Your name:"
|
||||||
msgstr "Uw gebruikernaam:"
|
msgstr "Uw gebruikersnaam:"
|
||||||
|
|
||||||
#: contrib/sessions/models.py:35
|
#: contrib/sessions/models.py:35
|
||||||
msgid "session key"
|
msgid "session key"
|
||||||
@ -1738,18 +1737,18 @@ msgstr "python model-class-naam"
|
|||||||
|
|
||||||
#: contrib/contenttypes/models.py:28
|
#: contrib/contenttypes/models.py:28
|
||||||
msgid "content type"
|
msgid "content type"
|
||||||
msgstr "inhoudtype"
|
msgstr "inhoudstype"
|
||||||
|
|
||||||
#: contrib/contenttypes/models.py:29
|
#: contrib/contenttypes/models.py:29
|
||||||
msgid "content types"
|
msgid "content types"
|
||||||
msgstr "inhoudtypen"
|
msgstr "inhoudstypen"
|
||||||
|
|
||||||
#: forms/__init__.py:380
|
#: forms/__init__.py:380
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Ensure your text is less than %s character."
|
msgid "Ensure your text is less than %s character."
|
||||||
msgid_plural "Ensure your text is less than %s characters."
|
msgid_plural "Ensure your text is less than %s characters."
|
||||||
msgstr[0] "Zorg ervoor dat uw tekst korter is dan %s teken."
|
msgstr[0] "Zorg ervoor dat uw tekst korter is dan %s karakter."
|
||||||
msgstr[1] "Zorg ervoor dat uw tekst korter is dan %S tekens."
|
msgstr[1] "Zorg ervoor dat uw tekst korter is dan %s karakters."
|
||||||
|
|
||||||
#: forms/__init__.py:385
|
#: forms/__init__.py:385
|
||||||
msgid "Line breaks are not allowed here."
|
msgid "Line breaks are not allowed here."
|
||||||
@ -1778,31 +1777,31 @@ msgstr "Geef een geheel getal op tussen 0 en 32.767."
|
|||||||
|
|
||||||
#: utils/dates.py:6
|
#: utils/dates.py:6
|
||||||
msgid "Monday"
|
msgid "Monday"
|
||||||
msgstr "Maandag"
|
msgstr "maandag"
|
||||||
|
|
||||||
#: utils/dates.py:6
|
#: utils/dates.py:6
|
||||||
msgid "Tuesday"
|
msgid "Tuesday"
|
||||||
msgstr "Dinsdag"
|
msgstr "dinsdag"
|
||||||
|
|
||||||
#: utils/dates.py:6
|
#: utils/dates.py:6
|
||||||
msgid "Wednesday"
|
msgid "Wednesday"
|
||||||
msgstr "Woensdag"
|
msgstr "woensdag"
|
||||||
|
|
||||||
#: utils/dates.py:6
|
#: utils/dates.py:6
|
||||||
msgid "Thursday"
|
msgid "Thursday"
|
||||||
msgstr "Donderdag"
|
msgstr "donderdag"
|
||||||
|
|
||||||
#: utils/dates.py:6
|
#: utils/dates.py:6
|
||||||
msgid "Friday"
|
msgid "Friday"
|
||||||
msgstr "Vrijdag"
|
msgstr "vrijdag"
|
||||||
|
|
||||||
#: utils/dates.py:7
|
#: utils/dates.py:7
|
||||||
msgid "Saturday"
|
msgid "Saturday"
|
||||||
msgstr "Zaterdag"
|
msgstr "zaterdag"
|
||||||
|
|
||||||
#: utils/dates.py:7
|
#: utils/dates.py:7
|
||||||
msgid "Sunday"
|
msgid "Sunday"
|
||||||
msgstr "Zondag"
|
msgstr "zondag"
|
||||||
|
|
||||||
#: utils/dates.py:14
|
#: utils/dates.py:14
|
||||||
msgid "January"
|
msgid "January"
|
||||||
@ -1890,7 +1889,7 @@ msgstr "sep"
|
|||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "oct"
|
msgid "oct"
|
||||||
msgstr "oct"
|
msgstr "okt"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "nov"
|
msgid "nov"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from django.conf.urls.defaults import *
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
(r'^login/$', 'django.contrib.auth.view.login'),
|
(r'^login/$', 'django.contrib.auth.views.login'),
|
||||||
(r'^logout/$', 'django.contrib.auth.views.logout'),
|
(r'^logout/$', 'django.contrib.auth.views.logout'),
|
||||||
(r'^login_another/$', 'django.contrib.auth.views.logout_then_login'),
|
(r'^login_another/$', 'django.contrib.auth.views.logout_then_login'),
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#changelist { position:relative; width:100%; }
|
#changelist { position:relative; width:100%; }
|
||||||
#changelist table { width:100%; }
|
#changelist table { width:100%; }
|
||||||
.change-list .filtered table { border-right:1px solid #ddd; }
|
.change-list .filtered table { border-right:1px solid #ddd; }
|
||||||
.change-list .filtered { min-height:400px; _height:400px; }
|
.change-list .filtered { min-height:400px; }
|
||||||
.change-list .filtered { background:white url(../img/admin/changelist-bg.gif) top right repeat-y !important; }
|
.change-list .filtered { background:white url(../img/admin/changelist-bg.gif) top right repeat-y !important; }
|
||||||
.change-list .filtered table, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { margin-right:160px !important; width:auto !important; }
|
.change-list .filtered table, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { margin-right:160px !important; width:auto !important; }
|
||||||
.change-list .filtered table tbody th { padding-right:1em; }
|
.change-list .filtered table tbody th { padding-right:1em; }
|
||||||
@ -27,7 +27,7 @@
|
|||||||
#changelist-filter { position:absolute; top:0; right:0; z-index:1000; width:160px; border-left:1px solid #ddd; background:#efefef; margin:0; }
|
#changelist-filter { position:absolute; top:0; right:0; z-index:1000; width:160px; border-left:1px solid #ddd; background:#efefef; margin:0; }
|
||||||
#changelist-filter h2 { font-size:11px; padding:2px 5px; border-bottom:1px solid #ddd; }
|
#changelist-filter h2 { font-size:11px; padding:2px 5px; border-bottom:1px solid #ddd; }
|
||||||
#changelist-filter h3 { font-size:12px; margin-bottom:0; }
|
#changelist-filter h3 { font-size:12px; margin-bottom:0; }
|
||||||
#changelist-filter ul { padding-left:0;margin-left:10px;_margin-right:-10px; }
|
#changelist-filter ul { padding-left:0;margin-left:10px; }
|
||||||
#changelist-filter li { list-style-type:none; margin-left:0; padding-left:0; }
|
#changelist-filter li { list-style-type:none; margin-left:0; padding-left:0; }
|
||||||
#changelist-filter a { color:#999; }
|
#changelist-filter a { color:#999; }
|
||||||
#changelist-filter a:hover { color:#036; }
|
#changelist-filter a:hover { color:#036; }
|
||||||
|
@ -86,7 +86,7 @@ textarea { vertical-align:top !important; }
|
|||||||
input[type=text], input[type=password], textarea, select, .vTextField { border:1px solid #ccc; }
|
input[type=text], input[type=password], textarea, select, .vTextField { border:1px solid #ccc; }
|
||||||
|
|
||||||
/* FORM BUTTONS */
|
/* FORM BUTTONS */
|
||||||
input[type=submit], input[type=button], .submit-row input { background:white url(../img/admin/nav-bg.gif) bottom repeat-x; padding:3px; color:black; }
|
input[type=submit], input[type=button], .submit-row input { background:white url(../img/admin/nav-bg.gif) bottom repeat-x; padding:3px; color:black; border:1px solid #bbb; border-color:#ddd #aaa #aaa #ddd; }
|
||||||
input[type=submit]:active, input[type=button]:active { background-image:url(../img/admin/nav-bg-reverse.gif); background-position:top; }
|
input[type=submit]:active, input[type=button]:active { background-image:url(../img/admin/nav-bg-reverse.gif); background-position:top; }
|
||||||
input[type=submit].default, .submit-row input.default { border:2px solid #5b80b2; background:#7CA0C7 url(../img/admin/default-bg.gif) bottom repeat-x; font-weight:bold; color:white; }
|
input[type=submit].default, .submit-row input.default { border:2px solid #5b80b2; background:#7CA0C7 url(../img/admin/default-bg.gif) bottom repeat-x; font-weight:bold; color:white; }
|
||||||
input[type=submit].default:active { background-image:url(../img/admin/default-bg-reverse.gif); background-position:top; }
|
input[type=submit].default:active { background-image:url(../img/admin/default-bg-reverse.gif); background-position:top; }
|
||||||
|
@ -3,13 +3,13 @@
|
|||||||
#content { margin:10px 15px; }
|
#content { margin:10px 15px; }
|
||||||
#header { width:100%; }
|
#header { width:100%; }
|
||||||
#content-main { float:left; width:100%; }
|
#content-main { float:left; width:100%; }
|
||||||
#content-related { float:right; width:220px; position:relative; margin-right:-230px; }
|
#content-related { float:right; width:18em; position:relative; margin-right:-19em; }
|
||||||
#footer { clear:both; padding:10px; }
|
#footer { clear:both; padding:10px; }
|
||||||
|
|
||||||
/* COLUMN TYPES */
|
/* COLUMN TYPES */
|
||||||
.colMS { margin-right:245px !important; }
|
.colMS { margin-right:20em !important; }
|
||||||
.colSM { margin-left:245px !important; }
|
.colSM { margin-left:20em !important; }
|
||||||
.colSM #content-related { float:left; margin-right:0; margin-left:-230px; }
|
.colSM #content-related { float:left; margin-right:0; margin-left:-19em; }
|
||||||
.colSM #content-main { float:right; }
|
.colSM #content-main { float:right; }
|
||||||
.popup .colM { width:95%; }
|
.popup .colM { width:95%; }
|
||||||
.subcol { float:left; width:46%; margin-right:15px; }
|
.subcol { float:left; width:46%; margin-right:15px; }
|
||||||
|
@ -4,3 +4,5 @@
|
|||||||
* html .form-row { height:1%; }
|
* html .form-row { height:1%; }
|
||||||
* html .dashboard #content { width:768px; } /* proper fixed width for dashboard in IE6 */
|
* html .dashboard #content { width:768px; } /* proper fixed width for dashboard in IE6 */
|
||||||
* html .dashboard #content-main { width:535px; } /* proper fixed width for dashboard in IE6 */
|
* html .dashboard #content-main { width:535px; } /* proper fixed width for dashboard in IE6 */
|
||||||
|
* html #changelist-filter ul { margin-right:-10px; } /* fix right margin for changelist filters in IE6 */
|
||||||
|
* html .change-list .filtered { height:400px; } /* IE ignores min-height, but treats height as if it were min-height */
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
function showRelatedObjectLookupPopup(triggeringLink) {
|
function showRelatedObjectLookupPopup(triggeringLink) {
|
||||||
var name = triggeringLink.id.replace(/^lookup_/, '');
|
var name = triggeringLink.id.replace(/^lookup_/, '');
|
||||||
|
// IE doesn't like periods in the window name, so convert temporarily.
|
||||||
|
name = name.replace(/\./g, '___');
|
||||||
var href;
|
var href;
|
||||||
if (triggeringLink.href.search(/\?/) >= 0) {
|
if (triggeringLink.href.search(/\?/) >= 0) {
|
||||||
href = triggeringLink.href + '&pop=1';
|
href = triggeringLink.href + '&pop=1';
|
||||||
@ -15,11 +17,12 @@ function showRelatedObjectLookupPopup(triggeringLink) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function dismissRelatedLookupPopup(win, chosenId) {
|
function dismissRelatedLookupPopup(win, chosenId) {
|
||||||
var elem = document.getElementById(win.name);
|
var name = win.name.replace(/___/g, '.');
|
||||||
|
var elem = document.getElementById(name);
|
||||||
if (elem.className.indexOf('vRawIdAdminField') != -1 && elem.value) {
|
if (elem.className.indexOf('vRawIdAdminField') != -1 && elem.value) {
|
||||||
elem.value += ',' + chosenId;
|
elem.value += ',' + chosenId;
|
||||||
} else {
|
} else {
|
||||||
document.getElementById(win.name).value = chosenId;
|
document.getElementById(name).value = chosenId;
|
||||||
}
|
}
|
||||||
win.close();
|
win.close();
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
<div id="branding">
|
<div id="branding">
|
||||||
{% block branding %}{% endblock %}
|
{% block branding %}{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
{% if not user.is_anonymous %}
|
{% if not user.is_anonymous %}{% if user.is_staff %}
|
||||||
<div id="user-tools">{% trans 'Welcome,' %} <strong>{% if user.first_name %}{{ user.first_name }}{% else %}{{ user.username }}{% endif %}</strong>. {% block userlinks %}<a href="doc/">{% trans 'Documentation' %}</a> / <a href="password_change/">{% trans 'Change password' %}</a> / <a href="logout/">{% trans 'Log out' %}</a>{% endblock %}</div>
|
<div id="user-tools">{% trans 'Welcome,' %} <strong>{% if user.first_name %}{{ user.first_name }}{% else %}{{ user.username }}{% endif %}</strong>. {% block userlinks %}<a href="doc/">{% trans 'Documentation' %}</a> / <a href="password_change/">{% trans 'Change password' %}</a> / <a href="logout/">{% trans 'Log out' %}</a>{% endblock %}</div>
|
||||||
{% endif %}
|
{% endif %}{% endif %}
|
||||||
{% block nav-global %}{% endblock %}
|
{% block nav-global %}{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
<!-- END Header -->
|
<!-- END Header -->
|
||||||
|
@ -2,14 +2,15 @@ from django import template
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.admin.views.main import MAX_SHOW_ALL_ALLOWED, ALL_VAR
|
from django.contrib.admin.views.main import MAX_SHOW_ALL_ALLOWED, ALL_VAR
|
||||||
from django.contrib.admin.views.main import ORDER_VAR, ORDER_TYPE_VAR, PAGE_VAR, SEARCH_VAR
|
from django.contrib.admin.views.main import ORDER_VAR, ORDER_TYPE_VAR, PAGE_VAR, SEARCH_VAR
|
||||||
from django.contrib.admin.views.main import IS_POPUP_VAR, EMPTY_CHANGELIST_VALUE, MONTHS
|
from django.contrib.admin.views.main import IS_POPUP_VAR, EMPTY_CHANGELIST_VALUE
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import dateformat
|
from django.utils import dateformat
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
from django.utils.translation import get_date_formats
|
from django.utils.translation import get_date_formats, get_partial_date_formats
|
||||||
from django.template import Library
|
from django.template import Library
|
||||||
|
import datetime
|
||||||
|
|
||||||
register = Library()
|
register = Library()
|
||||||
|
|
||||||
@ -193,18 +194,19 @@ def date_hierarchy(cl):
|
|||||||
year_lookup = cl.params.get(year_field)
|
year_lookup = cl.params.get(year_field)
|
||||||
month_lookup = cl.params.get(month_field)
|
month_lookup = cl.params.get(month_field)
|
||||||
day_lookup = cl.params.get(day_field)
|
day_lookup = cl.params.get(day_field)
|
||||||
|
year_month_format, month_day_format = get_partial_date_formats()
|
||||||
|
|
||||||
link = lambda d: cl.get_query_string(d, [field_generic])
|
link = lambda d: cl.get_query_string(d, [field_generic])
|
||||||
|
|
||||||
if year_lookup and month_lookup and day_lookup:
|
if year_lookup and month_lookup and day_lookup:
|
||||||
month_name = MONTHS[int(month_lookup)]
|
day = datetime.date(int(year_lookup), int(month_lookup), int(day_lookup))
|
||||||
return {
|
return {
|
||||||
'show': True,
|
'show': True,
|
||||||
'back': {
|
'back': {
|
||||||
'link': link({year_field: year_lookup, month_field: month_lookup}),
|
'link': link({year_field: year_lookup, month_field: month_lookup}),
|
||||||
'title': "%s %s" % (month_name, year_lookup)
|
'title': dateformat.format(day, year_month_format)
|
||||||
},
|
},
|
||||||
'choices': [{'title': "%s %s" % (month_name, day_lookup)}]
|
'choices': [{'title': dateformat.format(day, month_day_format)}]
|
||||||
}
|
}
|
||||||
elif year_lookup and month_lookup:
|
elif year_lookup and month_lookup:
|
||||||
days = cl.query_set.filter(**{year_field: year_lookup, month_field: month_lookup}).dates(field_name, 'day')
|
days = cl.query_set.filter(**{year_field: year_lookup, month_field: month_lookup}).dates(field_name, 'day')
|
||||||
@ -216,7 +218,7 @@ def date_hierarchy(cl):
|
|||||||
},
|
},
|
||||||
'choices': [{
|
'choices': [{
|
||||||
'link': link({year_field: year_lookup, month_field: month_lookup, day_field: day.day}),
|
'link': link({year_field: year_lookup, month_field: month_lookup, day_field: day.day}),
|
||||||
'title': day.strftime('%B %d')
|
'title': dateformat.format(day, month_day_format)
|
||||||
} for day in days]
|
} for day in days]
|
||||||
}
|
}
|
||||||
elif year_lookup:
|
elif year_lookup:
|
||||||
@ -229,7 +231,7 @@ def date_hierarchy(cl):
|
|||||||
},
|
},
|
||||||
'choices': [{
|
'choices': [{
|
||||||
'link': link({year_field: year_lookup, month_field: month.month}),
|
'link': link({year_field: year_lookup, month_field: month.month}),
|
||||||
'title': "%s %s" % (month.strftime('%B'), month.year)
|
'title': dateformat.format(month, year_month_format)
|
||||||
} for month in months]
|
} for month in months]
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
|
@ -81,12 +81,16 @@ ROLES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def create_reference_role(rolename, urlbase):
|
def create_reference_role(rolename, urlbase):
|
||||||
def _role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
def _role(name, rawtext, text, lineno, inliner, options=None, content=None):
|
||||||
|
if options is None: options = {}
|
||||||
|
if content is None: content = []
|
||||||
node = docutils.nodes.reference(rawtext, text, refuri=(urlbase % (inliner.document.settings.link_base, text.lower())), **options)
|
node = docutils.nodes.reference(rawtext, text, refuri=(urlbase % (inliner.document.settings.link_base, text.lower())), **options)
|
||||||
return [node], []
|
return [node], []
|
||||||
docutils.parsers.rst.roles.register_canonical_role(rolename, _role)
|
docutils.parsers.rst.roles.register_canonical_role(rolename, _role)
|
||||||
|
|
||||||
def default_reference_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
def default_reference_role(name, rawtext, text, lineno, inliner, options=None, content=None):
|
||||||
|
if options is None: options = {}
|
||||||
|
if content is None: content = []
|
||||||
context = inliner.document.settings.default_reference_context
|
context = inliner.document.settings.default_reference_context
|
||||||
node = docutils.nodes.reference(rawtext, text, refuri=(ROLES[context] % (inliner.document.settings.link_base, text.lower())), **options)
|
node = docutils.nodes.reference(rawtext, text, refuri=(ROLES[context] % (inliner.document.settings.link_base, text.lower())), **options)
|
||||||
return [node], []
|
return [node], []
|
||||||
|
@ -579,7 +579,9 @@ class ChangeList(object):
|
|||||||
filter_specs.append(spec)
|
filter_specs.append(spec)
|
||||||
return filter_specs, bool(filter_specs)
|
return filter_specs, bool(filter_specs)
|
||||||
|
|
||||||
def get_query_string(self, new_params={}, remove=[]):
|
def get_query_string(self, new_params=None, remove=None):
|
||||||
|
if new_params is None: new_params = {}
|
||||||
|
if remove is None: remove = []
|
||||||
p = self.params.copy()
|
p = self.params.copy()
|
||||||
for r in remove:
|
for r in remove:
|
||||||
for k in p.keys():
|
for k in p.keys():
|
||||||
|
@ -35,6 +35,8 @@ class AuthenticationForm(forms.Manipulator):
|
|||||||
self.user_cache = authenticate(username=username, password=password)
|
self.user_cache = authenticate(username=username, password=password)
|
||||||
if self.user_cache is None:
|
if self.user_cache is None:
|
||||||
raise validators.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
raise validators.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
||||||
|
elif not self.user_cache.is_active:
|
||||||
|
raise validators.ValidationError, _("This account is inactive.")
|
||||||
|
|
||||||
def get_user_id(self):
|
def get_user_id(self):
|
||||||
if self.user_cache:
|
if self.user_cache:
|
||||||
|
0
django/contrib/humanize/templatetags/__init__.py
Normal file
0
django/contrib/humanize/templatetags/__init__.py
Normal file
64
django/contrib/humanize/templatetags/humanize.py
Normal file
64
django/contrib/humanize/templatetags/humanize.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
from django import template
|
||||||
|
import re
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
def ordinal(value):
|
||||||
|
"""
|
||||||
|
Converts an integer to its ordinal as a string. 1 is '1st', 2 is '2nd',
|
||||||
|
3 is '3rd', etc. Works for any integer.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
value = int(value)
|
||||||
|
except ValueError:
|
||||||
|
return value
|
||||||
|
t = ('th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th')
|
||||||
|
if value % 100 in (11, 12, 13): # special case
|
||||||
|
return '%dth' % value
|
||||||
|
return '%d%s' % (value, t[value % 10])
|
||||||
|
register.filter(ordinal)
|
||||||
|
|
||||||
|
def intcomma(value):
|
||||||
|
"""
|
||||||
|
Converts an integer to a string containing commas every three digits.
|
||||||
|
For example, 3000 becomes '3,000' and 45000 becomes '45,000'.
|
||||||
|
"""
|
||||||
|
orig = str(value)
|
||||||
|
new = re.sub("^(-?\d+)(\d{3})", '\g<1>,\g<2>', str(value))
|
||||||
|
if orig == new:
|
||||||
|
return new
|
||||||
|
else:
|
||||||
|
return intcomma(new)
|
||||||
|
register.filter(intcomma)
|
||||||
|
|
||||||
|
def intword(value):
|
||||||
|
"""
|
||||||
|
Converts a large integer to a friendly text representation. Works best for
|
||||||
|
numbers over 1 million. For example, 1000000 becomes '1.0 million', 1200000
|
||||||
|
becomes '1.2 million' and '1200000000' becomes '1.2 billion'.
|
||||||
|
"""
|
||||||
|
value = int(value)
|
||||||
|
if value < 1000000:
|
||||||
|
return value
|
||||||
|
if value < 1000000000:
|
||||||
|
return '%.1f million' % (value / 1000000.0)
|
||||||
|
if value < 1000000000000:
|
||||||
|
return '%.1f billion' % (value / 1000000000.0)
|
||||||
|
if value < 1000000000000000:
|
||||||
|
return '%.1f trillion' % (value / 1000000000000.0)
|
||||||
|
return value
|
||||||
|
register.filter(intword)
|
||||||
|
|
||||||
|
def apnumber(value):
|
||||||
|
"""
|
||||||
|
For numbers 1-9, returns the number spelled out. Otherwise, returns the
|
||||||
|
number. This follows Associated Press style.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
value = int(value)
|
||||||
|
except ValueError:
|
||||||
|
return value
|
||||||
|
if not 0 < value < 10:
|
||||||
|
return value
|
||||||
|
return ('one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine')[value-1]
|
||||||
|
register.filter(apnumber)
|
@ -1055,7 +1055,9 @@ def run_shell(use_plain=False):
|
|||||||
# Don't bother loading IPython, because the user wants plain Python.
|
# Don't bother loading IPython, because the user wants plain Python.
|
||||||
raise ImportError
|
raise ImportError
|
||||||
import IPython
|
import IPython
|
||||||
shell = IPython.Shell.IPShell()
|
# Explicitly pass an empty list as arguments, because otherwise IPython
|
||||||
|
# would use sys.argv from this script.
|
||||||
|
shell = IPython.Shell.IPShell(argv=[])
|
||||||
shell.mainloop()
|
shell.mainloop()
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import code
|
import code
|
||||||
@ -1137,7 +1139,11 @@ def print_error(msg, cmd):
|
|||||||
sys.stderr.write(style.ERROR('Error: %s' % msg) + '\nRun "%s --help" for help.\n' % cmd)
|
sys.stderr.write(style.ERROR('Error: %s' % msg) + '\nRun "%s --help" for help.\n' % cmd)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING):
|
def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
|
||||||
|
# Use sys.argv if we've not passed in a custom argv
|
||||||
|
if argv is None:
|
||||||
|
argv = sys.argv
|
||||||
|
|
||||||
# Parse the command-line arguments. optparse handles the dirty work.
|
# Parse the command-line arguments. optparse handles the dirty work.
|
||||||
parser = DjangoOptionParser(usage=get_usage(action_mapping), version=get_version())
|
parser = DjangoOptionParser(usage=get_usage(action_mapping), version=get_version())
|
||||||
parser.add_option('--settings',
|
parser.add_option('--settings',
|
||||||
@ -1146,7 +1152,7 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING):
|
|||||||
help='Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".')
|
help='Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".')
|
||||||
parser.add_option('--plain', action='store_true', dest='plain',
|
parser.add_option('--plain', action='store_true', dest='plain',
|
||||||
help='Tells Django to use plain Python, not IPython, for "shell" command.')
|
help='Tells Django to use plain Python, not IPython, for "shell" command.')
|
||||||
options, args = parser.parse_args()
|
options, args = parser.parse_args(argv[1:])
|
||||||
|
|
||||||
# Take care of options.
|
# Take care of options.
|
||||||
if options.settings:
|
if options.settings:
|
||||||
@ -1161,7 +1167,7 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING):
|
|||||||
except IndexError:
|
except IndexError:
|
||||||
parser.print_usage_and_exit()
|
parser.print_usage_and_exit()
|
||||||
if not action_mapping.has_key(action):
|
if not action_mapping.has_key(action):
|
||||||
print_error("Your action, %r, was invalid." % action, sys.argv[0])
|
print_error("Your action, %r, was invalid." % action, argv[0])
|
||||||
|
|
||||||
# Switch to English, because django-admin.py creates database content
|
# Switch to English, because django-admin.py creates database content
|
||||||
# like permissions, and those shouldn't contain any translations.
|
# like permissions, and those shouldn't contain any translations.
|
||||||
@ -1220,7 +1226,7 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING):
|
|||||||
if action not in NO_SQL_TRANSACTION:
|
if action not in NO_SQL_TRANSACTION:
|
||||||
print style.SQL_KEYWORD("COMMIT;")
|
print style.SQL_KEYWORD("COMMIT;")
|
||||||
|
|
||||||
def execute_manager(settings_mod):
|
def execute_manager(settings_mod, argv=None):
|
||||||
# Add this project to sys.path so that it's importable in the conventional
|
# Add this project to sys.path so that it's importable in the conventional
|
||||||
# way. For example, if this file (manage.py) lives in a directory
|
# way. For example, if this file (manage.py) lives in a directory
|
||||||
# "myproject", this code would add "/path/to/myproject" to sys.path.
|
# "myproject", this code would add "/path/to/myproject" to sys.path.
|
||||||
@ -1247,4 +1253,4 @@ def execute_manager(settings_mod):
|
|||||||
action_mapping['startapp'].args = startapp.args
|
action_mapping['startapp'].args = startapp.args
|
||||||
|
|
||||||
# Run the django-admin.py command.
|
# Run the django-admin.py command.
|
||||||
execute_from_command_line(action_mapping)
|
execute_from_command_line(action_mapping, argv)
|
||||||
|
@ -23,6 +23,25 @@ def get_mod_func(callback):
|
|||||||
dot = callback.rindex('.')
|
dot = callback.rindex('.')
|
||||||
return callback[:dot], callback[dot+1:]
|
return callback[:dot], callback[dot+1:]
|
||||||
|
|
||||||
|
def reverse_helper(regex, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Does a "reverse" lookup -- returns the URL for the given args/kwargs.
|
||||||
|
The args/kwargs are applied to the given compiled regular expression.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
>>> reverse_helper(re.compile('^places/(\d+)/$'), 3)
|
||||||
|
'places/3/'
|
||||||
|
>>> reverse_helper(re.compile('^places/(?P<id>\d+)/$'), id=3)
|
||||||
|
'places/3/'
|
||||||
|
>>> reverse_helper(re.compile('^people/(?P<state>\w\w)/(\w+)/$'), 'adrian', state='il')
|
||||||
|
'people/il/adrian/'
|
||||||
|
|
||||||
|
Raises NoReverseMatch if the args/kwargs aren't valid for the regex.
|
||||||
|
"""
|
||||||
|
# TODO: Handle nested parenthesis in the following regex.
|
||||||
|
result = re.sub(r'\(([^)]+)\)', MatchChecker(args, kwargs), regex.pattern)
|
||||||
|
return result.replace('^', '').replace('$', '')
|
||||||
|
|
||||||
class MatchChecker(object):
|
class MatchChecker(object):
|
||||||
"Class used in reverse RegexURLPattern lookup."
|
"Class used in reverse RegexURLPattern lookup."
|
||||||
def __init__(self, args, kwargs):
|
def __init__(self, args, kwargs):
|
||||||
@ -108,23 +127,7 @@ class RegexURLPattern:
|
|||||||
return self.reverse_helper(*args, **kwargs)
|
return self.reverse_helper(*args, **kwargs)
|
||||||
|
|
||||||
def reverse_helper(self, *args, **kwargs):
|
def reverse_helper(self, *args, **kwargs):
|
||||||
"""
|
return reverse_helper(self.regex, *args, **kwargs)
|
||||||
Does a "reverse" lookup -- returns the URL for the given args/kwargs.
|
|
||||||
The args/kwargs are applied to the regular expression in this
|
|
||||||
RegexURLPattern. For example:
|
|
||||||
|
|
||||||
>>> RegexURLPattern('^places/(\d+)/$').reverse_helper(3)
|
|
||||||
'places/3/'
|
|
||||||
>>> RegexURLPattern('^places/(?P<id>\d+)/$').reverse_helper(id=3)
|
|
||||||
'places/3/'
|
|
||||||
>>> RegexURLPattern('^people/(?P<state>\w\w)/(\w+)/$').reverse_helper('adrian', state='il')
|
|
||||||
'people/il/adrian/'
|
|
||||||
|
|
||||||
Raises NoReverseMatch if the args/kwargs aren't valid for the RegexURLPattern.
|
|
||||||
"""
|
|
||||||
# TODO: Handle nested parenthesis in the following regex.
|
|
||||||
result = re.sub(r'\(([^)]+)\)', MatchChecker(args, kwargs), self.regex.pattern)
|
|
||||||
return result.replace('^', '').replace('$', '')
|
|
||||||
|
|
||||||
class RegexURLResolver(object):
|
class RegexURLResolver(object):
|
||||||
def __init__(self, regex, urlconf_name):
|
def __init__(self, regex, urlconf_name):
|
||||||
@ -182,9 +185,19 @@ class RegexURLResolver(object):
|
|||||||
|
|
||||||
def reverse(self, viewname, *args, **kwargs):
|
def reverse(self, viewname, *args, **kwargs):
|
||||||
for pattern in self.urlconf_module.urlpatterns:
|
for pattern in self.urlconf_module.urlpatterns:
|
||||||
if pattern.callback == viewname:
|
if isinstance(pattern, RegexURLResolver):
|
||||||
|
try:
|
||||||
|
return pattern.reverse_helper(viewname, *args, **kwargs)
|
||||||
|
except NoReverseMatch:
|
||||||
|
continue
|
||||||
|
elif pattern.callback == viewname:
|
||||||
try:
|
try:
|
||||||
return pattern.reverse_helper(*args, **kwargs)
|
return pattern.reverse_helper(*args, **kwargs)
|
||||||
except NoReverseMatch:
|
except NoReverseMatch:
|
||||||
continue
|
continue
|
||||||
raise NoReverseMatch
|
raise NoReverseMatch
|
||||||
|
|
||||||
|
def reverse_helper(self, viewname, *args, **kwargs):
|
||||||
|
sub_match = self.reverse(viewname, *args, **kwargs)
|
||||||
|
result = reverse_helper(self.regex, *args, **kwargs)
|
||||||
|
return result + sub_match
|
||||||
|
@ -399,7 +399,8 @@ class AnyValidator:
|
|||||||
as a validation error. The message is rather unspecific, so it's best to
|
as a validation error. The message is rather unspecific, so it's best to
|
||||||
specify one on instantiation.
|
specify one on instantiation.
|
||||||
"""
|
"""
|
||||||
def __init__(self, validator_list=[], error_message=gettext_lazy("This field is invalid.")):
|
def __init__(self, validator_list=None, error_message=gettext_lazy("This field is invalid.")):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.validator_list = validator_list
|
self.validator_list = validator_list
|
||||||
self.error_message = error_message
|
self.error_message = error_message
|
||||||
for v in validator_list:
|
for v in validator_list:
|
||||||
|
@ -125,6 +125,9 @@ def get_limit_offset_sql(limit, offset=None):
|
|||||||
def get_random_function_sql():
|
def get_random_function_sql():
|
||||||
return "RAND()"
|
return "RAND()"
|
||||||
|
|
||||||
|
def get_fulltext_search_sql(field_name):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def get_drop_foreignkey_sql():
|
def get_drop_foreignkey_sql():
|
||||||
return "DROP CONSTRAINT"
|
return "DROP CONSTRAINT"
|
||||||
|
|
||||||
|
@ -33,5 +33,6 @@ get_date_extract_sql = complain
|
|||||||
get_date_trunc_sql = complain
|
get_date_trunc_sql = complain
|
||||||
get_limit_offset_sql = complain
|
get_limit_offset_sql = complain
|
||||||
get_random_function_sql = complain
|
get_random_function_sql = complain
|
||||||
|
get_fulltext_search_sql = complain
|
||||||
get_drop_foreignkey_sql = complain
|
get_drop_foreignkey_sql = complain
|
||||||
OPERATOR_MAPPING = {}
|
OPERATOR_MAPPING = {}
|
||||||
|
@ -152,6 +152,9 @@ def get_limit_offset_sql(limit, offset=None):
|
|||||||
def get_random_function_sql():
|
def get_random_function_sql():
|
||||||
return "RAND()"
|
return "RAND()"
|
||||||
|
|
||||||
|
def get_fulltext_search_sql(field_name):
|
||||||
|
return 'MATCH (%s) AGAINST (%%s IN BOOLEAN MODE)' % field_name
|
||||||
|
|
||||||
def get_drop_foreignkey_sql():
|
def get_drop_foreignkey_sql():
|
||||||
return "DROP FOREIGN KEY"
|
return "DROP FOREIGN KEY"
|
||||||
|
|
||||||
|
@ -65,11 +65,13 @@ class FormatStylePlaceholderCursor(Database.Cursor):
|
|||||||
This fixes it -- but note that if you want to use a literal "%s" in a query,
|
This fixes it -- but note that if you want to use a literal "%s" in a query,
|
||||||
you'll need to use "%%s".
|
you'll need to use "%%s".
|
||||||
"""
|
"""
|
||||||
def execute(self, query, params=[]):
|
def execute(self, query, params=None):
|
||||||
|
if params is None: params = []
|
||||||
query = self.convert_arguments(query, len(params))
|
query = self.convert_arguments(query, len(params))
|
||||||
return Database.Cursor.execute(self, query, params)
|
return Database.Cursor.execute(self, query, params)
|
||||||
|
|
||||||
def executemany(self, query, params=[]):
|
def executemany(self, query, params=None):
|
||||||
|
if params is None: params = []
|
||||||
query = self.convert_arguments(query, len(params[0]))
|
query = self.convert_arguments(query, len(params[0]))
|
||||||
return Database.Cursor.executemany(self, query, params)
|
return Database.Cursor.executemany(self, query, params)
|
||||||
|
|
||||||
@ -106,6 +108,9 @@ def get_limit_offset_sql(limit, offset=None):
|
|||||||
def get_random_function_sql():
|
def get_random_function_sql():
|
||||||
return "DBMS_RANDOM.RANDOM"
|
return "DBMS_RANDOM.RANDOM"
|
||||||
|
|
||||||
|
def get_fulltext_search_sql(field_name):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def get_drop_foreignkey_sql():
|
def get_drop_foreignkey_sql():
|
||||||
return "DROP FOREIGN KEY"
|
return "DROP FOREIGN KEY"
|
||||||
|
|
||||||
|
@ -102,6 +102,9 @@ def get_limit_offset_sql(limit, offset=None):
|
|||||||
def get_random_function_sql():
|
def get_random_function_sql():
|
||||||
return "RANDOM()"
|
return "RANDOM()"
|
||||||
|
|
||||||
|
def get_fulltext_search_sql(field_name):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def get_drop_foreignkey_sql():
|
def get_drop_foreignkey_sql():
|
||||||
return "DROP CONSTRAINT"
|
return "DROP CONSTRAINT"
|
||||||
|
|
||||||
|
@ -108,6 +108,9 @@ def get_limit_offset_sql(limit, offset=None):
|
|||||||
def get_random_function_sql():
|
def get_random_function_sql():
|
||||||
return "RANDOM()"
|
return "RANDOM()"
|
||||||
|
|
||||||
|
def get_fulltext_search_sql(field_name):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def get_drop_foreignkey_sql():
|
def get_drop_foreignkey_sql():
|
||||||
return "DROP CONSTRAINT"
|
return "DROP CONSTRAINT"
|
||||||
|
|
||||||
|
@ -124,6 +124,9 @@ def get_limit_offset_sql(limit, offset=None):
|
|||||||
def get_random_function_sql():
|
def get_random_function_sql():
|
||||||
return "RANDOM()"
|
return "RANDOM()"
|
||||||
|
|
||||||
|
def get_fulltext_search_sql(field_name):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def get_drop_foreignkey_sql():
|
def get_drop_foreignkey_sql():
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ class Field(object):
|
|||||||
|
|
||||||
def get_db_prep_lookup(self, lookup_type, value):
|
def get_db_prep_lookup(self, lookup_type, value):
|
||||||
"Returns field's value prepared for database lookup."
|
"Returns field's value prepared for database lookup."
|
||||||
if lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'ne', 'year', 'month', 'day'):
|
if lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'ne', 'year', 'month', 'day', 'search'):
|
||||||
return [value]
|
return [value]
|
||||||
elif lookup_type in ('range', 'in'):
|
elif lookup_type in ('range', 'in'):
|
||||||
return value
|
return value
|
||||||
|
@ -198,7 +198,7 @@ class ForeignRelatedObjectsDescriptor(object):
|
|||||||
setattr(obj, rel_field.name, None)
|
setattr(obj, rel_field.name, None)
|
||||||
obj.save()
|
obj.save()
|
||||||
else:
|
else:
|
||||||
raise rel_field.rel.to.DoesNotExist, "'%s' is not related to '%s'." % (obj, instance)
|
raise rel_field.rel.to.DoesNotExist, "%r is not related to %r." % (obj, instance)
|
||||||
remove.alters_data = True
|
remove.alters_data = True
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
|
@ -615,6 +615,8 @@ def get_where_clause(lookup_type, table_prefix, field_name, value):
|
|||||||
return "%s = %%s" % backend.get_date_extract_sql(lookup_type, table_prefix + field_name)
|
return "%s = %%s" % backend.get_date_extract_sql(lookup_type, table_prefix + field_name)
|
||||||
elif lookup_type == 'isnull':
|
elif lookup_type == 'isnull':
|
||||||
return "%s%s IS %sNULL" % (table_prefix, field_name, (not value and 'NOT ' or ''))
|
return "%s%s IS %sNULL" % (table_prefix, field_name, (not value and 'NOT ' or ''))
|
||||||
|
elif lookup_type == 'search':
|
||||||
|
return backend.get_fulltext_search_sql(table_prefix + field_name)
|
||||||
raise TypeError, "Got invalid lookup_type: %s" % repr(lookup_type)
|
raise TypeError, "Got invalid lookup_type: %s" % repr(lookup_type)
|
||||||
|
|
||||||
def get_cached_row(klass, row, index_start):
|
def get_cached_row(klass, row, index_start):
|
||||||
|
@ -367,7 +367,8 @@ class FormField:
|
|||||||
|
|
||||||
class TextField(FormField):
|
class TextField(FormField):
|
||||||
input_type = "text"
|
input_type = "text"
|
||||||
def __init__(self, field_name, length=30, maxlength=None, is_required=False, validator_list=[], member_name=None):
|
def __init__(self, field_name, length=30, maxlength=None, is_required=False, validator_list=None, member_name=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.field_name = field_name
|
self.field_name = field_name
|
||||||
self.length, self.maxlength = length, maxlength
|
self.length, self.maxlength = length, maxlength
|
||||||
self.is_required = is_required
|
self.is_required = is_required
|
||||||
@ -404,7 +405,8 @@ class PasswordField(TextField):
|
|||||||
input_type = "password"
|
input_type = "password"
|
||||||
|
|
||||||
class LargeTextField(TextField):
|
class LargeTextField(TextField):
|
||||||
def __init__(self, field_name, rows=10, cols=40, is_required=False, validator_list=[], maxlength=None):
|
def __init__(self, field_name, rows=10, cols=40, is_required=False, validator_list=None, maxlength=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.field_name = field_name
|
self.field_name = field_name
|
||||||
self.rows, self.cols, self.is_required = rows, cols, is_required
|
self.rows, self.cols, self.is_required = rows, cols, is_required
|
||||||
self.validator_list = validator_list[:]
|
self.validator_list = validator_list[:]
|
||||||
@ -422,7 +424,8 @@ class LargeTextField(TextField):
|
|||||||
self.field_name, self.rows, self.cols, escape(data))
|
self.field_name, self.rows, self.cols, escape(data))
|
||||||
|
|
||||||
class HiddenField(FormField):
|
class HiddenField(FormField):
|
||||||
def __init__(self, field_name, is_required=False, validator_list=[]):
|
def __init__(self, field_name, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.field_name, self.is_required = field_name, is_required
|
self.field_name, self.is_required = field_name, is_required
|
||||||
self.validator_list = validator_list[:]
|
self.validator_list = validator_list[:]
|
||||||
|
|
||||||
@ -452,7 +455,9 @@ class CheckboxField(FormField):
|
|||||||
html2python = staticmethod(html2python)
|
html2python = staticmethod(html2python)
|
||||||
|
|
||||||
class SelectField(FormField):
|
class SelectField(FormField):
|
||||||
def __init__(self, field_name, choices=[], size=1, is_required=False, validator_list=[], member_name=None):
|
def __init__(self, field_name, choices=None, size=1, is_required=False, validator_list=None, member_name=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
|
if choices is None: choices = []
|
||||||
self.field_name = field_name
|
self.field_name = field_name
|
||||||
# choices is a list of (value, human-readable key) tuples because order matters
|
# choices is a list of (value, human-readable key) tuples because order matters
|
||||||
self.choices, self.size, self.is_required = choices, size, is_required
|
self.choices, self.size, self.is_required = choices, size, is_required
|
||||||
@ -488,7 +493,9 @@ class NullSelectField(SelectField):
|
|||||||
html2python = staticmethod(html2python)
|
html2python = staticmethod(html2python)
|
||||||
|
|
||||||
class RadioSelectField(FormField):
|
class RadioSelectField(FormField):
|
||||||
def __init__(self, field_name, choices=[], ul_class='', is_required=False, validator_list=[], member_name=None):
|
def __init__(self, field_name, choices=None, ul_class='', is_required=False, validator_list=None, member_name=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
|
if choices is None: choices = []
|
||||||
self.field_name = field_name
|
self.field_name = field_name
|
||||||
# choices is a list of (value, human-readable key) tuples because order matters
|
# choices is a list of (value, human-readable key) tuples because order matters
|
||||||
self.choices, self.is_required = choices, is_required
|
self.choices, self.is_required = choices, is_required
|
||||||
@ -552,7 +559,8 @@ class RadioSelectField(FormField):
|
|||||||
|
|
||||||
class NullBooleanField(SelectField):
|
class NullBooleanField(SelectField):
|
||||||
"This SelectField provides 'Yes', 'No' and 'Unknown', mapping results to True, False or None"
|
"This SelectField provides 'Yes', 'No' and 'Unknown', mapping results to True, False or None"
|
||||||
def __init__(self, field_name, is_required=False, validator_list=[]):
|
def __init__(self, field_name, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
SelectField.__init__(self, field_name, choices=[('1', 'Unknown'), ('2', 'Yes'), ('3', 'No')],
|
SelectField.__init__(self, field_name, choices=[('1', 'Unknown'), ('2', 'Yes'), ('3', 'No')],
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
|
|
||||||
@ -605,7 +613,9 @@ class CheckboxSelectMultipleField(SelectMultipleField):
|
|||||||
back into the single list that validators, renderers and save() expect.
|
back into the single list that validators, renderers and save() expect.
|
||||||
"""
|
"""
|
||||||
requires_data_list = True
|
requires_data_list = True
|
||||||
def __init__(self, field_name, choices=[], validator_list=[]):
|
def __init__(self, field_name, choices=None, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
|
if choices is None: choices = []
|
||||||
SelectMultipleField.__init__(self, field_name, choices, size=1, is_required=False, validator_list=validator_list)
|
SelectMultipleField.__init__(self, field_name, choices, size=1, is_required=False, validator_list=validator_list)
|
||||||
|
|
||||||
def prepare(self, new_data):
|
def prepare(self, new_data):
|
||||||
@ -636,7 +646,8 @@ class CheckboxSelectMultipleField(SelectMultipleField):
|
|||||||
####################
|
####################
|
||||||
|
|
||||||
class FileUploadField(FormField):
|
class FileUploadField(FormField):
|
||||||
def __init__(self, field_name, is_required=False, validator_list=[]):
|
def __init__(self, field_name, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.field_name, self.is_required = field_name, is_required
|
self.field_name, self.is_required = field_name, is_required
|
||||||
self.validator_list = [self.isNonEmptyFile] + validator_list
|
self.validator_list = [self.isNonEmptyFile] + validator_list
|
||||||
|
|
||||||
@ -675,7 +686,8 @@ class ImageUploadField(FileUploadField):
|
|||||||
####################
|
####################
|
||||||
|
|
||||||
class IntegerField(TextField):
|
class IntegerField(TextField):
|
||||||
def __init__(self, field_name, length=10, maxlength=None, is_required=False, validator_list=[], member_name=None):
|
def __init__(self, field_name, length=10, maxlength=None, is_required=False, validator_list=None, member_name=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isInteger] + validator_list
|
validator_list = [self.isInteger] + validator_list
|
||||||
if member_name is not None:
|
if member_name is not None:
|
||||||
self.member_name = member_name
|
self.member_name = member_name
|
||||||
@ -694,7 +706,8 @@ class IntegerField(TextField):
|
|||||||
html2python = staticmethod(html2python)
|
html2python = staticmethod(html2python)
|
||||||
|
|
||||||
class SmallIntegerField(IntegerField):
|
class SmallIntegerField(IntegerField):
|
||||||
def __init__(self, field_name, length=5, maxlength=5, is_required=False, validator_list=[]):
|
def __init__(self, field_name, length=5, maxlength=5, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isSmallInteger] + validator_list
|
validator_list = [self.isSmallInteger] + validator_list
|
||||||
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
|
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
|
||||||
|
|
||||||
@ -703,7 +716,8 @@ class SmallIntegerField(IntegerField):
|
|||||||
raise validators.CriticalValidationError, gettext("Enter a whole number between -32,768 and 32,767.")
|
raise validators.CriticalValidationError, gettext("Enter a whole number between -32,768 and 32,767.")
|
||||||
|
|
||||||
class PositiveIntegerField(IntegerField):
|
class PositiveIntegerField(IntegerField):
|
||||||
def __init__(self, field_name, length=10, maxlength=None, is_required=False, validator_list=[]):
|
def __init__(self, field_name, length=10, maxlength=None, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isPositive] + validator_list
|
validator_list = [self.isPositive] + validator_list
|
||||||
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
|
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
|
||||||
|
|
||||||
@ -712,7 +726,8 @@ class PositiveIntegerField(IntegerField):
|
|||||||
raise validators.CriticalValidationError, gettext("Enter a positive number.")
|
raise validators.CriticalValidationError, gettext("Enter a positive number.")
|
||||||
|
|
||||||
class PositiveSmallIntegerField(IntegerField):
|
class PositiveSmallIntegerField(IntegerField):
|
||||||
def __init__(self, field_name, length=5, maxlength=None, is_required=False, validator_list=[]):
|
def __init__(self, field_name, length=5, maxlength=None, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isPositiveSmall] + validator_list
|
validator_list = [self.isPositiveSmall] + validator_list
|
||||||
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
|
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
|
||||||
|
|
||||||
@ -721,7 +736,8 @@ class PositiveSmallIntegerField(IntegerField):
|
|||||||
raise validators.CriticalValidationError, gettext("Enter a whole number between 0 and 32,767.")
|
raise validators.CriticalValidationError, gettext("Enter a whole number between 0 and 32,767.")
|
||||||
|
|
||||||
class FloatField(TextField):
|
class FloatField(TextField):
|
||||||
def __init__(self, field_name, max_digits, decimal_places, is_required=False, validator_list=[]):
|
def __init__(self, field_name, max_digits, decimal_places, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.max_digits, self.decimal_places = max_digits, decimal_places
|
self.max_digits, self.decimal_places = max_digits, decimal_places
|
||||||
validator_list = [self.isValidFloat] + validator_list
|
validator_list = [self.isValidFloat] + validator_list
|
||||||
TextField.__init__(self, field_name, max_digits+1, max_digits+1, is_required, validator_list)
|
TextField.__init__(self, field_name, max_digits+1, max_digits+1, is_required, validator_list)
|
||||||
@ -746,7 +762,8 @@ class FloatField(TextField):
|
|||||||
class DatetimeField(TextField):
|
class DatetimeField(TextField):
|
||||||
"""A FormField that automatically converts its data to a datetime.datetime object.
|
"""A FormField that automatically converts its data to a datetime.datetime object.
|
||||||
The data should be in the format YYYY-MM-DD HH:MM:SS."""
|
The data should be in the format YYYY-MM-DD HH:MM:SS."""
|
||||||
def __init__(self, field_name, length=30, maxlength=None, is_required=False, validator_list=[]):
|
def __init__(self, field_name, length=30, maxlength=None, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.field_name = field_name
|
self.field_name = field_name
|
||||||
self.length, self.maxlength = length, maxlength
|
self.length, self.maxlength = length, maxlength
|
||||||
self.is_required = is_required
|
self.is_required = is_required
|
||||||
@ -769,7 +786,8 @@ class DatetimeField(TextField):
|
|||||||
class DateField(TextField):
|
class DateField(TextField):
|
||||||
"""A FormField that automatically converts its data to a datetime.date object.
|
"""A FormField that automatically converts its data to a datetime.date object.
|
||||||
The data should be in the format YYYY-MM-DD."""
|
The data should be in the format YYYY-MM-DD."""
|
||||||
def __init__(self, field_name, is_required=False, validator_list=[]):
|
def __init__(self, field_name, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isValidDate] + validator_list
|
validator_list = [self.isValidDate] + validator_list
|
||||||
TextField.__init__(self, field_name, length=10, maxlength=10,
|
TextField.__init__(self, field_name, length=10, maxlength=10,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
@ -793,7 +811,8 @@ class DateField(TextField):
|
|||||||
class TimeField(TextField):
|
class TimeField(TextField):
|
||||||
"""A FormField that automatically converts its data to a datetime.time object.
|
"""A FormField that automatically converts its data to a datetime.time object.
|
||||||
The data should be in the format HH:MM:SS or HH:MM:SS.mmmmmm."""
|
The data should be in the format HH:MM:SS or HH:MM:SS.mmmmmm."""
|
||||||
def __init__(self, field_name, is_required=False, validator_list=[]):
|
def __init__(self, field_name, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isValidTime] + validator_list
|
validator_list = [self.isValidTime] + validator_list
|
||||||
TextField.__init__(self, field_name, length=8, maxlength=8,
|
TextField.__init__(self, field_name, length=8, maxlength=8,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
@ -827,7 +846,8 @@ class TimeField(TextField):
|
|||||||
|
|
||||||
class EmailField(TextField):
|
class EmailField(TextField):
|
||||||
"A convenience FormField for validating e-mail addresses"
|
"A convenience FormField for validating e-mail addresses"
|
||||||
def __init__(self, field_name, length=50, maxlength=75, is_required=False, validator_list=[]):
|
def __init__(self, field_name, length=50, maxlength=75, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isValidEmail] + validator_list
|
validator_list = [self.isValidEmail] + validator_list
|
||||||
TextField.__init__(self, field_name, length, maxlength=maxlength,
|
TextField.__init__(self, field_name, length, maxlength=maxlength,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
@ -840,7 +860,8 @@ class EmailField(TextField):
|
|||||||
|
|
||||||
class URLField(TextField):
|
class URLField(TextField):
|
||||||
"A convenience FormField for validating URLs"
|
"A convenience FormField for validating URLs"
|
||||||
def __init__(self, field_name, length=50, maxlength=200, is_required=False, validator_list=[]):
|
def __init__(self, field_name, length=50, maxlength=200, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isValidURL] + validator_list
|
validator_list = [self.isValidURL] + validator_list
|
||||||
TextField.__init__(self, field_name, length=length, maxlength=maxlength,
|
TextField.__init__(self, field_name, length=length, maxlength=maxlength,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
@ -852,7 +873,8 @@ class URLField(TextField):
|
|||||||
raise validators.CriticalValidationError, e.messages
|
raise validators.CriticalValidationError, e.messages
|
||||||
|
|
||||||
class IPAddressField(TextField):
|
class IPAddressField(TextField):
|
||||||
def __init__(self, field_name, length=15, maxlength=15, is_required=False, validator_list=[]):
|
def __init__(self, field_name, length=15, maxlength=15, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isValidIPAddress] + validator_list
|
validator_list = [self.isValidIPAddress] + validator_list
|
||||||
TextField.__init__(self, field_name, length=length, maxlength=maxlength,
|
TextField.__init__(self, field_name, length=length, maxlength=maxlength,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
@ -873,7 +895,7 @@ class IPAddressField(TextField):
|
|||||||
|
|
||||||
class FilePathField(SelectField):
|
class FilePathField(SelectField):
|
||||||
"A SelectField whose choices are the files in a given directory."
|
"A SelectField whose choices are the files in a given directory."
|
||||||
def __init__(self, field_name, path, match=None, recursive=False, is_required=False, validator_list=[]):
|
def __init__(self, field_name, path, match=None, recursive=False, is_required=False, validator_list=None):
|
||||||
import os
|
import os
|
||||||
if match is not None:
|
if match is not None:
|
||||||
import re
|
import re
|
||||||
@ -896,7 +918,8 @@ class FilePathField(SelectField):
|
|||||||
|
|
||||||
class PhoneNumberField(TextField):
|
class PhoneNumberField(TextField):
|
||||||
"A convenience FormField for validating phone numbers (e.g. '630-555-1234')"
|
"A convenience FormField for validating phone numbers (e.g. '630-555-1234')"
|
||||||
def __init__(self, field_name, is_required=False, validator_list=[]):
|
def __init__(self, field_name, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isValidPhone] + validator_list
|
validator_list = [self.isValidPhone] + validator_list
|
||||||
TextField.__init__(self, field_name, length=12, maxlength=12,
|
TextField.__init__(self, field_name, length=12, maxlength=12,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
@ -909,7 +932,8 @@ class PhoneNumberField(TextField):
|
|||||||
|
|
||||||
class USStateField(TextField):
|
class USStateField(TextField):
|
||||||
"A convenience FormField for validating U.S. states (e.g. 'IL')"
|
"A convenience FormField for validating U.S. states (e.g. 'IL')"
|
||||||
def __init__(self, field_name, is_required=False, validator_list=[]):
|
def __init__(self, field_name, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isValidUSState] + validator_list
|
validator_list = [self.isValidUSState] + validator_list
|
||||||
TextField.__init__(self, field_name, length=2, maxlength=2,
|
TextField.__init__(self, field_name, length=2, maxlength=2,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
@ -929,7 +953,8 @@ class USStateField(TextField):
|
|||||||
|
|
||||||
class CommaSeparatedIntegerField(TextField):
|
class CommaSeparatedIntegerField(TextField):
|
||||||
"A convenience FormField for validating comma-separated integer fields"
|
"A convenience FormField for validating comma-separated integer fields"
|
||||||
def __init__(self, field_name, maxlength=None, is_required=False, validator_list=[]):
|
def __init__(self, field_name, maxlength=None, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isCommaSeparatedIntegerList] + validator_list
|
validator_list = [self.isCommaSeparatedIntegerList] + validator_list
|
||||||
TextField.__init__(self, field_name, length=20, maxlength=maxlength,
|
TextField.__init__(self, field_name, length=20, maxlength=maxlength,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
|
@ -227,7 +227,8 @@ class Parser(object):
|
|||||||
for lib in builtins:
|
for lib in builtins:
|
||||||
self.add_library(lib)
|
self.add_library(lib)
|
||||||
|
|
||||||
def parse(self, parse_until=[]):
|
def parse(self, parse_until=None):
|
||||||
|
if parse_until is None: parse_until = []
|
||||||
nodelist = self.create_nodelist()
|
nodelist = self.create_nodelist()
|
||||||
while self.tokens:
|
while self.tokens:
|
||||||
token = self.next_token()
|
token = self.next_token()
|
||||||
|
@ -42,7 +42,8 @@ class MergeDict:
|
|||||||
|
|
||||||
class SortedDict(dict):
|
class SortedDict(dict):
|
||||||
"A dictionary that keeps its keys in the order in which they're inserted."
|
"A dictionary that keeps its keys in the order in which they're inserted."
|
||||||
def __init__(self, data={}):
|
def __init__(self, data=None):
|
||||||
|
if data is None: data = {}
|
||||||
dict.__init__(self, data)
|
dict.__init__(self, data)
|
||||||
self.keyOrder = data.keys()
|
self.keyOrder = data.keys()
|
||||||
|
|
||||||
@ -123,8 +124,9 @@ class MultiValueDict(dict):
|
|||||||
def __copy__(self):
|
def __copy__(self):
|
||||||
return self.__class__(dict.items(self))
|
return self.__class__(dict.items(self))
|
||||||
|
|
||||||
def __deepcopy__(self, memo={}):
|
def __deepcopy__(self, memo=None):
|
||||||
import copy
|
import copy
|
||||||
|
if memo is None: memo = {}
|
||||||
result = self.__class__()
|
result = self.__class__()
|
||||||
memo[id(self)] = result
|
memo[id(self)] = result
|
||||||
for key, value in dict.items(self):
|
for key, value in dict.items(self):
|
||||||
|
@ -369,7 +369,22 @@ def get_date_formats():
|
|||||||
datetime_format = settings.DATETIME_FORMAT
|
datetime_format = settings.DATETIME_FORMAT
|
||||||
if time_format == 'TIME_FORMAT':
|
if time_format == 'TIME_FORMAT':
|
||||||
time_format = settings.TIME_FORMAT
|
time_format = settings.TIME_FORMAT
|
||||||
return (date_format, datetime_format, time_format)
|
return date_format, datetime_format, time_format
|
||||||
|
|
||||||
|
def get_partial_date_formats():
|
||||||
|
"""
|
||||||
|
This function checks whether translation files provide a translation for some
|
||||||
|
technical message ID to store partial date formats. If it doesn't contain
|
||||||
|
one, the formats provided in the settings will be used.
|
||||||
|
"""
|
||||||
|
from django.conf import settings
|
||||||
|
year_month_format = _('YEAR_MONTH_FORMAT')
|
||||||
|
month_day_format = _('MONTH_DAY_FORMAT')
|
||||||
|
if year_month_format == 'YEAR_MONTH_FORMAT':
|
||||||
|
year_month_format = settings.YEAR_MONTH_FORMAT
|
||||||
|
if month_day_format == 'MONTH_DAY_FORMAT':
|
||||||
|
month_day_format = settings.MONTH_DAY_FORMAT
|
||||||
|
return year_month_format, month_day_format
|
||||||
|
|
||||||
def install():
|
def install():
|
||||||
"""
|
"""
|
||||||
|
@ -5,8 +5,9 @@ Utilities for XML generation/parsing.
|
|||||||
from xml.sax.saxutils import XMLGenerator
|
from xml.sax.saxutils import XMLGenerator
|
||||||
|
|
||||||
class SimplerXMLGenerator(XMLGenerator):
|
class SimplerXMLGenerator(XMLGenerator):
|
||||||
def addQuickElement(self, name, contents=None, attrs={}):
|
def addQuickElement(self, name, contents=None, attrs=None):
|
||||||
"Convenience method for adding an element with no children"
|
"Convenience method for adding an element with no children"
|
||||||
|
if attrs is None: attrs = {}
|
||||||
self.startElement(name, attrs)
|
self.startElement(name, attrs)
|
||||||
if contents is not None:
|
if contents is not None:
|
||||||
self.characters(contents)
|
self.characters(contents)
|
||||||
|
@ -9,7 +9,7 @@ from django.http import Http404, HttpResponse, HttpResponseRedirect
|
|||||||
from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
|
from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
|
||||||
|
|
||||||
def create_object(request, model, template_name=None,
|
def create_object(request, model, template_name=None,
|
||||||
template_loader=loader, extra_context={}, post_save_redirect=None,
|
template_loader=loader, extra_context=None, post_save_redirect=None,
|
||||||
login_required=False, follow=None, context_processors=None):
|
login_required=False, follow=None, context_processors=None):
|
||||||
"""
|
"""
|
||||||
Generic object-creation function.
|
Generic object-creation function.
|
||||||
@ -19,6 +19,7 @@ def create_object(request, model, template_name=None,
|
|||||||
form
|
form
|
||||||
the form wrapper for the object
|
the form wrapper for the object
|
||||||
"""
|
"""
|
||||||
|
if extra_context is None: extra_context = {}
|
||||||
if login_required and request.user.is_anonymous():
|
if login_required and request.user.is_anonymous():
|
||||||
return redirect_to_login(request.path)
|
return redirect_to_login(request.path)
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ def create_object(request, model, template_name=None,
|
|||||||
|
|
||||||
def update_object(request, model, object_id=None, slug=None,
|
def update_object(request, model, object_id=None, slug=None,
|
||||||
slug_field=None, template_name=None, template_loader=loader,
|
slug_field=None, template_name=None, template_loader=loader,
|
||||||
extra_context={}, post_save_redirect=None,
|
extra_context=None, post_save_redirect=None,
|
||||||
login_required=False, follow=None, context_processors=None,
|
login_required=False, follow=None, context_processors=None,
|
||||||
template_object_name='object'):
|
template_object_name='object'):
|
||||||
"""
|
"""
|
||||||
@ -84,6 +85,7 @@ def update_object(request, model, object_id=None, slug=None,
|
|||||||
object
|
object
|
||||||
the original object being edited
|
the original object being edited
|
||||||
"""
|
"""
|
||||||
|
if extra_context is None: extra_context = {}
|
||||||
if login_required and request.user.is_anonymous():
|
if login_required and request.user.is_anonymous():
|
||||||
return redirect_to_login(request.path)
|
return redirect_to_login(request.path)
|
||||||
|
|
||||||
@ -143,7 +145,7 @@ def update_object(request, model, object_id=None, slug=None,
|
|||||||
|
|
||||||
def delete_object(request, model, post_delete_redirect,
|
def delete_object(request, model, post_delete_redirect,
|
||||||
object_id=None, slug=None, slug_field=None, template_name=None,
|
object_id=None, slug=None, slug_field=None, template_name=None,
|
||||||
template_loader=loader, extra_context={},
|
template_loader=loader, extra_context=None,
|
||||||
login_required=False, context_processors=None, template_object_name='object'):
|
login_required=False, context_processors=None, template_object_name='object'):
|
||||||
"""
|
"""
|
||||||
Generic object-delete function.
|
Generic object-delete function.
|
||||||
@ -157,6 +159,7 @@ def delete_object(request, model, post_delete_redirect,
|
|||||||
object
|
object
|
||||||
the original object being deleted
|
the original object being deleted
|
||||||
"""
|
"""
|
||||||
|
if extra_context is None: extra_context = {}
|
||||||
if login_required and request.user.is_anonymous():
|
if login_required and request.user.is_anonymous():
|
||||||
return redirect_to_login(request.path)
|
return redirect_to_login(request.path)
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import datetime, time
|
|||||||
|
|
||||||
def archive_index(request, queryset, date_field, num_latest=15,
|
def archive_index(request, queryset, date_field, num_latest=15,
|
||||||
template_name=None, template_loader=loader,
|
template_name=None, template_loader=loader,
|
||||||
extra_context={}, allow_empty=False, context_processors=None,
|
extra_context=None, allow_empty=False, context_processors=None,
|
||||||
mimetype=None):
|
mimetype=None):
|
||||||
"""
|
"""
|
||||||
Generic top-level archive of date-based objects.
|
Generic top-level archive of date-based objects.
|
||||||
@ -18,6 +18,7 @@ def archive_index(request, queryset, date_field, num_latest=15,
|
|||||||
latest
|
latest
|
||||||
Latest N (defaults to 15) objects by date
|
Latest N (defaults to 15) objects by date
|
||||||
"""
|
"""
|
||||||
|
if extra_context is None: extra_context = {}
|
||||||
model = queryset.model
|
model = queryset.model
|
||||||
queryset = queryset.filter(**{'%s__lte' % date_field: datetime.datetime.now()})
|
queryset = queryset.filter(**{'%s__lte' % date_field: datetime.datetime.now()})
|
||||||
date_list = queryset.dates(date_field, 'year')[::-1]
|
date_list = queryset.dates(date_field, 'year')[::-1]
|
||||||
@ -44,7 +45,7 @@ def archive_index(request, queryset, date_field, num_latest=15,
|
|||||||
return HttpResponse(t.render(c), mimetype=mimetype)
|
return HttpResponse(t.render(c), mimetype=mimetype)
|
||||||
|
|
||||||
def archive_year(request, year, queryset, date_field, template_name=None,
|
def archive_year(request, year, queryset, date_field, template_name=None,
|
||||||
template_loader=loader, extra_context={}, allow_empty=False,
|
template_loader=loader, extra_context=None, allow_empty=False,
|
||||||
context_processors=None, template_object_name='object', mimetype=None,
|
context_processors=None, template_object_name='object', mimetype=None,
|
||||||
make_object_list=False):
|
make_object_list=False):
|
||||||
"""
|
"""
|
||||||
@ -60,6 +61,7 @@ def archive_year(request, year, queryset, date_field, template_name=None,
|
|||||||
List of objects published in the given month
|
List of objects published in the given month
|
||||||
(Only available if make_object_list argument is True)
|
(Only available if make_object_list argument is True)
|
||||||
"""
|
"""
|
||||||
|
if extra_context is None: extra_context = {}
|
||||||
model = queryset.model
|
model = queryset.model
|
||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
|
|
||||||
@ -92,7 +94,7 @@ def archive_year(request, year, queryset, date_field, template_name=None,
|
|||||||
|
|
||||||
def archive_month(request, year, month, queryset, date_field,
|
def archive_month(request, year, month, queryset, date_field,
|
||||||
month_format='%b', template_name=None, template_loader=loader,
|
month_format='%b', template_name=None, template_loader=loader,
|
||||||
extra_context={}, allow_empty=False, context_processors=None,
|
extra_context=None, allow_empty=False, context_processors=None,
|
||||||
template_object_name='object', mimetype=None):
|
template_object_name='object', mimetype=None):
|
||||||
"""
|
"""
|
||||||
Generic monthly archive view.
|
Generic monthly archive view.
|
||||||
@ -108,6 +110,7 @@ def archive_month(request, year, month, queryset, date_field,
|
|||||||
object_list:
|
object_list:
|
||||||
list of objects published in the given month
|
list of objects published in the given month
|
||||||
"""
|
"""
|
||||||
|
if extra_context is None: extra_context = {}
|
||||||
try:
|
try:
|
||||||
date = datetime.date(*time.strptime(year+month, '%Y'+month_format)[:3])
|
date = datetime.date(*time.strptime(year+month, '%Y'+month_format)[:3])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -148,7 +151,7 @@ def archive_month(request, year, month, queryset, date_field,
|
|||||||
|
|
||||||
def archive_week(request, year, week, queryset, date_field,
|
def archive_week(request, year, week, queryset, date_field,
|
||||||
template_name=None, template_loader=loader,
|
template_name=None, template_loader=loader,
|
||||||
extra_context={}, allow_empty=True, context_processors=None,
|
extra_context=None, allow_empty=True, context_processors=None,
|
||||||
template_object_name='object', mimetype=None):
|
template_object_name='object', mimetype=None):
|
||||||
"""
|
"""
|
||||||
Generic weekly archive view.
|
Generic weekly archive view.
|
||||||
@ -160,6 +163,7 @@ def archive_week(request, year, week, queryset, date_field,
|
|||||||
object_list:
|
object_list:
|
||||||
list of objects published in the given week
|
list of objects published in the given week
|
||||||
"""
|
"""
|
||||||
|
if extra_context is None: extra_context = {}
|
||||||
try:
|
try:
|
||||||
date = datetime.date(*time.strptime(year+'-0-'+week, '%Y-%w-%U')[:3])
|
date = datetime.date(*time.strptime(year+'-0-'+week, '%Y-%w-%U')[:3])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -195,7 +199,7 @@ def archive_week(request, year, week, queryset, date_field,
|
|||||||
|
|
||||||
def archive_day(request, year, month, day, queryset, date_field,
|
def archive_day(request, year, month, day, queryset, date_field,
|
||||||
month_format='%b', day_format='%d', template_name=None,
|
month_format='%b', day_format='%d', template_name=None,
|
||||||
template_loader=loader, extra_context={}, allow_empty=False,
|
template_loader=loader, extra_context=None, allow_empty=False,
|
||||||
context_processors=None, template_object_name='object',
|
context_processors=None, template_object_name='object',
|
||||||
mimetype=None):
|
mimetype=None):
|
||||||
"""
|
"""
|
||||||
@ -212,6 +216,7 @@ def archive_day(request, year, month, day, queryset, date_field,
|
|||||||
next_day
|
next_day
|
||||||
(datetime) the next day, or None if the current day is today
|
(datetime) the next day, or None if the current day is today
|
||||||
"""
|
"""
|
||||||
|
if extra_context is None: extra_context = {}
|
||||||
try:
|
try:
|
||||||
date = datetime.date(*time.strptime(year+month+day, '%Y'+month_format+day_format)[:3])
|
date = datetime.date(*time.strptime(year+month+day, '%Y'+month_format+day_format)[:3])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -261,7 +266,7 @@ def archive_today(request, **kwargs):
|
|||||||
def object_detail(request, year, month, day, queryset, date_field,
|
def object_detail(request, year, month, day, queryset, date_field,
|
||||||
month_format='%b', day_format='%d', object_id=None, slug=None,
|
month_format='%b', day_format='%d', object_id=None, slug=None,
|
||||||
slug_field=None, template_name=None, template_name_field=None,
|
slug_field=None, template_name=None, template_name_field=None,
|
||||||
template_loader=loader, extra_context={}, context_processors=None,
|
template_loader=loader, extra_context=None, context_processors=None,
|
||||||
template_object_name='object', mimetype=None):
|
template_object_name='object', mimetype=None):
|
||||||
"""
|
"""
|
||||||
Generic detail view from year/month/day/slug or year/month/day/id structure.
|
Generic detail view from year/month/day/slug or year/month/day/id structure.
|
||||||
@ -271,6 +276,7 @@ def object_detail(request, year, month, day, queryset, date_field,
|
|||||||
object:
|
object:
|
||||||
the object to be detailed
|
the object to be detailed
|
||||||
"""
|
"""
|
||||||
|
if extra_context is None: extra_context = {}
|
||||||
try:
|
try:
|
||||||
date = datetime.date(*time.strptime(year+month+day, '%Y'+month_format+day_format)[:3])
|
date = datetime.date(*time.strptime(year+month+day, '%Y'+month_format+day_format)[:3])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -4,9 +4,9 @@ from django.core.xheaders import populate_xheaders
|
|||||||
from django.core.paginator import ObjectPaginator, InvalidPage
|
from django.core.paginator import ObjectPaginator, InvalidPage
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
||||||
def object_list(request, queryset, paginate_by=None, allow_empty=False,
|
def object_list(request, queryset, paginate_by=None, page=None,
|
||||||
template_name=None, template_loader=loader,
|
allow_empty=False, template_name=None, template_loader=loader,
|
||||||
extra_context={}, context_processors=None, template_object_name='object',
|
extra_context=None, context_processors=None, template_object_name='object',
|
||||||
mimetype=None):
|
mimetype=None):
|
||||||
"""
|
"""
|
||||||
Generic list of objects.
|
Generic list of objects.
|
||||||
@ -34,10 +34,12 @@ def object_list(request, queryset, paginate_by=None, allow_empty=False,
|
|||||||
hits
|
hits
|
||||||
number of objects, total
|
number of objects, total
|
||||||
"""
|
"""
|
||||||
|
if extra_context is None: extra_context = {}
|
||||||
queryset = queryset._clone()
|
queryset = queryset._clone()
|
||||||
if paginate_by:
|
if paginate_by:
|
||||||
paginator = ObjectPaginator(queryset, paginate_by)
|
paginator = ObjectPaginator(queryset, paginate_by)
|
||||||
page = request.GET.get('page', 1)
|
if not page:
|
||||||
|
page = request.GET.get('page', 1)
|
||||||
try:
|
try:
|
||||||
page = int(page)
|
page = int(page)
|
||||||
object_list = paginator.get_page(page - 1)
|
object_list = paginator.get_page(page - 1)
|
||||||
@ -78,7 +80,7 @@ def object_list(request, queryset, paginate_by=None, allow_empty=False,
|
|||||||
|
|
||||||
def object_detail(request, queryset, object_id=None, slug=None,
|
def object_detail(request, queryset, object_id=None, slug=None,
|
||||||
slug_field=None, template_name=None, template_name_field=None,
|
slug_field=None, template_name=None, template_name_field=None,
|
||||||
template_loader=loader, extra_context={},
|
template_loader=loader, extra_context=None,
|
||||||
context_processors=None, template_object_name='object',
|
context_processors=None, template_object_name='object',
|
||||||
mimetype=None):
|
mimetype=None):
|
||||||
"""
|
"""
|
||||||
@ -89,6 +91,7 @@ def object_detail(request, queryset, object_id=None, slug=None,
|
|||||||
object
|
object
|
||||||
the object
|
the object
|
||||||
"""
|
"""
|
||||||
|
if extra_context is None: extra_context = {}
|
||||||
model = queryset.model
|
model = queryset.model
|
||||||
if object_id:
|
if object_id:
|
||||||
queryset = queryset.filter(pk=object_id)
|
queryset = queryset.filter(pk=object_id)
|
||||||
|
@ -45,6 +45,71 @@ See the `csrf documentation`_.
|
|||||||
|
|
||||||
.. _csrf documentation: http://www.djangoproject.com/documentation/csrf/
|
.. _csrf documentation: http://www.djangoproject.com/documentation/csrf/
|
||||||
|
|
||||||
|
humanize
|
||||||
|
========
|
||||||
|
|
||||||
|
A set of Django template filters useful for adding a "human touch" to data.
|
||||||
|
To activate these filters, add ``'django.contrib.english'`` to your
|
||||||
|
``INSTALLED_APPS`` setting. Once you've done that, use ``{% load english %}``
|
||||||
|
in a template, and you'll have access to these filters:
|
||||||
|
|
||||||
|
apnumber
|
||||||
|
--------
|
||||||
|
|
||||||
|
For numbers 1-9, returns the number spelled out. Otherwise, returns the
|
||||||
|
number. This follows Associated Press style.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
* ``1`` becomes ``'one'``.
|
||||||
|
* ``2`` becomes ``'two'``.
|
||||||
|
* ``10`` becomes ``10``.
|
||||||
|
|
||||||
|
You can pass in either an integer or a string representation of an integer.
|
||||||
|
|
||||||
|
intcomma
|
||||||
|
--------
|
||||||
|
|
||||||
|
Converts an integer to a string containing commas every three digits.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
* ``4500`` becomes ``'4,500'``.
|
||||||
|
* ``45000`` becomes ``'45,000'``.
|
||||||
|
* ``450000`` becomes ``'450,000'``.
|
||||||
|
* ``4500000`` becomes ``'4,500,000'``.
|
||||||
|
|
||||||
|
You can pass in either an integer or a string representation of an integer.
|
||||||
|
|
||||||
|
intword
|
||||||
|
-------
|
||||||
|
|
||||||
|
Converts a large integer to a friendly text representation. Works best for
|
||||||
|
numbers over 1 million.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
* ``1000000`` becomes ``'1.0 million'``.
|
||||||
|
* ``1200000`` becomes ``'1.2 million'``.
|
||||||
|
* ``1200000000`` becomes ``'1.2 billion'``.
|
||||||
|
|
||||||
|
Values up to 1000000000000000 (one quadrillion) are supported.
|
||||||
|
|
||||||
|
You can pass in either an integer or a string representation of an integer.
|
||||||
|
|
||||||
|
ordinal
|
||||||
|
-------
|
||||||
|
|
||||||
|
Converts an integer to its ordinal as a string.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
* ``1`` becomes ``'1st'``.
|
||||||
|
* ``2`` becomes ``'2nd'``.
|
||||||
|
* ``3`` becomes ``'3rd'``.
|
||||||
|
|
||||||
|
You can pass in either an integer or a string representation of an integer.
|
||||||
|
|
||||||
flatpages
|
flatpages
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
@ -82,14 +82,14 @@ Methods
|
|||||||
``user_permissions``. ``User`` objects can access their related
|
``user_permissions``. ``User`` objects can access their related
|
||||||
objects in the same way as any other `Django model`_::
|
objects in the same way as any other `Django model`_::
|
||||||
|
|
||||||
``myuser.objects.groups = [group_list]``
|
myuser.objects.groups = [group_list]
|
||||||
``myuser.objects.groups.add(group, group,...)``
|
myuser.objects.groups.add(group, group,...)
|
||||||
``myuser.objects.groups.remove(group, group,...)``
|
myuser.objects.groups.remove(group, group,...)
|
||||||
``myuser.objects.groups.clear()``
|
myuser.objects.groups.clear()
|
||||||
``myuser.objects.permissions = [permission_list]``
|
myuser.objects.permissions = [permission_list]
|
||||||
``myuser.objects.permissions.add(permission, permission, ...)``
|
myuser.objects.permissions.add(permission, permission, ...)
|
||||||
``myuser.objects.permissions.remove(permission, permission, ...]``
|
myuser.objects.permissions.remove(permission, permission, ...]
|
||||||
``myuser.objects.permissions.clear()``
|
myuser.objects.permissions.clear()
|
||||||
|
|
||||||
In addition to those automatic API methods, ``User`` objects have the following
|
In addition to those automatic API methods, ``User`` objects have the following
|
||||||
custom methods:
|
custom methods:
|
||||||
|
@ -1035,6 +1035,15 @@ SQL equivalent::
|
|||||||
|
|
||||||
SELECT ... WHERE pub_date IS NULL;
|
SELECT ... WHERE pub_date IS NULL;
|
||||||
|
|
||||||
|
search
|
||||||
|
~~~~~~
|
||||||
|
|
||||||
|
A boolean full-text search, taking advantage of full-text indexing. This is
|
||||||
|
like ``contains`` but is significantly faster due to full-text indexing.
|
||||||
|
|
||||||
|
Note this is only available in MySQL and requires direct manipulation of the
|
||||||
|
database to add the full-text index.
|
||||||
|
|
||||||
Default lookups are exact
|
Default lookups are exact
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@ -1578,3 +1587,23 @@ get_FOO_height() and get_FOO_width()
|
|||||||
For every ``ImageField``, the object will have ``get_FOO_height()`` and
|
For every ``ImageField``, the object will have ``get_FOO_height()`` and
|
||||||
``get_FOO_width()`` methods, where ``FOO`` is the name of the field. This
|
``get_FOO_width()`` methods, where ``FOO`` is the name of the field. This
|
||||||
returns the height (or width) of the image, as an integer, in pixels.
|
returns the height (or width) of the image, as an integer, in pixels.
|
||||||
|
|
||||||
|
Falling back to raw SQL
|
||||||
|
=======================
|
||||||
|
|
||||||
|
If you find yourself needing to write an SQL query that is too complex for
|
||||||
|
Django's database-mapper to handle, you can fall back into raw-SQL statement
|
||||||
|
mode.
|
||||||
|
|
||||||
|
The preferred way to do this is by giving your model custom methods or custom
|
||||||
|
manager methods that execute queries. Although there's nothing in Django that
|
||||||
|
*requires* database queries to live in the model layer, this approach keeps all
|
||||||
|
your data-access logic in one place, which is smart from an code-organization
|
||||||
|
standpoint. For instructions, see `Executing custom SQL`_.
|
||||||
|
|
||||||
|
Finally, it's important to note that the Django database layer is merely an
|
||||||
|
interface to your database. You can access your database via other tools,
|
||||||
|
programming languages or database frameworks; there's nothing Django-specific
|
||||||
|
about your database.
|
||||||
|
|
||||||
|
.. _Executing custom SQL: http://www.djangoproject.com/documentation/model_api/#executing-custom-sql
|
||||||
|
@ -148,7 +148,11 @@ If you run this script as a user with normal privileges (recommended), you
|
|||||||
might not have access to start a port on a low port number. Low port numbers
|
might not have access to start a port on a low port number. Low port numbers
|
||||||
are reserved for the superuser (root).
|
are reserved for the superuser (root).
|
||||||
|
|
||||||
DO NOT USE THIS SERVER IN A PRODUCTION SETTING.
|
DO NOT USE THIS SERVER IN A PRODUCTION SETTING. It has not gone through
|
||||||
|
security audits or performance tests. (And that's how it's gonna stay. We're in
|
||||||
|
the business of making Web frameworks, not Web servers, so improving this
|
||||||
|
server to be able to handle a production environment is outside the scope of
|
||||||
|
Django.)
|
||||||
|
|
||||||
The development server automatically reloads Python code for each request, as
|
The development server automatically reloads Python code for each request, as
|
||||||
needed. You don't need to restart the server for code changes to take effect.
|
needed. You don't need to restart the server for code changes to take effect.
|
||||||
|
@ -112,7 +112,7 @@ Lawrence, Kansas, USA.
|
|||||||
.. _`Simon Willison`: http://simon.incutio.com/
|
.. _`Simon Willison`: http://simon.incutio.com/
|
||||||
.. _`simon.incutio.com`: http://simon.incutio.com/
|
.. _`simon.incutio.com`: http://simon.incutio.com/
|
||||||
.. _`Jacob Kaplan-Moss`: http://www.jacobian.org/
|
.. _`Jacob Kaplan-Moss`: http://www.jacobian.org/
|
||||||
.. _`Wilson Miner`: http://www.wilsonminer.com/live/
|
.. _`Wilson Miner`: http://www.wilsonminer.com/
|
||||||
|
|
||||||
Which sites use Django?
|
Which sites use Django?
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@ -641,8 +641,10 @@ A page representing a list of objects.
|
|||||||
|
|
||||||
* ``paginate_by``: An integer specifying how many objects should be
|
* ``paginate_by``: An integer specifying how many objects should be
|
||||||
displayed per page. If this is given, the view will paginate objects with
|
displayed per page. If this is given, the view will paginate objects with
|
||||||
``paginate_by`` objects per page. The view will expect a ``page`` query
|
``paginate_by`` objects per page. The view will expect either a ``page``
|
||||||
string (GET) parameter containing a zero-indexed page number.
|
query string parameter (via ``GET``) containing a zero-indexed page
|
||||||
|
number, or a ``page`` variable specified in the URLconf. See
|
||||||
|
"Notes on pagination" below.
|
||||||
|
|
||||||
* ``template_name``: The full name of a template to use in rendering the
|
* ``template_name``: The full name of a template to use in rendering the
|
||||||
page. This lets you override the default template name (see below).
|
page. This lets you override the default template name (see below).
|
||||||
@ -711,6 +713,25 @@ If the results are paginated, the context will contain these extra variables:
|
|||||||
* ``hits``: The total number of objects across *all* pages, not just this
|
* ``hits``: The total number of objects across *all* pages, not just this
|
||||||
page.
|
page.
|
||||||
|
|
||||||
|
Notes on pagination
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
If ``paginate_by`` is specified, Django will paginate the results. You can
|
||||||
|
specify the page number in the URL in one of two ways:
|
||||||
|
|
||||||
|
* Use the ``page`` parameter in the URLconf. For example, this is what
|
||||||
|
your URLconf might look like::
|
||||||
|
|
||||||
|
(r'^objects/page(?P<page>[0-9]+)/$', 'object_list', dict(info_dict))
|
||||||
|
|
||||||
|
* Pass the page number via the ``page`` query-string parameter. For
|
||||||
|
example, a URL would look like this:
|
||||||
|
|
||||||
|
/objects/?page=3
|
||||||
|
|
||||||
|
In both cases, ``page`` is 1-based, not 0-based, so the first page would be
|
||||||
|
represented as page ``1``.
|
||||||
|
|
||||||
``django.views.generic.list_detail.object_detail``
|
``django.views.generic.list_detail.object_detail``
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
||||||
|
@ -1239,6 +1239,12 @@ The above code results in an admin change list page that looks like this:
|
|||||||
|
|
||||||
(This example also has ``search_fields`` defined. See below.)
|
(This example also has ``search_fields`` defined. See below.)
|
||||||
|
|
||||||
|
``list_per_page``
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Set ``list_per_page`` to control how many items appear on each paginated admin
|
||||||
|
change list page. By default, this is set to ``100``.
|
||||||
|
|
||||||
``list_select_related``
|
``list_select_related``
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
@ -291,7 +291,7 @@ The default formatting to use for date fields on Django admin change-list
|
|||||||
pages -- and, possibly, by other parts of the system. See
|
pages -- and, possibly, by other parts of the system. See
|
||||||
`allowed date format strings`_.
|
`allowed date format strings`_.
|
||||||
|
|
||||||
See also DATETIME_FORMAT and TIME_FORMAT.
|
See also DATETIME_FORMAT, TIME_FORMAT, YEAR_MONTH_FORMAT and MONTH_DAY_FORMAT.
|
||||||
|
|
||||||
.. _allowed date format strings: http://www.djangoproject.com/documentation/templates/#now
|
.. _allowed date format strings: http://www.djangoproject.com/documentation/templates/#now
|
||||||
|
|
||||||
@ -304,7 +304,7 @@ The default formatting to use for datetime fields on Django admin change-list
|
|||||||
pages -- and, possibly, by other parts of the system. See
|
pages -- and, possibly, by other parts of the system. See
|
||||||
`allowed date format strings`_.
|
`allowed date format strings`_.
|
||||||
|
|
||||||
See also DATE_FORMAT and TIME_FORMAT.
|
See also DATE_FORMAT, DATETIME_FORMAT, TIME_FORMAT, YEAR_MONTH_FORMAT and MONTH_DAY_FORMAT.
|
||||||
|
|
||||||
.. _allowed date format strings: http://www.djangoproject.com/documentation/templates/#now
|
.. _allowed date format strings: http://www.djangoproject.com/documentation/templates/#now
|
||||||
|
|
||||||
@ -532,6 +532,23 @@ Default::
|
|||||||
|
|
||||||
A tuple of middleware classes to use. See the `middleware docs`_.
|
A tuple of middleware classes to use. See the `middleware docs`_.
|
||||||
|
|
||||||
|
MONTH_DAY_FORMAT
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Default: ``'F j'``
|
||||||
|
|
||||||
|
The default formatting to use for date fields on Django admin change-list
|
||||||
|
pages -- and, possibly, by other parts of the system -- in cases when only the
|
||||||
|
month and day are displayed.
|
||||||
|
|
||||||
|
For example, when a Django admin change-list page is being filtered by a date
|
||||||
|
drilldown, the header for a given day displays the day and month. Different
|
||||||
|
locales have different formats. For example, U.S. English would say
|
||||||
|
"January 1," whereas Spanish might say "1 Enero."
|
||||||
|
|
||||||
|
See `allowed date format strings`_. See also DATE_FORMAT, DATETIME_FORMAT,
|
||||||
|
TIME_FORMAT and YEAR_MONTH_FORMAT.
|
||||||
|
|
||||||
PREPEND_WWW
|
PREPEND_WWW
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
@ -696,7 +713,8 @@ The default formatting to use for time fields on Django admin change-list
|
|||||||
pages -- and, possibly, by other parts of the system. See
|
pages -- and, possibly, by other parts of the system. See
|
||||||
`allowed date format strings`_.
|
`allowed date format strings`_.
|
||||||
|
|
||||||
See also DATE_FORMAT and DATETIME_FORMAT.
|
See also DATE_FORMAT, DATETIME_FORMAT, TIME_FORMAT, YEAR_MONTH_FORMAT and
|
||||||
|
MONTH_DAY_FORMAT.
|
||||||
|
|
||||||
.. _allowed date format strings: http://www.djangoproject.com/documentation/templates/#now
|
.. _allowed date format strings: http://www.djangoproject.com/documentation/templates/#now
|
||||||
|
|
||||||
@ -720,6 +738,23 @@ A boolean that specifies whether to output the "Etag" header. This saves
|
|||||||
bandwidth but slows down performance. This is only used if ``CommonMiddleware``
|
bandwidth but slows down performance. This is only used if ``CommonMiddleware``
|
||||||
is installed (see the `middleware docs`_).
|
is installed (see the `middleware docs`_).
|
||||||
|
|
||||||
|
YEAR_MONTH_FORMAT
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Default: ``'F Y'``
|
||||||
|
|
||||||
|
The default formatting to use for date fields on Django admin change-list
|
||||||
|
pages -- and, possibly, by other parts of the system -- in cases when only the
|
||||||
|
year and month are displayed.
|
||||||
|
|
||||||
|
For example, when a Django admin change-list page is being filtered by a date
|
||||||
|
drilldown, the header for a given month displays the month and the year.
|
||||||
|
Different locales have different formats. For example, U.S. English would say
|
||||||
|
"January 2006," whereas another locale might say "2006/January."
|
||||||
|
|
||||||
|
See `allowed date format strings`_. See also DATE_FORMAT, DATETIME_FORMAT,
|
||||||
|
TIME_FORMAT and MONTH_DAY_FORMAT.
|
||||||
|
|
||||||
.. _cache docs: http://www.djangoproject.com/documentation/cache/
|
.. _cache docs: http://www.djangoproject.com/documentation/cache/
|
||||||
.. _middleware docs: http://www.djangoproject.com/documentation/middleware/
|
.. _middleware docs: http://www.djangoproject.com/documentation/middleware/
|
||||||
.. _session docs: http://www.djangoproject.com/documentation/sessions/
|
.. _session docs: http://www.djangoproject.com/documentation/sessions/
|
||||||
|
@ -1091,3 +1091,27 @@ Value Argument Outputs
|
|||||||
``None`` ``"yeah,no"`` ``"no"`` (converts None to False
|
``None`` ``"yeah,no"`` ``"no"`` (converts None to False
|
||||||
if no mapping for None is given)
|
if no mapping for None is given)
|
||||||
========== ====================== ==================================
|
========== ====================== ==================================
|
||||||
|
|
||||||
|
Other tags and filter libraries
|
||||||
|
===============================
|
||||||
|
|
||||||
|
Django comes with a couple of other template-tag libraries that you have to
|
||||||
|
enable explicitly in your ``INSTALLED_APPS`` setting and enable in your
|
||||||
|
template with the ``{% load %}`` tag.
|
||||||
|
|
||||||
|
django.contrib.humanize
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
A set of Django template filters useful for adding a "human touch" to data. See
|
||||||
|
the `humanize documentation`_.
|
||||||
|
|
||||||
|
.. _humanize documentation: http://www.djangoproject.com/documentation/add_ons/#humanize
|
||||||
|
|
||||||
|
django.contrib.markup
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
A collection of template filters that implement these common markup languages:
|
||||||
|
|
||||||
|
* Textile
|
||||||
|
* Markdown
|
||||||
|
* ReST (ReStructured Text)
|
||||||
|
@ -368,6 +368,11 @@ Generally, you'll store templates in files on your filesystem rather than using
|
|||||||
the low-level ``Template`` API yourself. Save templates in a directory
|
the low-level ``Template`` API yourself. Save templates in a directory
|
||||||
specified as a **template directory**.
|
specified as a **template directory**.
|
||||||
|
|
||||||
|
Django searches for template directories in a number of places, depending on
|
||||||
|
your template-loader settings (see "Loader types" below), but the most basic
|
||||||
|
way of specifying template directories is by using the ``TEMPLATE_DIRS``
|
||||||
|
setting.
|
||||||
|
|
||||||
The TEMPLATE_DIRS setting
|
The TEMPLATE_DIRS setting
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
3
setup.py
3
setup.py
@ -5,7 +5,7 @@ from setuptools import setup, find_packages
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name = "Django",
|
name = "Django",
|
||||||
version = "0.91",
|
version = "0.95",
|
||||||
url = 'http://www.djangoproject.com/',
|
url = 'http://www.djangoproject.com/',
|
||||||
author = 'Lawrence Journal-World',
|
author = 'Lawrence Journal-World',
|
||||||
author_email = 'holovaty@gmail.com',
|
author_email = 'holovaty@gmail.com',
|
||||||
@ -52,6 +52,7 @@ setup(
|
|||||||
'media/img/admin/*.png',
|
'media/img/admin/*.png',
|
||||||
'media/js/*.js',
|
'media/js/*.js',
|
||||||
'media/js/admin/*js'],
|
'media/js/admin/*js'],
|
||||||
|
'django.contrib.comments': ['templates/comments/*.html'],
|
||||||
},
|
},
|
||||||
scripts = ['django/bin/django-admin.py'],
|
scripts = ['django/bin/django-admin.py'],
|
||||||
zip_safe = False,
|
zip_safe = False,
|
||||||
|
@ -10,8 +10,9 @@ class Article(models.Model):
|
|||||||
headline = models.CharField(maxlength=100, default='Default headline')
|
headline = models.CharField(maxlength=100, default='Default headline')
|
||||||
pub_date = models.DateTimeField()
|
pub_date = models.DateTimeField()
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
|
|
||||||
# No articles are in the system yet.
|
# No articles are in the system yet.
|
||||||
@ -41,32 +42,32 @@ datetime.datetime(2005, 7, 28, 0, 0)
|
|||||||
|
|
||||||
# Article.objects.all() returns all the articles in the database.
|
# Article.objects.all() returns all the articles in the database.
|
||||||
>>> Article.objects.all()
|
>>> Article.objects.all()
|
||||||
[Area woman programs in Python]
|
[<Article: Area woman programs in Python>]
|
||||||
|
|
||||||
# Django provides a rich database lookup API.
|
# Django provides a rich database lookup API.
|
||||||
>>> Article.objects.get(id__exact=1)
|
>>> Article.objects.get(id__exact=1)
|
||||||
Area woman programs in Python
|
<Article: Area woman programs in Python>
|
||||||
>>> Article.objects.get(headline__startswith='Area woman')
|
>>> Article.objects.get(headline__startswith='Area woman')
|
||||||
Area woman programs in Python
|
<Article: Area woman programs in Python>
|
||||||
>>> Article.objects.get(pub_date__year=2005)
|
>>> Article.objects.get(pub_date__year=2005)
|
||||||
Area woman programs in Python
|
<Article: Area woman programs in Python>
|
||||||
>>> Article.objects.get(pub_date__year=2005, pub_date__month=7)
|
>>> Article.objects.get(pub_date__year=2005, pub_date__month=7)
|
||||||
Area woman programs in Python
|
<Article: Area woman programs in Python>
|
||||||
>>> Article.objects.get(pub_date__year=2005, pub_date__month=7, pub_date__day=28)
|
>>> Article.objects.get(pub_date__year=2005, pub_date__month=7, pub_date__day=28)
|
||||||
Area woman programs in Python
|
<Article: Area woman programs in Python>
|
||||||
|
|
||||||
# The "__exact" lookup type can be omitted, as a shortcut.
|
# The "__exact" lookup type can be omitted, as a shortcut.
|
||||||
>>> Article.objects.get(id=1)
|
>>> Article.objects.get(id=1)
|
||||||
Area woman programs in Python
|
<Article: Area woman programs in Python>
|
||||||
>>> Article.objects.get(headline='Area woman programs in Python')
|
>>> Article.objects.get(headline='Area woman programs in Python')
|
||||||
Area woman programs in Python
|
<Article: Area woman programs in Python>
|
||||||
|
|
||||||
>>> Article.objects.filter(pub_date__year=2005)
|
>>> Article.objects.filter(pub_date__year=2005)
|
||||||
[Area woman programs in Python]
|
[<Article: Area woman programs in Python>]
|
||||||
>>> Article.objects.filter(pub_date__year=2004)
|
>>> Article.objects.filter(pub_date__year=2004)
|
||||||
[]
|
[]
|
||||||
>>> Article.objects.filter(pub_date__year=2005, pub_date__month=7)
|
>>> Article.objects.filter(pub_date__year=2005, pub_date__month=7)
|
||||||
[Area woman programs in Python]
|
[<Article: Area woman programs in Python>]
|
||||||
|
|
||||||
# Django raises an Article.DoesNotExist exception for get() if the parameters
|
# Django raises an Article.DoesNotExist exception for get() if the parameters
|
||||||
# don't match any object.
|
# don't match any object.
|
||||||
@ -84,7 +85,7 @@ DoesNotExist: Article matching query does not exist.
|
|||||||
# shortcut for primary-key exact lookups.
|
# shortcut for primary-key exact lookups.
|
||||||
# The following is identical to articles.get(id=1).
|
# The following is identical to articles.get(id=1).
|
||||||
>>> Article.objects.get(pk=1)
|
>>> Article.objects.get(pk=1)
|
||||||
Area woman programs in Python
|
<Article: Area woman programs in Python>
|
||||||
|
|
||||||
# Model instances of the same type and same ID are considered equal.
|
# Model instances of the same type and same ID are considered equal.
|
||||||
>>> a = Article.objects.get(pk=1)
|
>>> a = Article.objects.get(pk=1)
|
||||||
@ -222,7 +223,7 @@ datetime.datetime(2005, 7, 28, 0, 0)
|
|||||||
>>> s1 = Article.objects.filter(id__exact=1)
|
>>> s1 = Article.objects.filter(id__exact=1)
|
||||||
>>> s2 = Article.objects.filter(id__exact=2)
|
>>> s2 = Article.objects.filter(id__exact=2)
|
||||||
>>> s1 | s2
|
>>> s1 | s2
|
||||||
[Area woman programs in Python, Second article]
|
[<Article: Area woman programs in Python>, <Article: Second article>]
|
||||||
>>> s1 & s2
|
>>> s1 & s2
|
||||||
[]
|
[]
|
||||||
|
|
||||||
@ -232,34 +233,34 @@ datetime.datetime(2005, 7, 28, 0, 0)
|
|||||||
|
|
||||||
# You can get items using index and slice notation.
|
# You can get items using index and slice notation.
|
||||||
>>> Article.objects.all()[0]
|
>>> Article.objects.all()[0]
|
||||||
Area woman programs in Python
|
<Article: Area woman programs in Python>
|
||||||
>>> Article.objects.all()[1:3]
|
>>> Article.objects.all()[1:3]
|
||||||
[Second article, Third article]
|
[<Article: Second article>, <Article: Third article>]
|
||||||
>>> s3 = Article.objects.filter(id__exact=3)
|
>>> s3 = Article.objects.filter(id__exact=3)
|
||||||
>>> (s1 | s2 | s3)[::2]
|
>>> (s1 | s2 | s3)[::2]
|
||||||
[Area woman programs in Python, Third article]
|
[<Article: Area woman programs in Python>, <Article: Third article>]
|
||||||
|
|
||||||
# Slices (without step) are lazy:
|
# Slices (without step) are lazy:
|
||||||
>>> Article.objects.all()[0:5].filter()
|
>>> Article.objects.all()[0:5].filter()
|
||||||
[Area woman programs in Python, Second article, Third article, Fourth article, Article 6]
|
[<Article: Area woman programs in Python>, <Article: Second article>, <Article: Third article>, <Article: Fourth article>, <Article: Article 6>]
|
||||||
|
|
||||||
# Slicing again works:
|
# Slicing again works:
|
||||||
>>> Article.objects.all()[0:5][0:2]
|
>>> Article.objects.all()[0:5][0:2]
|
||||||
[Area woman programs in Python, Second article]
|
[<Article: Area woman programs in Python>, <Article: Second article>]
|
||||||
>>> Article.objects.all()[0:5][:2]
|
>>> Article.objects.all()[0:5][:2]
|
||||||
[Area woman programs in Python, Second article]
|
[<Article: Area woman programs in Python>, <Article: Second article>]
|
||||||
>>> Article.objects.all()[0:5][4:]
|
>>> Article.objects.all()[0:5][4:]
|
||||||
[Article 6]
|
[<Article: Article 6>]
|
||||||
>>> Article.objects.all()[0:5][5:]
|
>>> Article.objects.all()[0:5][5:]
|
||||||
[]
|
[]
|
||||||
|
|
||||||
# Some more tests!
|
# Some more tests!
|
||||||
>>> Article.objects.all()[2:][0:2]
|
>>> Article.objects.all()[2:][0:2]
|
||||||
[Third article, Fourth article]
|
[<Article: Third article>, <Article: Fourth article>]
|
||||||
>>> Article.objects.all()[2:][:2]
|
>>> Article.objects.all()[2:][:2]
|
||||||
[Third article, Fourth article]
|
[<Article: Third article>, <Article: Fourth article>]
|
||||||
>>> Article.objects.all()[2:][2:3]
|
>>> Article.objects.all()[2:][2:3]
|
||||||
[Article 6]
|
[<Article: Article 6>]
|
||||||
|
|
||||||
# Note that you can't use 'offset' without 'limit' (on some dbs), so this doesn't work:
|
# Note that you can't use 'offset' without 'limit' (on some dbs), so this doesn't work:
|
||||||
>>> Article.objects.all()[2:]
|
>>> Article.objects.all()[2:]
|
||||||
@ -308,10 +309,10 @@ AttributeError: Manager isn't accessible via Article instances
|
|||||||
|
|
||||||
# Bulk delete test: How many objects before and after the delete?
|
# Bulk delete test: How many objects before and after the delete?
|
||||||
>>> Article.objects.all()
|
>>> Article.objects.all()
|
||||||
[Area woman programs in Python, Second article, Third article, Fourth article, Article 6, Default headline, Article 7, Updated article 8]
|
[<Article: Area woman programs in Python>, <Article: Second article>, <Article: Third article>, <Article: Fourth article>, <Article: Article 6>, <Article: Default headline>, <Article: Article 7>, <Article: Updated article 8>]
|
||||||
>>> Article.objects.filter(id__lte=4).delete()
|
>>> Article.objects.filter(id__lte=4).delete()
|
||||||
>>> Article.objects.all()
|
>>> Article.objects.all()
|
||||||
[Article 6, Default headline, Article 7, Updated article 8]
|
[<Article: Article 6>, <Article: Default headline>, <Article: Article 7>, <Article: Updated article 8>]
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ class Person(models.Model):
|
|||||||
name = models.CharField(maxlength=20)
|
name = models.CharField(maxlength=20)
|
||||||
gender = models.CharField(maxlength=1, choices=GENDER_CHOICES)
|
gender = models.CharField(maxlength=1, choices=GENDER_CHOICES)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
|
@ -12,7 +12,7 @@ class Person(models.Model):
|
|||||||
first_name = models.CharField(maxlength=30, db_column='firstname')
|
first_name = models.CharField(maxlength=30, db_column='firstname')
|
||||||
last_name = models.CharField(maxlength=30, db_column='last')
|
last_name = models.CharField(maxlength=30, db_column='last')
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return '%s %s' % (self.first_name, self.last_name)
|
return '%s %s' % (self.first_name, self.last_name)
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
@ -24,13 +24,13 @@ API_TESTS = """
|
|||||||
1
|
1
|
||||||
|
|
||||||
>>> Person.objects.all()
|
>>> Person.objects.all()
|
||||||
[John Smith]
|
[<Person: John Smith>]
|
||||||
|
|
||||||
>>> Person.objects.filter(first_name__exact='John')
|
>>> Person.objects.filter(first_name__exact='John')
|
||||||
[John Smith]
|
[<Person: John Smith>]
|
||||||
|
|
||||||
>>> Person.objects.get(first_name__exact='John')
|
>>> Person.objects.get(first_name__exact='John')
|
||||||
John Smith
|
<Person: John Smith>
|
||||||
|
|
||||||
>>> Person.objects.filter(firstname__exact='John')
|
>>> Person.objects.filter(firstname__exact='John')
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
|
@ -23,7 +23,7 @@ class Person(models.Model):
|
|||||||
fun = models.BooleanField()
|
fun = models.BooleanField()
|
||||||
objects = PersonManager()
|
objects = PersonManager()
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return "%s %s" % (self.first_name, self.last_name)
|
return "%s %s" % (self.first_name, self.last_name)
|
||||||
|
|
||||||
# An example of a custom manager that sets get_query_set().
|
# An example of a custom manager that sets get_query_set().
|
||||||
@ -39,7 +39,7 @@ class Book(models.Model):
|
|||||||
published_objects = PublishedBookManager()
|
published_objects = PublishedBookManager()
|
||||||
authors = models.ManyToManyField(Person, related_name='books')
|
authors = models.ManyToManyField(Person, related_name='books')
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.title
|
return self.title
|
||||||
|
|
||||||
# An example of providing multiple custom managers.
|
# An example of providing multiple custom managers.
|
||||||
@ -55,7 +55,7 @@ class Car(models.Model):
|
|||||||
cars = models.Manager()
|
cars = models.Manager()
|
||||||
fast_cars = FastCarManager()
|
fast_cars = FastCarManager()
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
@ -64,7 +64,7 @@ API_TESTS = """
|
|||||||
>>> p2 = Person(first_name='Droopy', last_name='Dog', fun=False)
|
>>> p2 = Person(first_name='Droopy', last_name='Dog', fun=False)
|
||||||
>>> p2.save()
|
>>> p2.save()
|
||||||
>>> Person.objects.get_fun_people()
|
>>> Person.objects.get_fun_people()
|
||||||
[Bugs Bunny]
|
[<Person: Bugs Bunny>]
|
||||||
|
|
||||||
# The RelatedManager used on the 'books' descriptor extends the default manager
|
# The RelatedManager used on the 'books' descriptor extends the default manager
|
||||||
>>> from modeltests.custom_managers.models import PublishedBookManager
|
>>> from modeltests.custom_managers.models import PublishedBookManager
|
||||||
@ -89,19 +89,19 @@ AttributeError: type object 'Book' has no attribute 'objects'
|
|||||||
True
|
True
|
||||||
|
|
||||||
>>> Book.published_objects.all()
|
>>> Book.published_objects.all()
|
||||||
[How to program]
|
[<Book: How to program>]
|
||||||
|
|
||||||
>>> c1 = Car(name='Corvette', mileage=21, top_speed=180)
|
>>> c1 = Car(name='Corvette', mileage=21, top_speed=180)
|
||||||
>>> c1.save()
|
>>> c1.save()
|
||||||
>>> c2 = Car(name='Neon', mileage=31, top_speed=100)
|
>>> c2 = Car(name='Neon', mileage=31, top_speed=100)
|
||||||
>>> c2.save()
|
>>> c2.save()
|
||||||
>>> Car.cars.order_by('name')
|
>>> Car.cars.order_by('name')
|
||||||
[Corvette, Neon]
|
[<Car: Corvette>, <Car: Neon>]
|
||||||
>>> Car.fast_cars.all()
|
>>> Car.fast_cars.all()
|
||||||
[Corvette]
|
[<Car: Corvette>]
|
||||||
|
|
||||||
# Each model class gets a "_default_manager" attribute, which is a reference
|
# Each model class gets a "_default_manager" attribute, which is a reference
|
||||||
# to the first manager defined in the class. In this case, it's "cars".
|
# to the first manager defined in the class. In this case, it's "cars".
|
||||||
>>> Car._default_manager.order_by('name')
|
>>> Car._default_manager.order_by('name')
|
||||||
[Corvette, Neon]
|
[<Car: Corvette>, <Car: Neon>]
|
||||||
"""
|
"""
|
||||||
|
@ -11,16 +11,16 @@ class Article(models.Model):
|
|||||||
headline = models.CharField(maxlength=100)
|
headline = models.CharField(maxlength=100)
|
||||||
pub_date = models.DateField()
|
pub_date = models.DateField()
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
def was_published_today(self):
|
def was_published_today(self):
|
||||||
return self.pub_date == datetime.date.today()
|
return self.pub_date == datetime.date.today()
|
||||||
|
|
||||||
def get_articles_from_same_day_1(self):
|
def articles_from_same_day_1(self):
|
||||||
return Article.objects.filter(pub_date=self.pub_date).exclude(id=self.id)
|
return Article.objects.filter(pub_date=self.pub_date).exclude(id=self.id)
|
||||||
|
|
||||||
def get_articles_from_same_day_2(self):
|
def articles_from_same_day_2(self):
|
||||||
"""
|
"""
|
||||||
Verbose version of get_articles_from_same_day_1, which does a custom
|
Verbose version of get_articles_from_same_day_1, which does a custom
|
||||||
database query for the sake of demonstration.
|
database query for the sake of demonstration.
|
||||||
@ -47,12 +47,12 @@ API_TESTS = """
|
|||||||
# Test the custom methods.
|
# Test the custom methods.
|
||||||
>>> a.was_published_today()
|
>>> a.was_published_today()
|
||||||
False
|
False
|
||||||
>>> a.get_articles_from_same_day_1()
|
>>> a.articles_from_same_day_1()
|
||||||
[Beatles reunite]
|
[<Article: Beatles reunite>]
|
||||||
>>> a.get_articles_from_same_day_2()
|
>>> a.articles_from_same_day_2()
|
||||||
[Beatles reunite]
|
[<Article: Beatles reunite>]
|
||||||
>>> b.get_articles_from_same_day_1()
|
>>> b.articles_from_same_day_1()
|
||||||
[Area man programs in Python]
|
[<Article: Area man programs in Python>]
|
||||||
>>> b.get_articles_from_same_day_2()
|
>>> b.articles_from_same_day_2()
|
||||||
[Area man programs in Python]
|
[<Article: Area man programs in Python>]
|
||||||
"""
|
"""
|
||||||
|
@ -14,7 +14,7 @@ class Employee(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('last_name', 'first_name')
|
ordering = ('last_name', 'first_name')
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return "%s %s" % (self.first_name, self.last_name)
|
return "%s %s" % (self.first_name, self.last_name)
|
||||||
|
|
||||||
class Business(models.Model):
|
class Business(models.Model):
|
||||||
@ -23,24 +23,24 @@ class Business(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name_plural = 'businesses'
|
verbose_name_plural = 'businesses'
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
>>> dan = Employee(employee_code='ABC123', first_name='Dan', last_name='Jones')
|
>>> dan = Employee(employee_code='ABC123', first_name='Dan', last_name='Jones')
|
||||||
>>> dan.save()
|
>>> dan.save()
|
||||||
>>> Employee.objects.all()
|
>>> Employee.objects.all()
|
||||||
[Dan Jones]
|
[<Employee: Dan Jones>]
|
||||||
|
|
||||||
>>> fran = Employee(employee_code='XYZ456', first_name='Fran', last_name='Bones')
|
>>> fran = Employee(employee_code='XYZ456', first_name='Fran', last_name='Bones')
|
||||||
>>> fran.save()
|
>>> fran.save()
|
||||||
>>> Employee.objects.all()
|
>>> Employee.objects.all()
|
||||||
[Fran Bones, Dan Jones]
|
[<Employee: Fran Bones>, <Employee: Dan Jones>]
|
||||||
|
|
||||||
>>> Employee.objects.get(pk='ABC123')
|
>>> Employee.objects.get(pk='ABC123')
|
||||||
Dan Jones
|
<Employee: Dan Jones>
|
||||||
>>> Employee.objects.get(pk='XYZ456')
|
>>> Employee.objects.get(pk='XYZ456')
|
||||||
Fran Bones
|
<Employee: Fran Bones>
|
||||||
>>> Employee.objects.get(pk='foo')
|
>>> Employee.objects.get(pk='foo')
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
@ -48,43 +48,43 @@ DoesNotExist: Employee matching query does not exist.
|
|||||||
|
|
||||||
# Use the name of the primary key, rather than pk.
|
# Use the name of the primary key, rather than pk.
|
||||||
>>> Employee.objects.get(employee_code__exact='ABC123')
|
>>> Employee.objects.get(employee_code__exact='ABC123')
|
||||||
Dan Jones
|
<Employee: Dan Jones>
|
||||||
|
|
||||||
# Fran got married and changed her last name.
|
# Fran got married and changed her last name.
|
||||||
>>> fran = Employee.objects.get(pk='XYZ456')
|
>>> fran = Employee.objects.get(pk='XYZ456')
|
||||||
>>> fran.last_name = 'Jones'
|
>>> fran.last_name = 'Jones'
|
||||||
>>> fran.save()
|
>>> fran.save()
|
||||||
>>> Employee.objects.filter(last_name__exact='Jones')
|
>>> Employee.objects.filter(last_name__exact='Jones')
|
||||||
[Dan Jones, Fran Jones]
|
[<Employee: Dan Jones>, <Employee: Fran Jones>]
|
||||||
>>> Employee.objects.in_bulk(['ABC123', 'XYZ456'])
|
>>> Employee.objects.in_bulk(['ABC123', 'XYZ456'])
|
||||||
{'XYZ456': Fran Jones, 'ABC123': Dan Jones}
|
{'XYZ456': <Employee: Fran Jones>, 'ABC123': <Employee: Dan Jones>}
|
||||||
|
|
||||||
>>> b = Business(name='Sears')
|
>>> b = Business(name='Sears')
|
||||||
>>> b.save()
|
>>> b.save()
|
||||||
>>> b.employees.add(dan, fran)
|
>>> b.employees.add(dan, fran)
|
||||||
>>> b.employees.all()
|
>>> b.employees.all()
|
||||||
[Dan Jones, Fran Jones]
|
[<Employee: Dan Jones>, <Employee: Fran Jones>]
|
||||||
>>> fran.business_set.all()
|
>>> fran.business_set.all()
|
||||||
[Sears]
|
[<Business: Sears>]
|
||||||
>>> Business.objects.in_bulk(['Sears'])
|
>>> Business.objects.in_bulk(['Sears'])
|
||||||
{'Sears': Sears}
|
{'Sears': <Business: Sears>}
|
||||||
|
|
||||||
>>> Business.objects.filter(name__exact='Sears')
|
>>> Business.objects.filter(name__exact='Sears')
|
||||||
[Sears]
|
[<Business: Sears>]
|
||||||
>>> Business.objects.filter(pk='Sears')
|
>>> Business.objects.filter(pk='Sears')
|
||||||
[Sears]
|
[<Business: Sears>]
|
||||||
|
|
||||||
# Queries across tables, involving primary key
|
# Queries across tables, involving primary key
|
||||||
>>> Employee.objects.filter(business__name__exact='Sears')
|
>>> Employee.objects.filter(business__name__exact='Sears')
|
||||||
[Dan Jones, Fran Jones]
|
[<Employee: Dan Jones>, <Employee: Fran Jones>]
|
||||||
>>> Employee.objects.filter(business__pk='Sears')
|
>>> Employee.objects.filter(business__pk='Sears')
|
||||||
[Dan Jones, Fran Jones]
|
[<Employee: Dan Jones>, <Employee: Fran Jones>]
|
||||||
|
|
||||||
>>> Business.objects.filter(employees__employee_code__exact='ABC123')
|
>>> Business.objects.filter(employees__employee_code__exact='ABC123')
|
||||||
[Sears]
|
[<Business: Sears>]
|
||||||
>>> Business.objects.filter(employees__pk='ABC123')
|
>>> Business.objects.filter(employees__pk='ABC123')
|
||||||
[Sears]
|
[<Business: Sears>]
|
||||||
>>> Business.objects.filter(employees__first_name__startswith='Fran')
|
>>> Business.objects.filter(employees__first_name__startswith='Fran')
|
||||||
[Sears]
|
[<Business: Sears>]
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -17,7 +17,7 @@ class Article(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
get_latest_by = 'pub_date'
|
get_latest_by = 'pub_date'
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
class Person(models.Model):
|
class Person(models.Model):
|
||||||
@ -26,7 +26,7 @@ class Person(models.Model):
|
|||||||
|
|
||||||
# Note that this model doesn't have "get_latest_by" set.
|
# Note that this model doesn't have "get_latest_by" set.
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
@ -49,19 +49,19 @@ DoesNotExist: Article matching query does not exist.
|
|||||||
|
|
||||||
# Get the latest Article.
|
# Get the latest Article.
|
||||||
>>> Article.objects.latest()
|
>>> Article.objects.latest()
|
||||||
Article 4
|
<Article: Article 4>
|
||||||
|
|
||||||
# Get the latest Article that matches certain filters.
|
# Get the latest Article that matches certain filters.
|
||||||
>>> Article.objects.filter(pub_date__lt=datetime(2005, 7, 27)).latest()
|
>>> Article.objects.filter(pub_date__lt=datetime(2005, 7, 27)).latest()
|
||||||
Article 1
|
<Article: Article 1>
|
||||||
|
|
||||||
# Pass a custom field name to latest() to change the field that's used to
|
# Pass a custom field name to latest() to change the field that's used to
|
||||||
# determine the latest object.
|
# determine the latest object.
|
||||||
>>> Article.objects.latest('expire_date')
|
>>> Article.objects.latest('expire_date')
|
||||||
Article 1
|
<Article: Article 1>
|
||||||
|
|
||||||
>>> Article.objects.filter(pub_date__gt=datetime(2005, 7, 26)).latest('expire_date')
|
>>> Article.objects.filter(pub_date__gt=datetime(2005, 7, 26)).latest('expire_date')
|
||||||
Article 3
|
<Article: Article 3>
|
||||||
|
|
||||||
# You can still use latest() with a model that doesn't have "get_latest_by"
|
# You can still use latest() with a model that doesn't have "get_latest_by"
|
||||||
# set -- just pass in the field name manually.
|
# set -- just pass in the field name manually.
|
||||||
@ -75,5 +75,5 @@ Traceback (most recent call last):
|
|||||||
AssertionError: latest() requires either a field_name parameter or 'get_latest_by' in the model
|
AssertionError: latest() requires either a field_name parameter or 'get_latest_by' in the model
|
||||||
|
|
||||||
>>> Person.objects.latest('birthday')
|
>>> Person.objects.latest('birthday')
|
||||||
Stephanie
|
<Person: Stephanie>
|
||||||
"""
|
"""
|
||||||
|
@ -12,7 +12,7 @@ class Article(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('-pub_date', 'headline')
|
ordering = ('-pub_date', 'headline')
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
@ -61,9 +61,9 @@ Article 4
|
|||||||
# in_bulk() takes a list of IDs and returns a dictionary mapping IDs
|
# in_bulk() takes a list of IDs and returns a dictionary mapping IDs
|
||||||
# to objects.
|
# to objects.
|
||||||
>>> Article.objects.in_bulk([1, 2])
|
>>> Article.objects.in_bulk([1, 2])
|
||||||
{1: Article 1, 2: Article 2}
|
{1: <Article: Article 1>, 2: <Article: Article 2>}
|
||||||
>>> Article.objects.in_bulk([3])
|
>>> Article.objects.in_bulk([3])
|
||||||
{3: Article 3}
|
{3: <Article: Article 3>}
|
||||||
>>> Article.objects.in_bulk([1000])
|
>>> Article.objects.in_bulk([1000])
|
||||||
{}
|
{}
|
||||||
>>> Article.objects.in_bulk([])
|
>>> Article.objects.in_bulk([])
|
||||||
@ -125,55 +125,55 @@ True
|
|||||||
# In the case of identical date values, these methods will use the ID as a
|
# In the case of identical date values, these methods will use the ID as a
|
||||||
# fallback check. This guarantees that no records are skipped or duplicated.
|
# fallback check. This guarantees that no records are skipped or duplicated.
|
||||||
>>> a1.get_next_by_pub_date()
|
>>> a1.get_next_by_pub_date()
|
||||||
Article 2
|
<Article: Article 2>
|
||||||
>>> a2.get_next_by_pub_date()
|
>>> a2.get_next_by_pub_date()
|
||||||
Article 3
|
<Article: Article 3>
|
||||||
>>> a3.get_next_by_pub_date()
|
>>> a3.get_next_by_pub_date()
|
||||||
Article 7
|
<Article: Article 7>
|
||||||
>>> a4.get_next_by_pub_date()
|
>>> a4.get_next_by_pub_date()
|
||||||
Article 6
|
<Article: Article 6>
|
||||||
>>> a5.get_next_by_pub_date()
|
>>> a5.get_next_by_pub_date()
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
DoesNotExist: Article matching query does not exist.
|
DoesNotExist: Article matching query does not exist.
|
||||||
>>> a6.get_next_by_pub_date()
|
>>> a6.get_next_by_pub_date()
|
||||||
Article 5
|
<Article: Article 5>
|
||||||
>>> a7.get_next_by_pub_date()
|
>>> a7.get_next_by_pub_date()
|
||||||
Article 4
|
<Article: Article 4>
|
||||||
|
|
||||||
>>> a7.get_previous_by_pub_date()
|
>>> a7.get_previous_by_pub_date()
|
||||||
Article 3
|
<Article: Article 3>
|
||||||
>>> a6.get_previous_by_pub_date()
|
>>> a6.get_previous_by_pub_date()
|
||||||
Article 4
|
<Article: Article 4>
|
||||||
>>> a5.get_previous_by_pub_date()
|
>>> a5.get_previous_by_pub_date()
|
||||||
Article 6
|
<Article: Article 6>
|
||||||
>>> a4.get_previous_by_pub_date()
|
>>> a4.get_previous_by_pub_date()
|
||||||
Article 7
|
<Article: Article 7>
|
||||||
>>> a3.get_previous_by_pub_date()
|
>>> a3.get_previous_by_pub_date()
|
||||||
Article 2
|
<Article: Article 2>
|
||||||
>>> a2.get_previous_by_pub_date()
|
>>> a2.get_previous_by_pub_date()
|
||||||
Article 1
|
<Article: Article 1>
|
||||||
|
|
||||||
# Underscores and percent signs have special meaning in the underlying
|
# Underscores and percent signs have special meaning in the underlying
|
||||||
# database library, but Django handles the quoting of them automatically.
|
# database library, but Django handles the quoting of them automatically.
|
||||||
>>> a8 = Article(headline='Article_ with underscore', pub_date=datetime(2005, 11, 20))
|
>>> a8 = Article(headline='Article_ with underscore', pub_date=datetime(2005, 11, 20))
|
||||||
>>> a8.save()
|
>>> a8.save()
|
||||||
>>> Article.objects.filter(headline__startswith='Article')
|
>>> Article.objects.filter(headline__startswith='Article')
|
||||||
[Article_ with underscore, Article 5, Article 6, Article 4, Article 2, Article 3, Article 7, Article 1]
|
[<Article: Article_ with underscore>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
|
||||||
>>> Article.objects.filter(headline__startswith='Article_')
|
>>> Article.objects.filter(headline__startswith='Article_')
|
||||||
[Article_ with underscore]
|
[<Article: Article_ with underscore>]
|
||||||
>>> a9 = Article(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21))
|
>>> a9 = Article(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21))
|
||||||
>>> a9.save()
|
>>> a9.save()
|
||||||
>>> Article.objects.filter(headline__startswith='Article')
|
>>> Article.objects.filter(headline__startswith='Article')
|
||||||
[Article% with percent sign, Article_ with underscore, Article 5, Article 6, Article 4, Article 2, Article 3, Article 7, Article 1]
|
[<Article: Article% with percent sign>, <Article: Article_ with underscore>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
|
||||||
>>> Article.objects.filter(headline__startswith='Article%')
|
>>> Article.objects.filter(headline__startswith='Article%')
|
||||||
[Article% with percent sign]
|
[<Article: Article% with percent sign>]
|
||||||
|
|
||||||
# exclude() is the opposite of filter() when doing lookups:
|
# exclude() is the opposite of filter() when doing lookups:
|
||||||
>>> Article.objects.filter(headline__contains='Article').exclude(headline__contains='with')
|
>>> Article.objects.filter(headline__contains='Article').exclude(headline__contains='with')
|
||||||
[Article 5, Article 6, Article 4, Article 2, Article 3, Article 7, Article 1]
|
[<Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
|
||||||
>>> Article.objects.exclude(headline__startswith="Article_")
|
>>> Article.objects.exclude(headline__startswith="Article_")
|
||||||
[Article% with percent sign, Article 5, Article 6, Article 4, Article 2, Article 3, Article 7, Article 1]
|
[<Article: Article% with percent sign>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
|
||||||
>>> Article.objects.exclude(headline="Article 7")
|
>>> Article.objects.exclude(headline="Article 7")
|
||||||
[Article% with percent sign, Article_ with underscore, Article 5, Article 6, Article 4, Article 2, Article 3, Article 1]
|
[<Article: Article% with percent sign>, <Article: Article_ with underscore>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 1>]
|
||||||
"""
|
"""
|
||||||
|
@ -16,14 +16,14 @@ class Reporter(models.Model):
|
|||||||
first_name = models.CharField(maxlength=30)
|
first_name = models.CharField(maxlength=30)
|
||||||
last_name = models.CharField(maxlength=30)
|
last_name = models.CharField(maxlength=30)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return "%s %s" % (self.first_name, self.last_name)
|
return "%s %s" % (self.first_name, self.last_name)
|
||||||
|
|
||||||
class Article(models.Model):
|
class Article(models.Model):
|
||||||
headline = models.CharField(maxlength=100)
|
headline = models.CharField(maxlength=100)
|
||||||
pub_date = models.DateField()
|
pub_date = models.DateField()
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
class Writer(models.Model):
|
class Writer(models.Model):
|
||||||
@ -31,8 +31,8 @@ class Writer(models.Model):
|
|||||||
article = models.ForeignKey(Article)
|
article = models.ForeignKey(Article)
|
||||||
position = models.CharField(maxlength=100)
|
position = models.CharField(maxlength=100)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return '%r (%s)' % (self.reporter, self.position)
|
return '%s (%s)' % (self.reporter, self.position)
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
# Create a few Reporters.
|
# Create a few Reporters.
|
||||||
@ -54,15 +54,15 @@ API_TESTS = """
|
|||||||
|
|
||||||
# Play around with the API.
|
# Play around with the API.
|
||||||
>>> a.writer_set.select_related().order_by('-position')
|
>>> a.writer_set.select_related().order_by('-position')
|
||||||
[John Smith (Main writer), Jane Doe (Contributor)]
|
[<Writer: John Smith (Main writer)>, <Writer: Jane Doe (Contributor)>]
|
||||||
>>> w1.reporter
|
>>> w1.reporter
|
||||||
John Smith
|
<Reporter: John Smith>
|
||||||
>>> w2.reporter
|
>>> w2.reporter
|
||||||
Jane Doe
|
<Reporter: Jane Doe>
|
||||||
>>> w1.article
|
>>> w1.article
|
||||||
This is a test
|
<Article: This is a test>
|
||||||
>>> w2.article
|
>>> w2.article
|
||||||
This is a test
|
<Article: This is a test>
|
||||||
>>> r1.writer_set.all()
|
>>> r1.writer_set.all()
|
||||||
[John Smith (Main writer)]
|
[<Writer: John Smith (Main writer)>]
|
||||||
"""
|
"""
|
||||||
|
@ -14,7 +14,7 @@ class Category(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('name',)
|
ordering = ('name',)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
class Article(models.Model):
|
class Article(models.Model):
|
||||||
@ -25,7 +25,7 @@ class Article(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('pub_date',)
|
ordering = ('pub_date',)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
@ -51,29 +51,29 @@ API_TESTS = """
|
|||||||
>>> a2.secondary_categories.add(c4)
|
>>> a2.secondary_categories.add(c4)
|
||||||
|
|
||||||
>>> a1.primary_categories.all()
|
>>> a1.primary_categories.all()
|
||||||
[Crime, News]
|
[<Category: Crime>, <Category: News>]
|
||||||
|
|
||||||
>>> a2.primary_categories.all()
|
>>> a2.primary_categories.all()
|
||||||
[News, Sports]
|
[<Category: News>, <Category: Sports>]
|
||||||
|
|
||||||
>>> a1.secondary_categories.all()
|
>>> a1.secondary_categories.all()
|
||||||
[Life]
|
[<Category: Life>]
|
||||||
|
|
||||||
|
|
||||||
>>> c1.primary_article_set.all()
|
>>> c1.primary_article_set.all()
|
||||||
[Area man runs]
|
[<Article: Area man runs>]
|
||||||
>>> c1.secondary_article_set.all()
|
>>> c1.secondary_article_set.all()
|
||||||
[]
|
[]
|
||||||
>>> c2.primary_article_set.all()
|
>>> c2.primary_article_set.all()
|
||||||
[Area man steals, Area man runs]
|
[<Article: Area man steals>, <Article: Area man runs>]
|
||||||
>>> c2.secondary_article_set.all()
|
>>> c2.secondary_article_set.all()
|
||||||
[]
|
[]
|
||||||
>>> c3.primary_article_set.all()
|
>>> c3.primary_article_set.all()
|
||||||
[Area man steals]
|
[<Article: Area man steals>]
|
||||||
>>> c3.secondary_article_set.all()
|
>>> c3.secondary_article_set.all()
|
||||||
[]
|
[]
|
||||||
>>> c4.primary_article_set.all()
|
>>> c4.primary_article_set.all()
|
||||||
[]
|
[]
|
||||||
>>> c4.secondary_article_set.all()
|
>>> c4.secondary_article_set.all()
|
||||||
[Area man steals, Area man runs]
|
[<Article: Area man steals>, <Article: Area man runs>]
|
||||||
"""
|
"""
|
||||||
|
@ -19,7 +19,7 @@ class Person(models.Model):
|
|||||||
friends = models.ManyToManyField('self')
|
friends = models.ManyToManyField('self')
|
||||||
idols = models.ManyToManyField('self', symmetrical=False, related_name='stalkers')
|
idols = models.ManyToManyField('self', symmetrical=False, related_name='stalkers')
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
@ -41,37 +41,37 @@ API_TESTS = """
|
|||||||
|
|
||||||
# Who is friends with Anne?
|
# Who is friends with Anne?
|
||||||
>>> a.friends.all()
|
>>> a.friends.all()
|
||||||
[Bill, Chuck, David]
|
[<Person: Bill>, <Person: Chuck>, <Person: David>]
|
||||||
|
|
||||||
# Who is friends with Bill?
|
# Who is friends with Bill?
|
||||||
>>> b.friends.all()
|
>>> b.friends.all()
|
||||||
[Anne]
|
[<Person: Anne>]
|
||||||
|
|
||||||
# Who is friends with Chuck?
|
# Who is friends with Chuck?
|
||||||
>>> c.friends.all()
|
>>> c.friends.all()
|
||||||
[Anne, David]
|
[<Person: Anne>, <Person: David>]
|
||||||
|
|
||||||
# Who is friends with David?
|
# Who is friends with David?
|
||||||
>>> d.friends.all()
|
>>> d.friends.all()
|
||||||
[Anne, Chuck]
|
[<Person: Anne>, <Person: Chuck>]
|
||||||
|
|
||||||
# Bill is already friends with Anne - add Anne again, but in the reverse direction
|
# Bill is already friends with Anne - add Anne again, but in the reverse direction
|
||||||
>>> b.friends.add(a)
|
>>> b.friends.add(a)
|
||||||
|
|
||||||
# Who is friends with Anne?
|
# Who is friends with Anne?
|
||||||
>>> a.friends.all()
|
>>> a.friends.all()
|
||||||
[Bill, Chuck, David]
|
[<Person: Bill>, <Person: Chuck>, <Person: David>]
|
||||||
|
|
||||||
# Who is friends with Bill?
|
# Who is friends with Bill?
|
||||||
>>> b.friends.all()
|
>>> b.friends.all()
|
||||||
[Anne]
|
[<Person: Anne>]
|
||||||
|
|
||||||
# Remove Anne from Bill's friends
|
# Remove Anne from Bill's friends
|
||||||
>>> b.friends.remove(a)
|
>>> b.friends.remove(a)
|
||||||
|
|
||||||
# Who is friends with Anne?
|
# Who is friends with Anne?
|
||||||
>>> a.friends.all()
|
>>> a.friends.all()
|
||||||
[Chuck, David]
|
[<Person: Chuck>, <Person: David>]
|
||||||
|
|
||||||
# Who is friends with Bill?
|
# Who is friends with Bill?
|
||||||
>>> b.friends.all()
|
>>> b.friends.all()
|
||||||
@ -87,11 +87,11 @@ API_TESTS = """
|
|||||||
# Reverse relationships should also be gone
|
# Reverse relationships should also be gone
|
||||||
# Who is friends with Chuck?
|
# Who is friends with Chuck?
|
||||||
>>> c.friends.all()
|
>>> c.friends.all()
|
||||||
[David]
|
[<Person: David>]
|
||||||
|
|
||||||
# Who is friends with David?
|
# Who is friends with David?
|
||||||
>>> d.friends.all()
|
>>> d.friends.all()
|
||||||
[Chuck]
|
[<Person: Chuck>]
|
||||||
|
|
||||||
|
|
||||||
# Add some idols in the direction of field definition
|
# Add some idols in the direction of field definition
|
||||||
@ -106,27 +106,27 @@ API_TESTS = """
|
|||||||
|
|
||||||
# Who are Anne's idols?
|
# Who are Anne's idols?
|
||||||
>>> a.idols.all()
|
>>> a.idols.all()
|
||||||
[Bill, Chuck, David]
|
[<Person: Bill>, <Person: Chuck>, <Person: David>]
|
||||||
|
|
||||||
# Who is stalking Anne?
|
# Who is stalking Anne?
|
||||||
>>> a.stalkers.all()
|
>>> a.stalkers.all()
|
||||||
[Bill]
|
[<Person: Bill>]
|
||||||
|
|
||||||
# Who are Bill's idols?
|
# Who are Bill's idols?
|
||||||
>>> b.idols.all()
|
>>> b.idols.all()
|
||||||
[Anne]
|
[<Person: Anne>]
|
||||||
|
|
||||||
# Who is stalking Bill?
|
# Who is stalking Bill?
|
||||||
>>> b.stalkers.all()
|
>>> b.stalkers.all()
|
||||||
[Anne]
|
[<Person: Anne>]
|
||||||
|
|
||||||
# Who are Chuck's idols?
|
# Who are Chuck's idols?
|
||||||
>>> c.idols.all()
|
>>> c.idols.all()
|
||||||
[David]
|
[<Person: David>]
|
||||||
|
|
||||||
# Who is stalking Chuck?
|
# Who is stalking Chuck?
|
||||||
>>> c.stalkers.all()
|
>>> c.stalkers.all()
|
||||||
[Anne]
|
[<Person: Anne>]
|
||||||
|
|
||||||
# Who are David's idols?
|
# Who are David's idols?
|
||||||
>>> d.idols.all()
|
>>> d.idols.all()
|
||||||
@ -134,40 +134,40 @@ API_TESTS = """
|
|||||||
|
|
||||||
# Who is stalking David
|
# Who is stalking David
|
||||||
>>> d.stalkers.all()
|
>>> d.stalkers.all()
|
||||||
[Anne, Chuck]
|
[<Person: Anne>, <Person: Chuck>]
|
||||||
|
|
||||||
# Bill is already being stalked by Anne - add Anne again, but in the reverse direction
|
# Bill is already being stalked by Anne - add Anne again, but in the reverse direction
|
||||||
>>> b.stalkers.add(a)
|
>>> b.stalkers.add(a)
|
||||||
|
|
||||||
# Who are Anne's idols?
|
# Who are Anne's idols?
|
||||||
>>> a.idols.all()
|
>>> a.idols.all()
|
||||||
[Bill, Chuck, David]
|
[<Person: Bill>, <Person: Chuck>, <Person: David>]
|
||||||
|
|
||||||
# Who is stalking Anne?
|
# Who is stalking Anne?
|
||||||
[Bill]
|
[<Person: Bill>]
|
||||||
|
|
||||||
# Who are Bill's idols
|
# Who are Bill's idols
|
||||||
>>> b.idols.all()
|
>>> b.idols.all()
|
||||||
[Anne]
|
[<Person: Anne>]
|
||||||
|
|
||||||
# Who is stalking Bill?
|
# Who is stalking Bill?
|
||||||
>>> b.stalkers.all()
|
>>> b.stalkers.all()
|
||||||
[Anne]
|
[<Person: Anne>]
|
||||||
|
|
||||||
# Remove Anne from Bill's list of stalkers
|
# Remove Anne from Bill's list of stalkers
|
||||||
>>> b.stalkers.remove(a)
|
>>> b.stalkers.remove(a)
|
||||||
|
|
||||||
# Who are Anne's idols?
|
# Who are Anne's idols?
|
||||||
>>> a.idols.all()
|
>>> a.idols.all()
|
||||||
[Chuck, David]
|
[<Person: Chuck>, <Person: David>]
|
||||||
|
|
||||||
# Who is stalking Anne?
|
# Who is stalking Anne?
|
||||||
>>> a.stalkers.all()
|
>>> a.stalkers.all()
|
||||||
[Bill]
|
[<Person: Bill>]
|
||||||
|
|
||||||
# Who are Bill's idols?
|
# Who are Bill's idols?
|
||||||
>>> b.idols.all()
|
>>> b.idols.all()
|
||||||
[Anne]
|
[<Person: Anne>]
|
||||||
|
|
||||||
# Who is stalking Bill?
|
# Who is stalking Bill?
|
||||||
>>> b.stalkers.all()
|
>>> b.stalkers.all()
|
||||||
@ -187,6 +187,6 @@ API_TESTS = """
|
|||||||
|
|
||||||
# Who is friends with David?
|
# Who is friends with David?
|
||||||
>>> d.stalkers.all()
|
>>> d.stalkers.all()
|
||||||
[Chuck]
|
[<Person: Chuck>]
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -16,7 +16,7 @@ class Category(models.Model):
|
|||||||
name = models.CharField(maxlength=20)
|
name = models.CharField(maxlength=20)
|
||||||
parent = models.ForeignKey('self', null=True, related_name='child_set')
|
parent = models.ForeignKey('self', null=True, related_name='child_set')
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
@ -27,14 +27,14 @@ API_TESTS = """
|
|||||||
>>> c.save()
|
>>> c.save()
|
||||||
|
|
||||||
>>> r.child_set.all()
|
>>> r.child_set.all()
|
||||||
[Child category]
|
[<Category: Child category>]
|
||||||
>>> r.child_set.get(name__startswith='Child')
|
>>> r.child_set.get(name__startswith='Child')
|
||||||
Child category
|
<Category: Child category>
|
||||||
>>> print r.parent
|
>>> print r.parent
|
||||||
None
|
None
|
||||||
|
|
||||||
>>> c.child_set.all()
|
>>> c.child_set.all()
|
||||||
[]
|
[]
|
||||||
>>> c.parent
|
>>> c.parent
|
||||||
Root category
|
<Category: Root category>
|
||||||
"""
|
"""
|
||||||
|
@ -14,7 +14,7 @@ class Person(models.Model):
|
|||||||
mother = models.ForeignKey('self', null=True, related_name='mothers_child_set')
|
mother = models.ForeignKey('self', null=True, related_name='mothers_child_set')
|
||||||
father = models.ForeignKey('self', null=True, related_name='fathers_child_set')
|
father = models.ForeignKey('self', null=True, related_name='fathers_child_set')
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.full_name
|
return self.full_name
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
@ -29,13 +29,13 @@ API_TESTS = """
|
|||||||
>>> kid.save()
|
>>> kid.save()
|
||||||
|
|
||||||
>>> kid.mother
|
>>> kid.mother
|
||||||
Jane Smith
|
<Person: Jane Smith>
|
||||||
>>> kid.father
|
>>> kid.father
|
||||||
John Smith Senior
|
<Person: John Smith Senior>
|
||||||
>>> dad.fathers_child_set.all()
|
>>> dad.fathers_child_set.all()
|
||||||
[John Smith Junior]
|
[<Person: John Smith Junior>]
|
||||||
>>> mom.mothers_child_set.all()
|
>>> mom.mothers_child_set.all()
|
||||||
[John Smith Junior]
|
[<Person: John Smith Junior>]
|
||||||
>>> kid.mothers_child_set.all()
|
>>> kid.mothers_child_set.all()
|
||||||
[]
|
[]
|
||||||
>>> kid.fathers_child_set.all()
|
>>> kid.fathers_child_set.all()
|
||||||
|
@ -10,7 +10,7 @@ class Musician(models.Model):
|
|||||||
first_name = models.CharField(maxlength=30)
|
first_name = models.CharField(maxlength=30)
|
||||||
last_name = models.CharField(maxlength=30)
|
last_name = models.CharField(maxlength=30)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return "%s %s" % (self.first_name, self.last_name)
|
return "%s %s" % (self.first_name, self.last_name)
|
||||||
|
|
||||||
class Album(models.Model):
|
class Album(models.Model):
|
||||||
@ -18,7 +18,7 @@ class Album(models.Model):
|
|||||||
musician = models.ForeignKey(Musician)
|
musician = models.ForeignKey(Musician)
|
||||||
release_date = models.DateField(blank=True, null=True)
|
release_date = models.DateField(blank=True, null=True)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
@ -35,7 +35,7 @@ API_TESTS = """
|
|||||||
|
|
||||||
# Verify it worked.
|
# Verify it worked.
|
||||||
>>> Musician.objects.all()
|
>>> Musician.objects.all()
|
||||||
[Ella Fitzgerald]
|
[<Musician: Ella Fitzgerald>]
|
||||||
>>> [m1] == list(Musician.objects.all())
|
>>> [m1] == list(Musician.objects.all())
|
||||||
True
|
True
|
||||||
|
|
||||||
@ -69,9 +69,9 @@ True
|
|||||||
|
|
||||||
# Verify it worked.
|
# Verify it worked.
|
||||||
>>> Album.objects.all()
|
>>> Album.objects.all()
|
||||||
[Ella and Basie]
|
[<Album: Ella and Basie>]
|
||||||
>>> Album.objects.get().musician
|
>>> Album.objects.get().musician
|
||||||
Ella Fitzgerald
|
<Musician: Ella Fitzgerald>
|
||||||
|
|
||||||
# Create an Album with a release_date.
|
# Create an Album with a release_date.
|
||||||
>>> data = MultiValueDict({'name': ['Ultimate Ella'], 'musician': ['1'], 'release_date': ['2005-02-13']})
|
>>> data = MultiValueDict({'name': ['Ultimate Ella'], 'musician': ['1'], 'release_date': ['2005-02-13']})
|
||||||
@ -82,10 +82,10 @@ Ella Fitzgerald
|
|||||||
|
|
||||||
# Verify it worked.
|
# Verify it worked.
|
||||||
>>> Album.objects.order_by('name')
|
>>> Album.objects.order_by('name')
|
||||||
[Ella and Basie, Ultimate Ella]
|
[<Album: Ella and Basie>, <Album: Ultimate Ella>]
|
||||||
>>> a2 = Album.objects.get(pk=2)
|
>>> a2 = Album.objects.get(pk=2)
|
||||||
>>> a2
|
>>> a2
|
||||||
Ultimate Ella
|
<Album: Ultimate Ella>
|
||||||
>>> a2.release_date
|
>>> a2.release_date
|
||||||
datetime.date(2005, 2, 13)
|
datetime.date(2005, 2, 13)
|
||||||
"""
|
"""
|
||||||
|
@ -12,7 +12,7 @@ from django.db import models
|
|||||||
class Publication(models.Model):
|
class Publication(models.Model):
|
||||||
title = models.CharField(maxlength=30)
|
title = models.CharField(maxlength=30)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.title
|
return self.title
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -22,7 +22,7 @@ class Article(models.Model):
|
|||||||
headline = models.CharField(maxlength=100)
|
headline = models.CharField(maxlength=100)
|
||||||
publications = models.ManyToManyField(Publication)
|
publications = models.ManyToManyField(Publication)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -58,29 +58,29 @@ API_TESTS = """
|
|||||||
|
|
||||||
# Article objects have access to their related Publication objects.
|
# Article objects have access to their related Publication objects.
|
||||||
>>> a1.publications.all()
|
>>> a1.publications.all()
|
||||||
[The Python Journal]
|
[<Publication: The Python Journal>]
|
||||||
>>> a2.publications.all()
|
>>> a2.publications.all()
|
||||||
[Highlights for Children, Science News, Science Weekly, The Python Journal]
|
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]
|
||||||
|
|
||||||
# Publication objects have access to their related Article objects.
|
# Publication objects have access to their related Article objects.
|
||||||
>>> p2.article_set.all()
|
>>> p2.article_set.all()
|
||||||
[NASA uses Python]
|
[<Article: NASA uses Python>]
|
||||||
>>> p1.article_set.all()
|
>>> p1.article_set.all()
|
||||||
[Django lets you build Web apps easily, NASA uses Python]
|
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
|
||||||
>>> Publication.objects.get(id=4).article_set.all()
|
>>> Publication.objects.get(id=4).article_set.all()
|
||||||
[NASA uses Python]
|
[<Article: NASA uses Python>]
|
||||||
|
|
||||||
# We can perform kwarg queries across m2m relationships
|
# We can perform kwarg queries across m2m relationships
|
||||||
>>> Article.objects.filter(publications__id__exact=1)
|
>>> Article.objects.filter(publications__id__exact=1)
|
||||||
[Django lets you build Web apps easily, NASA uses Python]
|
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
|
||||||
>>> Article.objects.filter(publications__pk=1)
|
>>> Article.objects.filter(publications__pk=1)
|
||||||
[Django lets you build Web apps easily, NASA uses Python]
|
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
|
||||||
|
|
||||||
>>> Article.objects.filter(publications__title__startswith="Science")
|
>>> Article.objects.filter(publications__title__startswith="Science")
|
||||||
[NASA uses Python, NASA uses Python]
|
[<Article: NASA uses Python>, <Article: NASA uses Python>]
|
||||||
|
|
||||||
>>> Article.objects.filter(publications__title__startswith="Science").distinct()
|
>>> Article.objects.filter(publications__title__startswith="Science").distinct()
|
||||||
[NASA uses Python]
|
[<Article: NASA uses Python>]
|
||||||
|
|
||||||
# The count() function respects distinct() as well.
|
# The count() function respects distinct() as well.
|
||||||
>>> Article.objects.filter(publications__title__startswith="Science").count()
|
>>> Article.objects.filter(publications__title__startswith="Science").count()
|
||||||
@ -92,23 +92,23 @@ API_TESTS = """
|
|||||||
# Reverse m2m queries are supported (i.e., starting at the table that doesn't
|
# Reverse m2m queries are supported (i.e., starting at the table that doesn't
|
||||||
# have a ManyToManyField).
|
# have a ManyToManyField).
|
||||||
>>> Publication.objects.filter(id__exact=1)
|
>>> Publication.objects.filter(id__exact=1)
|
||||||
[The Python Journal]
|
[<Publication: The Python Journal>]
|
||||||
>>> Publication.objects.filter(pk=1)
|
>>> Publication.objects.filter(pk=1)
|
||||||
[The Python Journal]
|
[<Publication: The Python Journal>]
|
||||||
|
|
||||||
>>> Publication.objects.filter(article__headline__startswith="NASA")
|
>>> Publication.objects.filter(article__headline__startswith="NASA")
|
||||||
[Highlights for Children, Science News, Science Weekly, The Python Journal]
|
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]
|
||||||
|
|
||||||
>>> Publication.objects.filter(article__id__exact=1)
|
>>> Publication.objects.filter(article__id__exact=1)
|
||||||
[The Python Journal]
|
[<Publication: The Python Journal>]
|
||||||
|
|
||||||
>>> Publication.objects.filter(article__pk=1)
|
>>> Publication.objects.filter(article__pk=1)
|
||||||
[The Python Journal]
|
[<Publication: The Python Journal>]
|
||||||
|
|
||||||
# If we delete a Publication, its Articles won't be able to access it.
|
# If we delete a Publication, its Articles won't be able to access it.
|
||||||
>>> p1.delete()
|
>>> p1.delete()
|
||||||
>>> Publication.objects.all()
|
>>> Publication.objects.all()
|
||||||
[Highlights for Children, Science News, Science Weekly]
|
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>]
|
||||||
>>> a1 = Article.objects.get(pk=1)
|
>>> a1 = Article.objects.get(pk=1)
|
||||||
>>> a1.publications.all()
|
>>> a1.publications.all()
|
||||||
[]
|
[]
|
||||||
@ -116,7 +116,7 @@ API_TESTS = """
|
|||||||
# If we delete an Article, its Publications won't be able to access it.
|
# If we delete an Article, its Publications won't be able to access it.
|
||||||
>>> a2.delete()
|
>>> a2.delete()
|
||||||
>>> Article.objects.all()
|
>>> Article.objects.all()
|
||||||
[Django lets you build Web apps easily]
|
[<Article: Django lets you build Web apps easily>]
|
||||||
>>> p2.article_set.all()
|
>>> p2.article_set.all()
|
||||||
[]
|
[]
|
||||||
|
|
||||||
@ -125,22 +125,22 @@ API_TESTS = """
|
|||||||
>>> a4.save()
|
>>> a4.save()
|
||||||
>>> p2.article_set.add(a4)
|
>>> p2.article_set.add(a4)
|
||||||
>>> p2.article_set.all()
|
>>> p2.article_set.all()
|
||||||
[NASA finds intelligent life on Earth]
|
[<Article: NASA finds intelligent life on Earth>]
|
||||||
>>> a4.publications.all()
|
>>> a4.publications.all()
|
||||||
[Science News]
|
[<Publication: Science News>]
|
||||||
|
|
||||||
# Adding via the other end using keywords
|
# Adding via the other end using keywords
|
||||||
>>> new_article = p2.article_set.create(headline='Oxygen-free diet works wonders')
|
>>> new_article = p2.article_set.create(headline='Oxygen-free diet works wonders')
|
||||||
>>> p2.article_set.all()
|
>>> p2.article_set.all()
|
||||||
[NASA finds intelligent life on Earth, Oxygen-free diet works wonders]
|
[<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
|
||||||
>>> a5 = p2.article_set.all()[1]
|
>>> a5 = p2.article_set.all()[1]
|
||||||
>>> a5.publications.all()
|
>>> a5.publications.all()
|
||||||
[Science News]
|
[<Publication: Science News>]
|
||||||
|
|
||||||
# Removing publication from an article:
|
# Removing publication from an article:
|
||||||
>>> a4.publications.remove(p2)
|
>>> a4.publications.remove(p2)
|
||||||
>>> p2.article_set.all()
|
>>> p2.article_set.all()
|
||||||
[Oxygen-free diet works wonders]
|
[<Article: Oxygen-free diet works wonders>]
|
||||||
>>> a4.publications.all()
|
>>> a4.publications.all()
|
||||||
[]
|
[]
|
||||||
|
|
||||||
@ -154,33 +154,33 @@ API_TESTS = """
|
|||||||
# Relation sets can be assigned. Assignment clears any existing set members
|
# Relation sets can be assigned. Assignment clears any existing set members
|
||||||
>>> p2.article_set = [a4, a5]
|
>>> p2.article_set = [a4, a5]
|
||||||
>>> p2.article_set.all()
|
>>> p2.article_set.all()
|
||||||
[NASA finds intelligent life on Earth, Oxygen-free diet works wonders]
|
[<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
|
||||||
>>> a4.publications.all()
|
>>> a4.publications.all()
|
||||||
[Science News]
|
[<Publication: Science News>]
|
||||||
>>> a4.publications = [p3]
|
>>> a4.publications = [p3]
|
||||||
>>> p2.article_set.all()
|
>>> p2.article_set.all()
|
||||||
[Oxygen-free diet works wonders]
|
[<Article: Oxygen-free diet works wonders>]
|
||||||
>>> a4.publications.all()
|
>>> a4.publications.all()
|
||||||
[Science Weekly]
|
[<Publication: Science Weekly>]
|
||||||
|
|
||||||
# Relation sets can be cleared:
|
# Relation sets can be cleared:
|
||||||
>>> p2.article_set.clear()
|
>>> p2.article_set.clear()
|
||||||
>>> p2.article_set.all()
|
>>> p2.article_set.all()
|
||||||
[]
|
[]
|
||||||
>>> a4.publications.all()
|
>>> a4.publications.all()
|
||||||
[Science Weekly]
|
[<Publication: Science Weekly>]
|
||||||
|
|
||||||
# And you can clear from the other end
|
# And you can clear from the other end
|
||||||
>>> p2.article_set.add(a4, a5)
|
>>> p2.article_set.add(a4, a5)
|
||||||
>>> p2.article_set.all()
|
>>> p2.article_set.all()
|
||||||
[NASA finds intelligent life on Earth, Oxygen-free diet works wonders]
|
[<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
|
||||||
>>> a4.publications.all()
|
>>> a4.publications.all()
|
||||||
[Science News, Science Weekly]
|
[<Publication: Science News>, <Publication: Science Weekly>]
|
||||||
>>> a4.publications.clear()
|
>>> a4.publications.clear()
|
||||||
>>> a4.publications.all()
|
>>> a4.publications.all()
|
||||||
[]
|
[]
|
||||||
>>> p2.article_set.all()
|
>>> p2.article_set.all()
|
||||||
[Oxygen-free diet works wonders]
|
[<Article: Oxygen-free diet works wonders>]
|
||||||
|
|
||||||
# Recreate the article and Publication we just deleted.
|
# Recreate the article and Publication we just deleted.
|
||||||
>>> p1 = Publication(id=None, title='The Python Journal')
|
>>> p1 = Publication(id=None, title='The Python Journal')
|
||||||
@ -192,22 +192,22 @@ API_TESTS = """
|
|||||||
# Bulk delete some Publications - references to deleted publications should go
|
# Bulk delete some Publications - references to deleted publications should go
|
||||||
>>> Publication.objects.filter(title__startswith='Science').delete()
|
>>> Publication.objects.filter(title__startswith='Science').delete()
|
||||||
>>> Publication.objects.all()
|
>>> Publication.objects.all()
|
||||||
[Highlights for Children, The Python Journal]
|
[<Publication: Highlights for Children>, <Publication: The Python Journal>]
|
||||||
>>> Article.objects.all()
|
>>> Article.objects.all()
|
||||||
[Django lets you build Web apps easily, NASA finds intelligent life on Earth, NASA uses Python, Oxygen-free diet works wonders]
|
[<Article: Django lets you build Web apps easily>, <Article: NASA finds intelligent life on Earth>, <Article: NASA uses Python>, <Article: Oxygen-free diet works wonders>]
|
||||||
>>> a2.publications.all()
|
>>> a2.publications.all()
|
||||||
[The Python Journal]
|
[<Publication: The Python Journal>]
|
||||||
|
|
||||||
# Bulk delete some articles - references to deleted objects should go
|
# Bulk delete some articles - references to deleted objects should go
|
||||||
>>> q = Article.objects.filter(headline__startswith='Django')
|
>>> q = Article.objects.filter(headline__startswith='Django')
|
||||||
>>> print q
|
>>> print q
|
||||||
[Django lets you build Web apps easily]
|
[<Article: Django lets you build Web apps easily>]
|
||||||
>>> q.delete()
|
>>> q.delete()
|
||||||
|
|
||||||
# After the delete, the QuerySet cache needs to be cleared, and the referenced objects should be gone
|
# After the delete, the QuerySet cache needs to be cleared, and the referenced objects should be gone
|
||||||
>>> print q
|
>>> print q
|
||||||
[]
|
[]
|
||||||
>>> p1.article_set.all()
|
>>> p1.article_set.all()
|
||||||
[NASA uses Python]
|
[<Article: NASA uses Python>]
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -11,7 +11,7 @@ class Reporter(models.Model):
|
|||||||
last_name = models.CharField(maxlength=30)
|
last_name = models.CharField(maxlength=30)
|
||||||
email = models.EmailField()
|
email = models.EmailField()
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return "%s %s" % (self.first_name, self.last_name)
|
return "%s %s" % (self.first_name, self.last_name)
|
||||||
|
|
||||||
class Article(models.Model):
|
class Article(models.Model):
|
||||||
@ -19,7 +19,7 @@ class Article(models.Model):
|
|||||||
pub_date = models.DateField()
|
pub_date = models.DateField()
|
||||||
reporter = models.ForeignKey(Reporter)
|
reporter = models.ForeignKey(Reporter)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -42,7 +42,7 @@ API_TESTS = """
|
|||||||
1
|
1
|
||||||
|
|
||||||
>>> a.reporter
|
>>> a.reporter
|
||||||
John Smith
|
<Reporter: John Smith>
|
||||||
|
|
||||||
# Article objects have access to their related Reporter objects.
|
# Article objects have access to their related Reporter objects.
|
||||||
>>> r = a.reporter
|
>>> r = a.reporter
|
||||||
@ -52,7 +52,7 @@ John Smith
|
|||||||
# Create an Article via the Reporter object.
|
# Create an Article via the Reporter object.
|
||||||
>>> new_article = r.article_set.create(headline="John's second story", pub_date=datetime(2005, 7, 29))
|
>>> new_article = r.article_set.create(headline="John's second story", pub_date=datetime(2005, 7, 29))
|
||||||
>>> new_article
|
>>> new_article
|
||||||
John's second story
|
<Article: John's second story>
|
||||||
>>> new_article.reporter.id
|
>>> new_article.reporter.id
|
||||||
1
|
1
|
||||||
|
|
||||||
@ -62,43 +62,43 @@ John's second story
|
|||||||
>>> new_article2.reporter.id
|
>>> new_article2.reporter.id
|
||||||
1
|
1
|
||||||
>>> r.article_set.all()
|
>>> r.article_set.all()
|
||||||
[John's second story, Paul's story, This is a test]
|
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]
|
||||||
|
|
||||||
# Add the same article to a different article set - check that it moves.
|
# Add the same article to a different article set - check that it moves.
|
||||||
>>> r2.article_set.add(new_article2)
|
>>> r2.article_set.add(new_article2)
|
||||||
>>> new_article2.reporter.id
|
>>> new_article2.reporter.id
|
||||||
2
|
2
|
||||||
>>> r.article_set.all()
|
>>> r.article_set.all()
|
||||||
[John's second story, This is a test]
|
[<Article: John's second story>, <Article: This is a test>]
|
||||||
>>> r2.article_set.all()
|
>>> r2.article_set.all()
|
||||||
[Paul's story]
|
[<Article: Paul's story>]
|
||||||
|
|
||||||
# Assign the article to the reporter directly using the descriptor
|
# Assign the article to the reporter directly using the descriptor
|
||||||
>>> new_article2.reporter = r
|
>>> new_article2.reporter = r
|
||||||
>>> new_article2.save()
|
>>> new_article2.save()
|
||||||
>>> new_article2.reporter
|
>>> new_article2.reporter
|
||||||
John Smith
|
<Reporter: John Smith>
|
||||||
>>> new_article2.reporter.id
|
>>> new_article2.reporter.id
|
||||||
1
|
1
|
||||||
>>> r.article_set.all()
|
>>> r.article_set.all()
|
||||||
[John's second story, Paul's story, This is a test]
|
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]
|
||||||
>>> r2.article_set.all()
|
>>> r2.article_set.all()
|
||||||
[]
|
[]
|
||||||
|
|
||||||
# Set the article back again using set descriptor.
|
# Set the article back again using set descriptor.
|
||||||
>>> r2.article_set = [new_article, new_article2]
|
>>> r2.article_set = [new_article, new_article2]
|
||||||
>>> r.article_set.all()
|
>>> r.article_set.all()
|
||||||
[This is a test]
|
[<Article: This is a test>]
|
||||||
>>> r2.article_set.all()
|
>>> r2.article_set.all()
|
||||||
[John's second story, Paul's story]
|
[<Article: John's second story>, <Article: Paul's story>]
|
||||||
|
|
||||||
# Funny case - assignment notation can only go so far; because the
|
# Funny case - assignment notation can only go so far; because the
|
||||||
# ForeignKey cannot be null, existing members of the set must remain
|
# ForeignKey cannot be null, existing members of the set must remain
|
||||||
>>> r.article_set = [new_article]
|
>>> r.article_set = [new_article]
|
||||||
>>> r.article_set.all()
|
>>> r.article_set.all()
|
||||||
[John's second story, This is a test]
|
[<Article: John's second story>, <Article: This is a test>]
|
||||||
>>> r2.article_set.all()
|
>>> r2.article_set.all()
|
||||||
[Paul's story]
|
[<Article: Paul's story>]
|
||||||
|
|
||||||
# Reporter cannot be null - there should not be a clear or remove method
|
# Reporter cannot be null - there should not be a clear or remove method
|
||||||
>>> hasattr(r2.article_set, 'remove')
|
>>> hasattr(r2.article_set, 'remove')
|
||||||
@ -108,10 +108,10 @@ False
|
|||||||
|
|
||||||
# Reporter objects have access to their related Article objects.
|
# Reporter objects have access to their related Article objects.
|
||||||
>>> r.article_set.all()
|
>>> r.article_set.all()
|
||||||
[John's second story, This is a test]
|
[<Article: John's second story>, <Article: This is a test>]
|
||||||
|
|
||||||
>>> r.article_set.filter(headline__startswith='This')
|
>>> r.article_set.filter(headline__startswith='This')
|
||||||
[This is a test]
|
[<Article: This is a test>]
|
||||||
|
|
||||||
>>> r.article_set.count()
|
>>> r.article_set.count()
|
||||||
2
|
2
|
||||||
@ -121,24 +121,24 @@ False
|
|||||||
|
|
||||||
# Get articles by id
|
# Get articles by id
|
||||||
>>> Article.objects.filter(id__exact=1)
|
>>> Article.objects.filter(id__exact=1)
|
||||||
[This is a test]
|
[<Article: This is a test>]
|
||||||
>>> Article.objects.filter(pk=1)
|
>>> Article.objects.filter(pk=1)
|
||||||
[This is a test]
|
[<Article: This is a test>]
|
||||||
|
|
||||||
# Query on an article property
|
# Query on an article property
|
||||||
>>> Article.objects.filter(headline__startswith='This')
|
>>> Article.objects.filter(headline__startswith='This')
|
||||||
[This is a test]
|
[<Article: This is a test>]
|
||||||
|
|
||||||
# The API automatically follows relationships as far as you need.
|
# The API automatically follows relationships as far as you need.
|
||||||
# Use double underscores to separate relationships.
|
# Use double underscores to separate relationships.
|
||||||
# This works as many levels deep as you want. There's no limit.
|
# This works as many levels deep as you want. There's no limit.
|
||||||
# Find all Articles for any Reporter whose first name is "John".
|
# Find all Articles for any Reporter whose first name is "John".
|
||||||
>>> Article.objects.filter(reporter__first_name__exact='John')
|
>>> Article.objects.filter(reporter__first_name__exact='John')
|
||||||
[John's second story, This is a test]
|
[<Article: John's second story>, <Article: This is a test>]
|
||||||
|
|
||||||
# Query twice over the related field.
|
# Query twice over the related field.
|
||||||
>>> Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith')
|
>>> Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith')
|
||||||
[John's second story, This is a test]
|
[<Article: John's second story>, <Article: This is a test>]
|
||||||
|
|
||||||
# The underlying query only makes one join when a related table is referenced twice.
|
# The underlying query only makes one join when a related table is referenced twice.
|
||||||
>>> query = Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith')
|
>>> query = Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith')
|
||||||
@ -148,13 +148,13 @@ False
|
|||||||
|
|
||||||
# The automatically joined table has a predictable name.
|
# The automatically joined table has a predictable name.
|
||||||
>>> Article.objects.filter(reporter__first_name__exact='John').extra(where=["many_to_one_article__reporter.last_name='Smith'"])
|
>>> Article.objects.filter(reporter__first_name__exact='John').extra(where=["many_to_one_article__reporter.last_name='Smith'"])
|
||||||
[John's second story, This is a test]
|
[<Article: John's second story>, <Article: This is a test>]
|
||||||
|
|
||||||
# Find all Articles for the Reporter whose ID is 1.
|
# Find all Articles for the Reporter whose ID is 1.
|
||||||
>>> Article.objects.filter(reporter__id__exact=1)
|
>>> Article.objects.filter(reporter__id__exact=1)
|
||||||
[John's second story, This is a test]
|
[<Article: John's second story>, <Article: This is a test>]
|
||||||
>>> Article.objects.filter(reporter__pk=1)
|
>>> Article.objects.filter(reporter__pk=1)
|
||||||
[John's second story, This is a test]
|
[<Article: John's second story>, <Article: This is a test>]
|
||||||
|
|
||||||
# You need two underscores between "reporter" and "id" -- not one.
|
# You need two underscores between "reporter" and "id" -- not one.
|
||||||
>>> Article.objects.filter(reporter_id__exact=1)
|
>>> Article.objects.filter(reporter_id__exact=1)
|
||||||
@ -170,7 +170,7 @@ TypeError: Cannot resolve keyword 'reporter_id' into field
|
|||||||
|
|
||||||
# "pk" shortcut syntax works in a related context, too.
|
# "pk" shortcut syntax works in a related context, too.
|
||||||
>>> Article.objects.filter(reporter__pk=1)
|
>>> Article.objects.filter(reporter__pk=1)
|
||||||
[John's second story, This is a test]
|
[<Article: John's second story>, <Article: This is a test>]
|
||||||
|
|
||||||
# You can also instantiate an Article by passing
|
# You can also instantiate an Article by passing
|
||||||
# the Reporter's ID instead of a Reporter object.
|
# the Reporter's ID instead of a Reporter object.
|
||||||
@ -179,31 +179,31 @@ TypeError: Cannot resolve keyword 'reporter_id' into field
|
|||||||
>>> a3.reporter.id
|
>>> a3.reporter.id
|
||||||
1
|
1
|
||||||
>>> a3.reporter
|
>>> a3.reporter
|
||||||
John Smith
|
<Reporter: John Smith>
|
||||||
|
|
||||||
# Similarly, the reporter ID can be a string.
|
# Similarly, the reporter ID can be a string.
|
||||||
>>> a4 = Article(id=None, headline="This is a test", pub_date=datetime(2005, 7, 27), reporter_id="1")
|
>>> a4 = Article(id=None, headline="This is a test", pub_date=datetime(2005, 7, 27), reporter_id="1")
|
||||||
>>> a4.save()
|
>>> a4.save()
|
||||||
>>> a4.reporter
|
>>> a4.reporter
|
||||||
John Smith
|
<Reporter: John Smith>
|
||||||
|
|
||||||
# Reporters can be queried
|
# Reporters can be queried
|
||||||
>>> Reporter.objects.filter(id__exact=1)
|
>>> Reporter.objects.filter(id__exact=1)
|
||||||
[John Smith]
|
[<Reporter: John Smith>]
|
||||||
>>> Reporter.objects.filter(pk=1)
|
>>> Reporter.objects.filter(pk=1)
|
||||||
[John Smith]
|
[<Reporter: John Smith>]
|
||||||
>>> Reporter.objects.filter(first_name__startswith='John')
|
>>> Reporter.objects.filter(first_name__startswith='John')
|
||||||
[John Smith]
|
[<Reporter: John Smith>]
|
||||||
|
|
||||||
# Reporters can query in opposite direction of ForeignKey definition
|
# Reporters can query in opposite direction of ForeignKey definition
|
||||||
>>> Reporter.objects.filter(article__id__exact=1)
|
>>> Reporter.objects.filter(article__id__exact=1)
|
||||||
[John Smith]
|
[<Reporter: John Smith>]
|
||||||
>>> Reporter.objects.filter(article__pk=1)
|
>>> Reporter.objects.filter(article__pk=1)
|
||||||
[John Smith]
|
[<Reporter: John Smith>]
|
||||||
>>> Reporter.objects.filter(article__headline__startswith='This')
|
>>> Reporter.objects.filter(article__headline__startswith='This')
|
||||||
[John Smith, John Smith, John Smith]
|
[<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]
|
||||||
>>> Reporter.objects.filter(article__headline__startswith='This').distinct()
|
>>> Reporter.objects.filter(article__headline__startswith='This').distinct()
|
||||||
[John Smith]
|
[<Reporter: John Smith>]
|
||||||
|
|
||||||
# Counting in the opposite direction works in conjunction with distinct()
|
# Counting in the opposite direction works in conjunction with distinct()
|
||||||
>>> Reporter.objects.filter(article__headline__startswith='This').count()
|
>>> Reporter.objects.filter(article__headline__startswith='This').count()
|
||||||
@ -213,20 +213,20 @@ John Smith
|
|||||||
|
|
||||||
# Queries can go round in circles.
|
# Queries can go round in circles.
|
||||||
>>> Reporter.objects.filter(article__reporter__first_name__startswith='John')
|
>>> Reporter.objects.filter(article__reporter__first_name__startswith='John')
|
||||||
[John Smith, John Smith, John Smith, John Smith]
|
[<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]
|
||||||
>>> Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct()
|
>>> Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct()
|
||||||
[John Smith]
|
[<Reporter: John Smith>]
|
||||||
|
|
||||||
# If you delete a reporter, his articles will be deleted.
|
# If you delete a reporter, his articles will be deleted.
|
||||||
>>> Article.objects.all()
|
>>> Article.objects.all()
|
||||||
[John's second story, Paul's story, This is a test, This is a test, This is a test]
|
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>, <Article: This is a test>, <Article: This is a test>]
|
||||||
>>> Reporter.objects.order_by('first_name')
|
>>> Reporter.objects.order_by('first_name')
|
||||||
[John Smith, Paul Jones]
|
[<Reporter: John Smith>, <Reporter: Paul Jones>]
|
||||||
>>> r2.delete()
|
>>> r2.delete()
|
||||||
>>> Article.objects.all()
|
>>> Article.objects.all()
|
||||||
[John's second story, This is a test, This is a test, This is a test]
|
[<Article: John's second story>, <Article: This is a test>, <Article: This is a test>, <Article: This is a test>]
|
||||||
>>> Reporter.objects.order_by('first_name')
|
>>> Reporter.objects.order_by('first_name')
|
||||||
[John Smith]
|
[<Reporter: John Smith>]
|
||||||
|
|
||||||
# Deletes using a join in the query
|
# Deletes using a join in the query
|
||||||
>>> Reporter.objects.filter(article__headline__startswith='This').delete()
|
>>> Reporter.objects.filter(article__headline__startswith='This').delete()
|
||||||
|
@ -10,19 +10,19 @@ from django.db import models
|
|||||||
class Reporter(models.Model):
|
class Reporter(models.Model):
|
||||||
name = models.CharField(maxlength=30)
|
name = models.CharField(maxlength=30)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
class Article(models.Model):
|
class Article(models.Model):
|
||||||
headline = models.CharField(maxlength=100)
|
headline = models.CharField(maxlength=100)
|
||||||
reporter = models.ForeignKey(Reporter, null=True)
|
reporter = models.ForeignKey(Reporter, null=True)
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return self.headline
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('headline',)
|
ordering = ('headline',)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.headline
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
# Create a Reporter.
|
# Create a Reporter.
|
||||||
>>> r = Reporter(name='John Smith')
|
>>> r = Reporter(name='John Smith')
|
||||||
@ -36,7 +36,7 @@ API_TESTS = """
|
|||||||
1
|
1
|
||||||
|
|
||||||
>>> a.reporter
|
>>> a.reporter
|
||||||
John Smith
|
<Reporter: John Smith>
|
||||||
|
|
||||||
# Article objects have access to their related Reporter objects.
|
# Article objects have access to their related Reporter objects.
|
||||||
>>> r = a.reporter
|
>>> r = a.reporter
|
||||||
@ -44,15 +44,15 @@ John Smith
|
|||||||
# Create an Article via the Reporter object.
|
# Create an Article via the Reporter object.
|
||||||
>>> a2 = r.article_set.create(headline="Second")
|
>>> a2 = r.article_set.create(headline="Second")
|
||||||
>>> a2
|
>>> a2
|
||||||
Second
|
<Article: Second>
|
||||||
>>> a2.reporter.id
|
>>> a2.reporter.id
|
||||||
1
|
1
|
||||||
|
|
||||||
# Reporter objects have access to their related Article objects.
|
# Reporter objects have access to their related Article objects.
|
||||||
>>> r.article_set.all()
|
>>> r.article_set.all()
|
||||||
[First, Second]
|
[<Article: First>, <Article: Second>]
|
||||||
>>> r.article_set.filter(headline__startswith='Fir')
|
>>> r.article_set.filter(headline__startswith='Fir')
|
||||||
[First]
|
[<Article: First>]
|
||||||
>>> r.article_set.count()
|
>>> r.article_set.count()
|
||||||
2
|
2
|
||||||
|
|
||||||
@ -78,47 +78,47 @@ None
|
|||||||
|
|
||||||
# To retrieve the articles with no reporters set, use "reporter__isnull=True".
|
# To retrieve the articles with no reporters set, use "reporter__isnull=True".
|
||||||
>>> Article.objects.filter(reporter__isnull=True)
|
>>> Article.objects.filter(reporter__isnull=True)
|
||||||
[Third]
|
[<Article: Third>]
|
||||||
|
|
||||||
# Set the reporter for the Third article
|
# Set the reporter for the Third article
|
||||||
>>> r.article_set.add(a3)
|
>>> r.article_set.add(a3)
|
||||||
>>> r.article_set.all()
|
>>> r.article_set.all()
|
||||||
[First, Second, Third]
|
[<Article: First>, <Article: Second>, <Article: Third>]
|
||||||
|
|
||||||
# Remove an article from the set, and check that it was removed.
|
# Remove an article from the set, and check that it was removed.
|
||||||
>>> r.article_set.remove(a3)
|
>>> r.article_set.remove(a3)
|
||||||
>>> r.article_set.all()
|
>>> r.article_set.all()
|
||||||
[First, Second]
|
[<Article: First>, <Article: Second>]
|
||||||
>>> Article.objects.filter(reporter__isnull=True)
|
>>> Article.objects.filter(reporter__isnull=True)
|
||||||
[Third]
|
[<Article: Third>]
|
||||||
|
|
||||||
# Create another article and reporter
|
# Create another article and reporter
|
||||||
>>> r2 = Reporter(name='Paul Jones')
|
>>> r2 = Reporter(name='Paul Jones')
|
||||||
>>> r2.save()
|
>>> r2.save()
|
||||||
>>> a4 = r2.article_set.create(headline='Fourth')
|
>>> a4 = r2.article_set.create(headline='Fourth')
|
||||||
>>> r2.article_set.all()
|
>>> r2.article_set.all()
|
||||||
[Fourth]
|
[<Article: Fourth>]
|
||||||
|
|
||||||
# Try to remove a4 from a set it does not belong to
|
# Try to remove a4 from a set it does not belong to
|
||||||
>>> r.article_set.remove(a4)
|
>>> r.article_set.remove(a4)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
DoesNotExist: 'Article object' is not related to 'Reporter object'.
|
DoesNotExist: <Article: Fourth> is not related to <Reporter: John Smith>.
|
||||||
|
|
||||||
>>> r2.article_set.all()
|
>>> r2.article_set.all()
|
||||||
[Fourth]
|
[<Article: Fourth>]
|
||||||
|
|
||||||
# Use descriptor assignment to allocate ForeignKey. Null is legal, so
|
# Use descriptor assignment to allocate ForeignKey. Null is legal, so
|
||||||
# existing members of set that are not in the assignment set are set null
|
# existing members of set that are not in the assignment set are set null
|
||||||
>>> r2.article_set = [a2, a3]
|
>>> r2.article_set = [a2, a3]
|
||||||
>>> r2.article_set.all()
|
>>> r2.article_set.all()
|
||||||
[Second, Third]
|
[<Article: Second>, <Article: Third>]
|
||||||
|
|
||||||
# Clear the rest of the set
|
# Clear the rest of the set
|
||||||
>>> r.article_set.clear()
|
>>> r.article_set.clear()
|
||||||
>>> r.article_set.all()
|
>>> r.article_set.all()
|
||||||
[]
|
[]
|
||||||
>>> Article.objects.filter(reporter__isnull=True)
|
>>> Article.objects.filter(reporter__isnull=True)
|
||||||
[First, Fourth]
|
[<Article: First>, <Article: Fourth>]
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -10,20 +10,20 @@ class Place(models.Model):
|
|||||||
name = models.CharField(maxlength=50)
|
name = models.CharField(maxlength=50)
|
||||||
address = models.CharField(maxlength=80)
|
address = models.CharField(maxlength=80)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return "%s the place" % self.name
|
return "%s the place" % self.name
|
||||||
|
|
||||||
class Restaurant(Place):
|
class Restaurant(Place):
|
||||||
serves_hot_dogs = models.BooleanField()
|
serves_hot_dogs = models.BooleanField()
|
||||||
serves_pizza = models.BooleanField()
|
serves_pizza = models.BooleanField()
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return "%s the restaurant" % self.name
|
return "%s the restaurant" % self.name
|
||||||
|
|
||||||
class ItalianRestaurant(Restaurant):
|
class ItalianRestaurant(Restaurant):
|
||||||
serves_gnocchi = models.BooleanField()
|
serves_gnocchi = models.BooleanField()
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return "%s the italian restaurant" % self.name
|
return "%s the italian restaurant" % self.name
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
|
@ -12,7 +12,7 @@ class Place(models.Model):
|
|||||||
name = models.CharField(maxlength=50)
|
name = models.CharField(maxlength=50)
|
||||||
address = models.CharField(maxlength=80)
|
address = models.CharField(maxlength=80)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return "%s the place" % self.name
|
return "%s the place" % self.name
|
||||||
|
|
||||||
class Restaurant(models.Model):
|
class Restaurant(models.Model):
|
||||||
@ -20,15 +20,15 @@ class Restaurant(models.Model):
|
|||||||
serves_hot_dogs = models.BooleanField()
|
serves_hot_dogs = models.BooleanField()
|
||||||
serves_pizza = models.BooleanField()
|
serves_pizza = models.BooleanField()
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return "%s the restaurant" % self.place.name
|
return "%s the restaurant" % self.place.name
|
||||||
|
|
||||||
class Waiter(models.Model):
|
class Waiter(models.Model):
|
||||||
restaurant = models.ForeignKey(Restaurant)
|
restaurant = models.ForeignKey(Restaurant)
|
||||||
name = models.CharField(maxlength=50)
|
name = models.CharField(maxlength=50)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return "%s the waiter at %r" % (self.name, self.restaurant)
|
return "%s the waiter at %s" % (self.name, self.restaurant)
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
# Create a couple of Places.
|
# Create a couple of Places.
|
||||||
@ -43,11 +43,11 @@ API_TESTS = """
|
|||||||
|
|
||||||
# A Restaurant can access its place.
|
# A Restaurant can access its place.
|
||||||
>>> r.place
|
>>> r.place
|
||||||
Demon Dogs the place
|
<Place: Demon Dogs the place>
|
||||||
|
|
||||||
# A Place can access its restaurant, if available.
|
# A Place can access its restaurant, if available.
|
||||||
>>> p1.restaurant
|
>>> p1.restaurant
|
||||||
Demon Dogs the restaurant
|
<Restaurant: Demon Dogs the restaurant>
|
||||||
|
|
||||||
# p2 doesn't have an associated restaurant.
|
# p2 doesn't have an associated restaurant.
|
||||||
>>> p2.restaurant
|
>>> p2.restaurant
|
||||||
@ -60,9 +60,9 @@ DoesNotExist: Restaurant matching query does not exist.
|
|||||||
>>> r.place = p2
|
>>> r.place = p2
|
||||||
>>> r.save()
|
>>> r.save()
|
||||||
>>> p2.restaurant
|
>>> p2.restaurant
|
||||||
Ace Hardware the restaurant
|
<Restaurant: Ace Hardware the restaurant>
|
||||||
>>> r.place
|
>>> r.place
|
||||||
Ace Hardware the place
|
<Place: Ace Hardware the place>
|
||||||
|
|
||||||
# Set the place back again, using assignment in the reverse direction
|
# Set the place back again, using assignment in the reverse direction
|
||||||
# Need to reget restaurant object first, because the reverse set
|
# Need to reget restaurant object first, because the reverse set
|
||||||
@ -70,59 +70,59 @@ Ace Hardware the place
|
|||||||
>>> p1.restaurant = r
|
>>> p1.restaurant = r
|
||||||
>>> r.save()
|
>>> r.save()
|
||||||
>>> p1.restaurant
|
>>> p1.restaurant
|
||||||
Demon Dogs the restaurant
|
<Restaurant: Demon Dogs the restaurant>
|
||||||
|
|
||||||
>>> r = Restaurant.objects.get(pk=1)
|
>>> r = Restaurant.objects.get(pk=1)
|
||||||
>>> r.place
|
>>> r.place
|
||||||
Demon Dogs the place
|
<Place: Demon Dogs the place>
|
||||||
|
|
||||||
# Restaurant.objects.all() just returns the Restaurants, not the Places.
|
# Restaurant.objects.all() just returns the Restaurants, not the Places.
|
||||||
# Note that there are two restaurants - Ace Hardware the Restaurant was created
|
# Note that there are two restaurants - Ace Hardware the Restaurant was created
|
||||||
# in the call to r.place = p2. This means there are multiple restaurants referencing
|
# in the call to r.place = p2. This means there are multiple restaurants referencing
|
||||||
# a single place...
|
# a single place...
|
||||||
>>> Restaurant.objects.all()
|
>>> Restaurant.objects.all()
|
||||||
[Demon Dogs the restaurant, Ace Hardware the restaurant]
|
[<Restaurant: Demon Dogs the restaurant>, <Restaurant: Ace Hardware the restaurant>]
|
||||||
|
|
||||||
# Place.objects.all() returns all Places, regardless of whether they have
|
# Place.objects.all() returns all Places, regardless of whether they have
|
||||||
# Restaurants.
|
# Restaurants.
|
||||||
>>> Place.objects.order_by('name')
|
>>> Place.objects.order_by('name')
|
||||||
[Ace Hardware the place, Demon Dogs the place]
|
[<Place: Ace Hardware the place>, <Place: Demon Dogs the place>]
|
||||||
|
|
||||||
>>> Restaurant.objects.get(place__id__exact=1)
|
>>> Restaurant.objects.get(place__id__exact=1)
|
||||||
Demon Dogs the restaurant
|
<Restaurant: Demon Dogs the restaurant>
|
||||||
>>> Restaurant.objects.get(pk=1)
|
>>> Restaurant.objects.get(pk=1)
|
||||||
Demon Dogs the restaurant
|
<Restaurant: Demon Dogs the restaurant>
|
||||||
>>> Restaurant.objects.get(place__exact=1)
|
>>> Restaurant.objects.get(place__exact=1)
|
||||||
Demon Dogs the restaurant
|
<Restaurant: Demon Dogs the restaurant>
|
||||||
>>> Restaurant.objects.get(place__pk=1)
|
>>> Restaurant.objects.get(place__pk=1)
|
||||||
Demon Dogs the restaurant
|
<Restaurant: Demon Dogs the restaurant>
|
||||||
>>> Restaurant.objects.get(place__name__startswith="Demon")
|
>>> Restaurant.objects.get(place__name__startswith="Demon")
|
||||||
Demon Dogs the restaurant
|
<Restaurant: Demon Dogs the restaurant>
|
||||||
|
|
||||||
>>> Place.objects.get(id__exact=1)
|
>>> Place.objects.get(id__exact=1)
|
||||||
Demon Dogs the place
|
<Place: Demon Dogs the place>
|
||||||
>>> Place.objects.get(pk=1)
|
>>> Place.objects.get(pk=1)
|
||||||
Demon Dogs the place
|
<Place: Demon Dogs the place>
|
||||||
>>> Place.objects.get(restaurant__place__exact=1)
|
>>> Place.objects.get(restaurant__place__exact=1)
|
||||||
Demon Dogs the place
|
<Place: Demon Dogs the place>
|
||||||
>>> Place.objects.get(restaurant__pk=1)
|
>>> Place.objects.get(restaurant__pk=1)
|
||||||
Demon Dogs the place
|
<Place: Demon Dogs the place>
|
||||||
|
|
||||||
# Add a Waiter to the Restaurant.
|
# Add a Waiter to the Restaurant.
|
||||||
>>> w = r.waiter_set.create(name='Joe')
|
>>> w = r.waiter_set.create(name='Joe')
|
||||||
>>> w.save()
|
>>> w.save()
|
||||||
>>> w
|
>>> w
|
||||||
Joe the waiter at Demon Dogs the restaurant
|
<Waiter: Joe the waiter at Demon Dogs the restaurant>
|
||||||
|
|
||||||
# Query the waiters
|
# Query the waiters
|
||||||
>>> Waiter.objects.filter(restaurant__place__exact=1)
|
>>> Waiter.objects.filter(restaurant__place__exact=1)
|
||||||
[Joe the waiter at Demon Dogs the restaurant]
|
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
|
||||||
>>> Waiter.objects.filter(restaurant__pk=1)
|
>>> Waiter.objects.filter(restaurant__pk=1)
|
||||||
[Joe the waiter at Demon Dogs the restaurant]
|
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
|
||||||
>>> Waiter.objects.filter(id__exact=1)
|
>>> Waiter.objects.filter(id__exact=1)
|
||||||
[Joe the waiter at Demon Dogs the restaurant]
|
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
|
||||||
>>> Waiter.objects.filter(pk=1)
|
>>> Waiter.objects.filter(pk=1)
|
||||||
[Joe the waiter at Demon Dogs the restaurant]
|
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
|
||||||
|
|
||||||
# Delete the restaurant; the waiter should also be removed
|
# Delete the restaurant; the waiter should also be removed
|
||||||
>>> r = Restaurant.objects.get(pk=1)
|
>>> r = Restaurant.objects.get(pk=1)
|
||||||
|
@ -16,10 +16,11 @@ from django.db import models
|
|||||||
class Article(models.Model):
|
class Article(models.Model):
|
||||||
headline = models.CharField(maxlength=50)
|
headline = models.CharField(maxlength=50)
|
||||||
pub_date = models.DateTimeField()
|
pub_date = models.DateTimeField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('pub_date',)
|
ordering = ('pub_date',)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
@ -36,10 +37,10 @@ API_TESTS = """
|
|||||||
>>> a3.save()
|
>>> a3.save()
|
||||||
|
|
||||||
>>> Article.objects.filter(headline__startswith='Hello') | Article.objects.filter(headline__startswith='Goodbye')
|
>>> Article.objects.filter(headline__startswith='Hello') | Article.objects.filter(headline__startswith='Goodbye')
|
||||||
[Hello, Goodbye, Hello and goodbye]
|
[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]
|
||||||
|
|
||||||
>>> Article.objects.filter(Q(headline__startswith='Hello') | Q(headline__startswith='Goodbye'))
|
>>> Article.objects.filter(Q(headline__startswith='Hello') | Q(headline__startswith='Goodbye'))
|
||||||
[Hello, Goodbye, Hello and goodbye]
|
[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]
|
||||||
|
|
||||||
>>> Article.objects.filter(Q(headline__startswith='Hello') & Q(headline__startswith='Goodbye'))
|
>>> Article.objects.filter(Q(headline__startswith='Hello') & Q(headline__startswith='Goodbye'))
|
||||||
[]
|
[]
|
||||||
@ -51,34 +52,34 @@ API_TESTS = """
|
|||||||
[]
|
[]
|
||||||
|
|
||||||
>>> articles.filter(headline__startswith='Hello') & articles.filter(headline__contains='bye')
|
>>> articles.filter(headline__startswith='Hello') & articles.filter(headline__contains='bye')
|
||||||
[Hello and goodbye]
|
[<Article: Hello and goodbye>]
|
||||||
|
|
||||||
>>> Article.objects.filter(Q(headline__contains='bye'), headline__startswith='Hello')
|
>>> Article.objects.filter(Q(headline__contains='bye'), headline__startswith='Hello')
|
||||||
[Hello and goodbye]
|
[<Article: Hello and goodbye>]
|
||||||
|
|
||||||
>>> Article.objects.filter(headline__contains='Hello') | Article.objects.filter(headline__contains='bye')
|
>>> Article.objects.filter(headline__contains='Hello') | Article.objects.filter(headline__contains='bye')
|
||||||
[Hello, Goodbye, Hello and goodbye]
|
[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]
|
||||||
|
|
||||||
>>> Article.objects.filter(headline__iexact='Hello') | Article.objects.filter(headline__contains='ood')
|
>>> Article.objects.filter(headline__iexact='Hello') | Article.objects.filter(headline__contains='ood')
|
||||||
[Hello, Goodbye, Hello and goodbye]
|
[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]
|
||||||
|
|
||||||
>>> Article.objects.filter(Q(pk=1) | Q(pk=2))
|
>>> Article.objects.filter(Q(pk=1) | Q(pk=2))
|
||||||
[Hello, Goodbye]
|
[<Article: Hello>, <Article: Goodbye>]
|
||||||
|
|
||||||
>>> Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))
|
>>> Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))
|
||||||
[Hello, Goodbye, Hello and goodbye]
|
[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]
|
||||||
|
|
||||||
# Q arg objects are ANDed
|
# Q arg objects are ANDed
|
||||||
>>> Article.objects.filter(Q(headline__startswith='Hello'), Q(headline__contains='bye'))
|
>>> Article.objects.filter(Q(headline__startswith='Hello'), Q(headline__contains='bye'))
|
||||||
[Hello and goodbye]
|
[<Article: Hello and goodbye>]
|
||||||
|
|
||||||
# Q arg AND order is irrelevant
|
# Q arg AND order is irrelevant
|
||||||
>>> Article.objects.filter(Q(headline__contains='bye'), headline__startswith='Hello')
|
>>> Article.objects.filter(Q(headline__contains='bye'), headline__startswith='Hello')
|
||||||
[Hello and goodbye]
|
[<Article: Hello and goodbye>]
|
||||||
|
|
||||||
# Try some arg queries with operations other than get_list
|
# Try some arg queries with operations other than get_list
|
||||||
>>> Article.objects.get(Q(headline__startswith='Hello'), Q(headline__contains='bye'))
|
>>> Article.objects.get(Q(headline__startswith='Hello'), Q(headline__contains='bye'))
|
||||||
Hello and goodbye
|
<Article: Hello and goodbye>
|
||||||
|
|
||||||
>>> Article.objects.filter(Q(headline__startswith='Hello') | Q(headline__contains='bye')).count()
|
>>> Article.objects.filter(Q(headline__startswith='Hello') | Q(headline__contains='bye')).count()
|
||||||
3
|
3
|
||||||
@ -87,17 +88,17 @@ Hello and goodbye
|
|||||||
[{'headline': 'Hello and goodbye', 'pub_date': datetime.datetime(2005, 11, 29, 0, 0), 'id': 3}]
|
[{'headline': 'Hello and goodbye', 'pub_date': datetime.datetime(2005, 11, 29, 0, 0), 'id': 3}]
|
||||||
|
|
||||||
>>> Article.objects.filter(Q(headline__startswith='Hello')).in_bulk([1,2])
|
>>> Article.objects.filter(Q(headline__startswith='Hello')).in_bulk([1,2])
|
||||||
{1: Hello}
|
{1: <Article: Hello>}
|
||||||
|
|
||||||
# Demonstrating exclude with a Q object
|
# Demonstrating exclude with a Q object
|
||||||
>>> Article.objects.exclude(Q(headline__startswith='Hello'))
|
>>> Article.objects.exclude(Q(headline__startswith='Hello'))
|
||||||
[Goodbye]
|
[<Article: Goodbye>]
|
||||||
|
|
||||||
# The 'complex_filter' method supports framework features such as
|
# The 'complex_filter' method supports framework features such as
|
||||||
# 'limit_choices_to' which normally take a single dictionary of lookup arguments
|
# 'limit_choices_to' which normally take a single dictionary of lookup arguments
|
||||||
# but need to support arbitrary queries via Q objects too.
|
# but need to support arbitrary queries via Q objects too.
|
||||||
>>> Article.objects.complex_filter({'pk': 1})
|
>>> Article.objects.complex_filter({'pk': 1})
|
||||||
[Hello]
|
[<Article: Hello>]
|
||||||
>>> Article.objects.complex_filter(Q(pk=1) | Q(pk=2))
|
>>> Article.objects.complex_filter(Q(pk=1) | Q(pk=2))
|
||||||
[Hello, Goodbye]
|
[<Article: Hello>, <Article: Goodbye>]
|
||||||
"""
|
"""
|
||||||
|
@ -21,7 +21,7 @@ class Article(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('-pub_date', 'headline')
|
ordering = ('-pub_date', 'headline')
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
@ -39,26 +39,26 @@ API_TESTS = """
|
|||||||
# By default, Article.objects.all() orders by pub_date descending, then
|
# By default, Article.objects.all() orders by pub_date descending, then
|
||||||
# headline ascending.
|
# headline ascending.
|
||||||
>>> Article.objects.all()
|
>>> Article.objects.all()
|
||||||
[Article 4, Article 2, Article 3, Article 1]
|
[<Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 1>]
|
||||||
|
|
||||||
# Override ordering with order_by, which is in the same format as the ordering
|
# Override ordering with order_by, which is in the same format as the ordering
|
||||||
# attribute in models.
|
# attribute in models.
|
||||||
>>> Article.objects.order_by('headline')
|
>>> Article.objects.order_by('headline')
|
||||||
[Article 1, Article 2, Article 3, Article 4]
|
[<Article: Article 1>, <Article: Article 2>, <Article: Article 3>, <Article: Article 4>]
|
||||||
>>> Article.objects.order_by('pub_date', '-headline')
|
>>> Article.objects.order_by('pub_date', '-headline')
|
||||||
[Article 1, Article 3, Article 2, Article 4]
|
[<Article: Article 1>, <Article: Article 3>, <Article: Article 2>, <Article: Article 4>]
|
||||||
|
|
||||||
# Use the 'stop' part of slicing notation to limit the results.
|
# Use the 'stop' part of slicing notation to limit the results.
|
||||||
>>> Article.objects.order_by('headline')[:2]
|
>>> Article.objects.order_by('headline')[:2]
|
||||||
[Article 1, Article 2]
|
[<Article: Article 1>, <Article: Article 2>]
|
||||||
|
|
||||||
# Use the 'stop' and 'start' parts of slicing notation to offset the result list.
|
# Use the 'stop' and 'start' parts of slicing notation to offset the result list.
|
||||||
>>> Article.objects.order_by('headline')[1:3]
|
>>> Article.objects.order_by('headline')[1:3]
|
||||||
[Article 2, Article 3]
|
[<Article: Article 2>, <Article: Article 3>]
|
||||||
|
|
||||||
# Getting a single item should work too:
|
# Getting a single item should work too:
|
||||||
>>> Article.objects.all()[0]
|
>>> Article.objects.all()[0]
|
||||||
Article 4
|
<Article: Article 4>
|
||||||
|
|
||||||
# Use '?' to order randomly. (We're using [...] in the output to indicate we
|
# Use '?' to order randomly. (We're using [...] in the output to indicate we
|
||||||
# don't know what order the output will be in.
|
# don't know what order the output will be in.
|
||||||
|
@ -12,7 +12,7 @@ class Article(models.Model):
|
|||||||
headline = models.CharField(maxlength=100, default='Default headline')
|
headline = models.CharField(maxlength=100, default='Default headline')
|
||||||
pub_date = models.DateTimeField()
|
pub_date = models.DateTimeField()
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
@ -35,11 +35,11 @@ API_TESTS = """
|
|||||||
|
|
||||||
# get the first page (zero-based)
|
# get the first page (zero-based)
|
||||||
>>> paginator.get_page(0)
|
>>> paginator.get_page(0)
|
||||||
[Article 1, Article 2, Article 3, Article 4, Article 5]
|
[<Article: Article 1>, <Article: Article 2>, <Article: Article 3>, <Article: Article 4>, <Article: Article 5>]
|
||||||
|
|
||||||
# get the second page
|
# get the second page
|
||||||
>>> paginator.get_page(1)
|
>>> paginator.get_page(1)
|
||||||
[Article 6, Article 7, Article 8, Article 9]
|
[<Article: Article 6>, <Article: Article 7>, <Article: Article 8>, <Article: Article 9>]
|
||||||
|
|
||||||
# does the first page have a next or previous page?
|
# does the first page have a next or previous page?
|
||||||
>>> paginator.has_next_page(0)
|
>>> paginator.has_next_page(0)
|
||||||
|
@ -21,7 +21,7 @@ class Thing(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'select'
|
db_table = 'select'
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.when
|
return self.when
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
@ -39,18 +39,18 @@ a
|
|||||||
h
|
h
|
||||||
|
|
||||||
>>> Thing.objects.order_by('when')
|
>>> Thing.objects.order_by('when')
|
||||||
[a, h]
|
[<Thing: a>, <Thing: h>]
|
||||||
>>> v = Thing.objects.get(pk='a')
|
>>> v = Thing.objects.get(pk='a')
|
||||||
>>> print v.join
|
>>> print v.join
|
||||||
b
|
b
|
||||||
>>> print v.where
|
>>> print v.where
|
||||||
2005-01-01
|
2005-01-01
|
||||||
>>> Thing.objects.order_by('select.when')
|
>>> Thing.objects.order_by('select.when')
|
||||||
[a, h]
|
[<Thing: a>, <Thing: h>]
|
||||||
|
|
||||||
>>> Thing.objects.dates('where', 'year')
|
>>> Thing.objects.dates('where', 'year')
|
||||||
[datetime.datetime(2005, 1, 1, 0, 0), datetime.datetime(2006, 1, 1, 0, 0)]
|
[datetime.datetime(2005, 1, 1, 0, 0), datetime.datetime(2006, 1, 1, 0, 0)]
|
||||||
|
|
||||||
>>> Thing.objects.filter(where__month=1)
|
>>> Thing.objects.filter(where__month=1)
|
||||||
[a]
|
[<Thing: a>]
|
||||||
"""
|
"""
|
||||||
|
@ -8,20 +8,23 @@ from django.db import models
|
|||||||
|
|
||||||
class User(models.Model):
|
class User(models.Model):
|
||||||
name = models.CharField(maxlength=200)
|
name = models.CharField(maxlength=200)
|
||||||
def __repr__(self):
|
|
||||||
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
class Poll(models.Model):
|
class Poll(models.Model):
|
||||||
question = models.CharField(maxlength=200)
|
question = models.CharField(maxlength=200)
|
||||||
creator = models.ForeignKey(User)
|
creator = models.ForeignKey(User)
|
||||||
def __repr__(self):
|
|
||||||
|
def __str__(self):
|
||||||
return self.question
|
return self.question
|
||||||
|
|
||||||
class Choice(models.Model):
|
class Choice(models.Model):
|
||||||
name = models.CharField(maxlength=100)
|
name = models.CharField(maxlength=100)
|
||||||
poll = models.ForeignKey(Poll, related_name="poll_choice")
|
poll = models.ForeignKey(Poll, related_name="poll_choice")
|
||||||
related_poll = models.ForeignKey(Poll, related_name="related_choice")
|
related_poll = models.ForeignKey(Poll, related_name="related_choice")
|
||||||
def __repr(self):
|
|
||||||
|
def __str(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
@ -38,15 +41,15 @@ API_TESTS = """
|
|||||||
|
|
||||||
>>> # Reverse lookups by field name:
|
>>> # Reverse lookups by field name:
|
||||||
>>> User.objects.get(poll__question__exact="What's the first question?")
|
>>> User.objects.get(poll__question__exact="What's the first question?")
|
||||||
John Doe
|
<User: John Doe>
|
||||||
>>> User.objects.get(poll__question__exact="What's the second question?")
|
>>> User.objects.get(poll__question__exact="What's the second question?")
|
||||||
Jim Bo
|
<User: Jim Bo>
|
||||||
|
|
||||||
>>> # Reverse lookups by related_name:
|
>>> # Reverse lookups by related_name:
|
||||||
>>> Poll.objects.get(poll_choice__name__exact="This is the answer.")
|
>>> Poll.objects.get(poll_choice__name__exact="This is the answer.")
|
||||||
What's the first question?
|
<Poll: What's the first question?>
|
||||||
>>> Poll.objects.get(related_choice__name__exact="This is the answer.")
|
>>> Poll.objects.get(related_choice__name__exact="This is the answer.")
|
||||||
What's the second question?
|
<Poll: What's the second question?>
|
||||||
|
|
||||||
>>> # If a related_name is given you can't use the field name instead:
|
>>> # If a related_name is given you can't use the field name instead:
|
||||||
>>> Poll.objects.get(choice__name__exact="This is the answer")
|
>>> Poll.objects.get(choice__name__exact="This is the answer")
|
||||||
|
@ -11,7 +11,7 @@ class Person(models.Model):
|
|||||||
first_name = models.CharField(maxlength=20)
|
first_name = models.CharField(maxlength=20)
|
||||||
last_name = models.CharField(maxlength=20)
|
last_name = models.CharField(maxlength=20)
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return "%s %s" % (self.first_name, self.last_name)
|
return "%s %s" % (self.first_name, self.last_name)
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
@ -31,7 +31,7 @@ Before save
|
|||||||
After save
|
After save
|
||||||
|
|
||||||
>>> Person.objects.all()
|
>>> Person.objects.all()
|
||||||
[John Smith]
|
[<Person: John Smith>]
|
||||||
|
|
||||||
>>> p1.delete()
|
>>> p1.delete()
|
||||||
Before deletion
|
Before deletion
|
||||||
|
0
tests/modeltests/str/__init__.py
Normal file
0
tests/modeltests/str/__init__.py
Normal file
@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
2. Adding __repr__() to models
|
2. Adding __str__() to models
|
||||||
|
|
||||||
Although it's not a strict requirement, each model should have a ``__repr__()``
|
Although it's not a strict requirement, each model should have a ``__str__()``
|
||||||
method to return a "human-readable" representation of the object. Do this not
|
method to return a "human-readable" representation of the object. Do this not
|
||||||
only for your own sanity when dealing with the interactive prompt, but also
|
only for your own sanity when dealing with the interactive prompt, but also
|
||||||
because objects' representations are used throughout Django's
|
because objects' representations are used throughout Django's
|
||||||
@ -14,7 +14,7 @@ class Article(models.Model):
|
|||||||
headline = models.CharField(maxlength=100)
|
headline = models.CharField(maxlength=100)
|
||||||
pub_date = models.DateTimeField()
|
pub_date = models.DateTimeField()
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
@ -23,9 +23,9 @@ API_TESTS = """
|
|||||||
>>> a = Article(headline='Area man programs in Python', pub_date=datetime(2005, 7, 28))
|
>>> a = Article(headline='Area man programs in Python', pub_date=datetime(2005, 7, 28))
|
||||||
>>> a.save()
|
>>> a.save()
|
||||||
|
|
||||||
>>> repr(a)
|
>>> str(a)
|
||||||
'Area man programs in Python'
|
'Area man programs in Python'
|
||||||
|
|
||||||
>>> a
|
>>> a
|
||||||
Area man programs in Python
|
<Article: Area man programs in Python>
|
||||||
"""
|
"""
|
@ -14,12 +14,19 @@ class Reporter(models.Model):
|
|||||||
last_name = models.CharField(maxlength=30)
|
last_name = models.CharField(maxlength=30)
|
||||||
email = models.EmailField()
|
email = models.EmailField()
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return "%s %s" % (self.first_name, self.last_name)
|
return "%s %s" % (self.first_name, self.last_name)
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
>>> from django.db import connection, transaction
|
>>> from django.db import connection, transaction
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
building_docs = getattr(settings, 'BUILDING_DOCS', False)
|
||||||
|
|
||||||
|
if building_docs or settings.DATABASE_ENGINE != 'mysql':
|
||||||
|
API_TESTS += """
|
||||||
# the default behavior is to autocommit after each save() action
|
# the default behavior is to autocommit after each save() action
|
||||||
>>> def create_a_reporter_then_fail(first, last):
|
>>> def create_a_reporter_then_fail(first, last):
|
||||||
... a = Reporter(first_name=first, last_name=last)
|
... a = Reporter(first_name=first, last_name=last)
|
||||||
@ -33,7 +40,7 @@ Exception: I meant to do that
|
|||||||
|
|
||||||
# The object created before the exception still exists
|
# The object created before the exception still exists
|
||||||
>>> Reporter.objects.all()
|
>>> Reporter.objects.all()
|
||||||
[Alice Smith]
|
[<Reporter: Alice Smith>]
|
||||||
|
|
||||||
# the autocommit decorator works exactly the same as the default behavior
|
# the autocommit decorator works exactly the same as the default behavior
|
||||||
>>> autocomitted_create_then_fail = transaction.autocommit(create_a_reporter_then_fail)
|
>>> autocomitted_create_then_fail = transaction.autocommit(create_a_reporter_then_fail)
|
||||||
@ -44,7 +51,7 @@ Exception: I meant to do that
|
|||||||
|
|
||||||
# Same behavior as before
|
# Same behavior as before
|
||||||
>>> Reporter.objects.all()
|
>>> Reporter.objects.all()
|
||||||
[Alice Smith, Ben Jones]
|
[<Reporter: Alice Smith>, <Reporter: Ben Jones>]
|
||||||
|
|
||||||
# With the commit_on_success decorator, the transaction is only comitted if the
|
# With the commit_on_success decorator, the transaction is only comitted if the
|
||||||
# function doesn't throw an exception
|
# function doesn't throw an exception
|
||||||
@ -56,7 +63,7 @@ Exception: I meant to do that
|
|||||||
|
|
||||||
# This time the object never got saved
|
# This time the object never got saved
|
||||||
>>> Reporter.objects.all()
|
>>> Reporter.objects.all()
|
||||||
[Alice Smith, Ben Jones]
|
[<Reporter: Alice Smith>, <Reporter: Ben Jones>]
|
||||||
|
|
||||||
# If there aren't any exceptions, the data will get saved
|
# If there aren't any exceptions, the data will get saved
|
||||||
>>> def remove_a_reporter():
|
>>> def remove_a_reporter():
|
||||||
@ -66,7 +73,7 @@ Exception: I meant to do that
|
|||||||
>>> remove_comitted_on_success = transaction.commit_on_success(remove_a_reporter)
|
>>> remove_comitted_on_success = transaction.commit_on_success(remove_a_reporter)
|
||||||
>>> remove_comitted_on_success()
|
>>> remove_comitted_on_success()
|
||||||
>>> Reporter.objects.all()
|
>>> Reporter.objects.all()
|
||||||
[Ben Jones]
|
[<Reporter: Ben Jones>]
|
||||||
|
|
||||||
# You can manually manage transactions if you really want to, but you
|
# You can manually manage transactions if you really want to, but you
|
||||||
# have to remember to commit/rollback
|
# have to remember to commit/rollback
|
||||||
@ -77,7 +84,7 @@ Exception: I meant to do that
|
|||||||
>>> manually_managed = transaction.commit_manually(manually_managed)
|
>>> manually_managed = transaction.commit_manually(manually_managed)
|
||||||
>>> manually_managed()
|
>>> manually_managed()
|
||||||
>>> Reporter.objects.all()
|
>>> Reporter.objects.all()
|
||||||
[Ben Jones, Carol Doe]
|
[<Reporter: Ben Jones>, <Reporter: Carol Doe>]
|
||||||
|
|
||||||
# If you forget, you'll get bad errors
|
# If you forget, you'll get bad errors
|
||||||
>>> def manually_managed_mistake():
|
>>> def manually_managed_mistake():
|
||||||
|
@ -17,7 +17,7 @@ class Person(models.Model):
|
|||||||
favorite_moment = models.DateTimeField()
|
favorite_moment = models.DateTimeField()
|
||||||
email = models.EmailField()
|
email = models.EmailField()
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
|
Loading…
x
Reference in New Issue
Block a user