From f9412b4d210d3f89965d399e62a18804fd759f69 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 17 Dec 2009 15:15:26 +0000 Subject: [PATCH] [soc2009/multidb] Merged up to trunk r11885. git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/multidb@11888 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- AUTHORS | 1 + django/conf/locale/pl/LC_MESSAGES/django.mo | Bin 66292 -> 67007 bytes django/conf/locale/pl/LC_MESSAGES/django.po | 348 ++++++++++-------- django/contrib/admindocs/tests/__init__.py | 20 +- django/contrib/admindocs/tests/fields.py | 10 +- django/contrib/admindocs/views.py | 18 +- django/contrib/contenttypes/generic.py | 29 +- django/contrib/gis/db/models/fields.py | 11 +- django/contrib/localflavor/us/models.py | 13 +- django/core/management/commands/dumpdata.py | 15 +- django/db/models/fields/__init__.py | 65 ++-- django/db/models/fields/files.py | 7 +- django/db/models/fields/related.py | 14 +- django/db/models/loading.py | 10 +- django/forms/models.py | 6 +- docs/howto/custom-model-fields.txt | 26 +- tests/modeltests/model_formsets/models.py | 47 +++ .../generic_inline_admin/models.py | 4 +- .../generic_inline_admin/tests.py | 58 ++- 19 files changed, 421 insertions(+), 281 deletions(-) diff --git a/AUTHORS b/AUTHORS index 1bd0863fff547..bf7ee55533b0a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -385,6 +385,7 @@ answer newbie questions, and generally made Django that much better: Vinay Sajip Kadesarin Sanjek Massimo Scamarcia + Paulo Scardine David Schein Bernd Schlapsi schwank@gmail.com diff --git a/django/conf/locale/pl/LC_MESSAGES/django.mo b/django/conf/locale/pl/LC_MESSAGES/django.mo index d52de20b5c007c11fc9b88f2a582a62b66af4d0c..06b72035d5cf5e675b52011858f8e5140ba3489e 100644 GIT binary patch delta 22249 zcmZA92Y6IfyY}&&kc1L?=ym7`z4zWbp-D#r86bot5JCyXL8OQ%3ZWM%3J6k!P!yyW z1(6~}q$ou}nt)0Z)bqb*KfE8;x39DKt!MSM_TDoCzSsF{a?qaXLB5}|2hDM~?xt~^ z0ywU)<8%ymoJ;jp>NuV*jx#&Jaf)D0;%!|Wrz{@Bp7;#wVwcw(CqK@_nz$a*;SG!L zV;FIGH^<3^b&>gePG>TuC>Uza#|YxRm=#IT392b%ISvM$VMwa zhFZuq)VOyr5Oel$oDk-B^7u23Qy4X2N#rn`@|Y1TTYUozC2o!yuoG&cUYHd}V`iL& z9H2Ab{0KGfC#ZhwP~&gK^vv&kX$=k_i*vqJ1s3Og)uB9wU=7qn^-)LI0k!i1s0qfQ zPG%D3#kr`3e2(hB&D>?>2hlg4ilbzvW6NHSlL^nD?$tG{f{#%PDc##~g0Ko|z?!HD z8lV=?46|c9%z|&A#u}=^HQ`;%fR9i|@APpe&WJkd zFx13FQManJ#Whe1Y=Bx|b1QF)YS#q|VN@T^zc`r*)?g)SqV?ABOVo)RMooCe;_Fub z5Ow7LqIQP;Rut7R0(CE|n9WfW^+4Uz7}UVy zu?$W|o!ll&!d<8ZRer;5R|mDxCaCdSA?j>?pl;P!^Ezrl4^cb)2eqNhQEs~;m`?A11u~kjCTgMvsC(1`wXja8op(nKI0)4~ z33W@xq9%A3bux=kJKTus|0U|J*@N2PK~%r*FogM?OJsCUu45^Dj#@~ue(qCR1~(A5 z#s&BcwZN4AjuVL=VJ*CmUW|x#C;q^kgIeGs)aS)I)Jg6~pN{MdnS6K+^W#6Lo#tgU z?X(1HL1j?`R7IUgYb)=GYS#~gF~&@=@)4*Vk3;pFjv9ZFm-E;AxSE0@xCIO1ISj_X zPz(GUwSaU3T(e>|;ylf!VDhlI8BK=p&q(<=31;nybHCkXFf7o zNrPB-pq^NccqVqjJy;vF4{_gycBor409)ZitboT*pZPDa1m=o!t&63I`=P#D-o=J^ z9knoD@p!jm4b;FLF&yJiPxD-Cglkc+<6YD(3QlkrUJN@E*GDa27M90#*bpzG9_|7| z-CIxXzTY@_PRR_`Kv)or;(Nm!c+Ei~6Ck3AM1TR=yiG;33pb zPoNfZ*2*tieAB#->i@)IXM{UXI`pYy7#U5NAJwp^#br=Cs%&u$vp!~_ycq^!S5&|5 zsPUpO6k{+mj==0V$>Mpag|8aH`D-WZD9{47p*rqDox~B;z-LhHE~7f$H1DA%{L_4n zYL{lDJ6YZ3@(}p*3i24LX^i^Wr1IDrn%2M=fA4YQk@<{5#Y_ z&zYA{?XIE5xs5uxhp2G^#=7HXK;4QQ{+Rn;n2e4t0yRJlREGwr_qV0h_e4!N2=z3_ zquRZN8t`3n4tj`}p~l;XdJB%AHgFy_-(~cF|KCxDf=UT%hs876=SP<8s7W6f0pfjim zE}@S8ro|7;=ct8;yy=dU12ujgRQtkM1;eo%_I{K5uL<9^hBGh^@f_5I8&DH&v-*7& ze`E1!^8#vutEdyXje3ahTl@^05&w(TuqpFu{4qYuOhk2f7q#QrsH0kr+R;v{KZ5Fb z8g+yhQSGmyK8k-weI7hSJ*2@C-1j^W)*-Hd`7su?P~TKCdg$ImO|-~dgPLeN>Vskr z>LkvgUaPC9d;SpBFYqll&WakZ2x>zWQSED^CTxv4umdul&xt0Zqf0=2_K!y0vq@Gy z9o2C*YC#JuUT*O!a|7xmwxJeu0JV@)SQ4*bc}zRe{lKe^!OZWp_hF}a?PsDkunct~Yf$ZWSovWqKY==lE0_--U?JvrLf>|O7?eg0*bw!R z+yQm32BMDaZPYU{-^w?mj`%og!t>@YsD(d3oy1d%LngT=lo=~fo*#YX$h09-7L!ps zS%vDj5u4*KtcXFAISs6arEw+J$CKC)vrKWnBO=j5{3({iBiIHXAZu~zPIdp{vUe)y zPu|J)j{7Tj0ahnIgIY-FH1{dbfg!~C%p#~AhGTlHh`L3!QSF*p+!lj~yP-Zgdt)<< zw|L7m&Oexf!xX6FG4nL)1TLT^`VDmp9$8C{AE0*n2-V>~)I!s}=YAgK#WchfQT0_(ehzNaL3Jtiu0hxDTHbD{)dy%J*kKpu`OyrJ^T$EX9#NNNvHuPTlsXZhQ6$1W|GlLSD^0AdUGf0-W|b$cowygKT#9Du=+GJ z-5-}(Py^ROJsXWs?V6cwt-iC_YbNKfBkNCrCQ7u5H&F|kf;xejs1uoI^~+HMuQ5MI zJ$&2EuTUSc`%n+#CDe&LL_IrcXSwE|#rf+KtO5mXFdo%$2lmFZSRN~A zu^Vv`7RO_#x8xxf!b}U@9hb#$;$EneoP>J%51?*Y_C@ZqPyqF8cu?ix$g|{gDwEN@ ztb@9TjZyc!h1!~3b#Z^F!a|Gy-o z0lq;!{U=aQ?`70LS1~)@viJpRprFNW`%I_>=SLlN5mf)CsD-w~R@ezO-eS~i`3d&W z`@e;ZCeFOXjtaXIdr&8mjGFLG)PPg549-NoHM>v)A3<&86srAs)XuM>ZtWw~c+N*| zzhLyKVKy@Am=E;{SOnFfJZ8gMs1>(CweN-6aWv}n9gOOij015B_QBs#4_Vu#{A$8U zsFO*%%-u-nGR|KE=A=La7D5eJ9Cad9EN+C_X{5!yQ4_|Z+Kon?%oJ4r53vz0#p-w! z!!gftcLR-38*8nf*IGbt3N(P%OhBzP88yLp)R9leg18+E;8|>ff1q|;eTDlodp0&A zK8f`(`^WC<8Hrj*ENb4_J~Enk3F;QCwu%i_z8!UM_n~gV5mdV$Q470b{*F4K7nlaq zed3-_MpXN}rU!$FOQG8P%37u-s$o;J4QilHsFl8E@#|)P)KL$#`jM!G`cSuKDr$kV zt$u~oe`fWmZoSXhOD2eh$5AUfje2T-Mos)DY9TLB13N3-c9~EM$cuV*!ciww9yLyV zRKM1!g|$aL)URO>M)~Fb53mNYs9P}{)o?tP#CK2~HexVtL7mhNRJ(nse#b06hno1R z`Kx)$>hGc2KgEp9?*y)LSDXb^ksmcc2{QtzKnp01Ik75Mz}A=+$DkH6(c&qnh0j3sUxZq~Y7EBDQ48B< z@lI6#eW-;TLiPVj;Ia}}z?I&(W}#rshwbpl5R@Hv1xu+v)igDKNG z_Y9X-hrRF_7Q(LU-IGnibi}?-$kZgW9`)MY!2I|(mcv{d+t#`NzBXq+$?t``LGlf#ZX7r1~ow>>SVfO2==wu ziBNNv;#n_wKa!oj#5 zvtZFw_wR<4Q76_0)qgmu-&oWF-?DhR)z3sNU;$>u4d~Oi*dA+e$r}8E*(iU8+DYgZ z_ehJP2Cjx$Xam%dwluq0{Q%U-3`H$$yv38PeirJ)7H{GHYsDX1!!_1m6IP{sCpN$b zs1;Y->fYlG<_c<%csADQ>=ZCGq zMbyA|P&d+_I<>X<%_j)VR^;|M$OmGWx(tvWjF> z$G80r_!z}J#EY>6Zbc1n5k2@Teu^PG__qMuhm$y3^l-RRKJ6$aZaI5<~(Z0*RUxT-R*vR4#d91 z^RWj$+0Fgek#yYS{%l@n{)R;;FTU3;Z;rW%Ct@R9hSL2Gol8qrc$+cgG#E8s!OC6IWs%{0Zw~-GlBk zl8l9jXJH%MgthP=%!@S+xeM!PPVkYbOvOfw!E4wE+a7ioGy~Of1s2AyusU8sJriMH z^Y6r18dX0AJ-84H;!bRVKcb$UBHy?tRS#;6P#*&!jsQcPg#|YwmxQ=P@7HYhQR{q8@cOwHZr+$CDMMevlhZ=Y}s^dc{K0-Zoy}xtY$6_Gy2vqyg<^&8Oeh0OX53GC+YMvz)ua?a3Y$THbw_C-2^Qief zYQPJqc2`jY-9??uW2=8|1|E0c|MaMZ<;8SZ#NyHxS4RK;{-+KZ9bGHTguPJ{4n|Eh z47HQ77>aM97VS3TM9JcDQj>6HPAKegmsLz#pm=!ysUekW&M4x3=pgsroqrL+kp+504 zeDA);MX?!iL)5~ipcecgY9R}-11?8x=ppLacw+T0EDk#D_Dhc%$CsUqj;H`eVlgub zHNhd&K*v$-PNOI+~t=66bw(SWtAq6z9q z+gscdbuYcB0fwU%HWstvB&(l?+WAT={|wb`H)_JK&F`@|@nuY}_doEg`(9^6?I1s9 zL=S4m#mrb2wcs{Z-WAop4{AY!Q4^0x^`C-j|30eSJj{uoDAxPGgN%QL_&V|T zsE(D-xf9nyoj@bh0y>y|Q3J=JCLDztX98-$(@`5r!8AA@b+U_5<9~|&|Ng(x3bvy@ z<9A#9qj?3@@g{1ZKT+RuPf$C`^@BTMG1LOepcYi!;szGCMs1`sYMiJaIDf6gYYm2= zp7Ie`5_ej|Yp9MlFc_DBwLCk?CQ77=L)&GI&_X0Ih(2wqWp8>Vw{HSN7FzTc$`^ad* zcGv)iVP4#XTG+SdNz{aAF$`~`Ci)lkJs)zxy(Psl3vm0XH zZ%?KS1#e&#d=K@5WG`ys%c!HjftvUM>S&*!Cin-n(BMn%t;vd7NCC`=5vXw*pf=hP zbql+r|9}4l zsGqs-_^x>$`w(}z;-2_s^i`zbCo(ND%T+!N12`J&P2B66`&N8`)rqfRSqJ2>d8(_v+eG=*!dGi;a`$03Ef^rmW#^QJdbt{5@bqC0ST1bA> z#6?i|x)S!n)~IJ>6>7qrsP}w7s{L8i!hS_9>^|nkCq6RTQI;F-5#=$9p&FLQAgpe2 z9gCZw25gDy-w8EQFVsoKqJErC#1NcpzK1%g6wHUd)nxQA?MDrC8a2=*)B^6J-j2U8 z1Ve7R<(W`%PKyhm?s0L{&MIIhY=P}@A-2F<*aj>8=08!NGoFkFdKtjs{5hs0PIJrMP)5{73Sc`dj~Vp+KaNa#3Z|k4o{5@x z73u?IgT)6iJ@GNr(|Zmz;WgAmzo9nr(Bh}Kj5y%7TfPF-ehumtZNx0h?;Iwhhv}RO z@IGpS|4=Iqz2iQu1yLVRrOlccO57YvU?13th?*zkAv6EG2V)QhkJZbrS{ z*DOwZpYxBPpvHao%O?t35YNG;co}D4(FgXmj9TEgxD0P#QJnhFtzV1fh!5gm`~&-A zpFiA(cpqv(KVxBh>?5NU<@(dTM|H3?aZhZBlTkZ9j2ZEFOu*;Z5@Y{zKa#hYSFsG` znIE}Nd2Q@K{0`Q|^VkJ*K6Y=FZ!noO6eObV`AE}ezJt1#Gf}VSeAK;MV)Y-R?)f@% z3+h?;3f1l~s{b+6Gjkf%{wKHG=iDF@M!`MQ0s@}6X25L3VWA(Tazlj(8Mm;Bjhz@1O>li8_%5 zsP>;(yv^coQ0-5nc6up|YY*q!Q|xXol+F0rk-LeZl)*g3Q|#6vZ{x@EB?# z=TH-0u=4BXJ*$6$TF7(MQ=k4H_w%3{>b35L4RA8{#6#EuJ^#9|_n?0{e>GT7fd}tl zUd;TTd*tD$l~+WaNNtN7nQc%D?21{iFX~psTRalAz$xZz)W%kzZp|tm84bJ>)p0-S z890hM(i5nAebMS~p#O6K`K9JOM@{e#s$VFjGAruVL{IMosvK`5)?G%oyO-XU9CmC6IA_PJJ>u zfhMSitu2nUxEpGLeNYP;WF}(`;&)N~_oMnBF;8GF;A({e-$;+4OIJksD(X3ZS*;6 zVgCjB+@~=#*nPN)qu&2&sHeFDs$oCWiNvD@9*b%>(aIO2Uc)u03AdwO&mXipuCW9c z$nPg#SruG2v69ak6lGak$@katxVDk+NQ0ilPsy*RtTU;f)gLz(sWI18i_g)gosF51 zvagAMCZ6mz^Z(h6@k<7*5_F}k z8F^j#NVUm-ZtZH?7?p{CA=UA>`rjWZz6P0mqiCa3)>YctEB`jB0ewo68j|lsU0(9- z$zQ~4#4S+Q0rKaWw}{0m)91`o$_6Ol+D&RmeLm6wYgZ)=pFufjG|%5epC|m}v&zZj zb$MN!5=`>)Dnpy%7Pp{X3i%H)J8APP?bLn{X&Pl`sMGVDlfHUfZW9;r|Ck^sMd6PW z=(oqEB zQq~>cCw_x`Gk*ND$5Zw-3iBN#=b_~1|JC!mhWG<|&7^EG z^_NJqNncT>Z~m5~6Sjgm)~_J-Jt)gfIzj(Wa3^K!sIN$V5Bcv%FRv)t@V@qSR#@Q_ z8s#HDkBY&h4djcxY>na6Z=~!Tbx}BhRG9L+l$Rjifc!VFv{$xu%BIF)zAx$V4Xt#w zCBGFDNO|e?0kN(JNE$`b)sa+}zWJ^He98yXXDP0vZW-l# zF6s(&Dx@@PQmoZcYw9nwKU&eGHTh_gz62hT>eKEXL;XwL72@l}UC58X%vdmGQ|K>vhs5%371&B-MFk=4A4-XgAB>(*0vBWt%8Vw*G_YlaAEL+6<-q zHR8iozm2atXA;4muM85)ATucorYr-lB(6$+H~EiABN;%~N95nbi57Py--fpH@g3B4 zin=&A>;LmKeTG_mkh;tCXMTRYxz{ilOygdp5Yj*zd`wvfJW85Q+1m`L zYZ>|Dq@t8J$BU?I3+W`WuAlG*j?V`KfZ52eAfLw?oTOt7%4_4VR(8k+Q@?wp-)tcT$p_Kq8{*ug zBg8fFM?6RQD)QG!x|ZX6?s)$BoreT-88|JLqCtBaJaHTNJN!yqoHUkb3duw2M*JIn z%38ZGiLX(vt0LtOUg_VPx;3`&^5kc@&G>)Z!Tfz`xPZ!b6lNz?C!M5GTGBhDPQ*Xs zP}{OgwhPGbqo00^e}#J~OHb0Z9lxi(p2hz8(-D-X@(zuM z`!B=x=NdF#A`>p8I;u}g)q)|d`Itp zX<9t7#yc>K_<{AhLcErIRSaf;UUbYs(sh_L-X{N?`Xl5sSltaQOMPyOuTZy7dHjpE z$0SKVGo4&yrjja9agjE<)?3H-DSu472S<|@lXQKEbupMerDY&B)6|B1SK zl-;7NKI$4y*#z7|Su@(`%1Hh)X({PVx5#b&ts6L%=#-wySln)9Ysg<=fR2<;#b!9# z27D_eplz6MB_)SQ-m`rNQcy>$*#R4*4%gf9c<$Kc#Rv9p1FYYSf2e$@Sta;t6rOidW&KU(~Yds4Es%k67ToAIPwq;}SR0=2r15HBKqZRO?gCUx}~ zA({G6;we^_LfnD;N7i>P@iE#pAZ;T5FG<&Y>Kl^6XXEvz|ss1ZV@Ul;<>|9e z-vvX+T(t(Tk*`Fhu8%2OMY_d+lPKRr(my(#Al9|s`kckQZjt}bpJ*3Po8KvaFC`!{ z%$Ji~UDCJI^rU7X4kX1`uX~goApa$)nw7nz4gJbrqoO z58|ifzs678^49*!?hMr?}P1&SM<0u0iA%V+Zy)2-Q7RA6Cx4WRBf%5;U1&rVqj zQcuzt#%W@U*o^OyTG8eg>MCJ<{mLz64FV{9^-4#O*~-q~XQUCN4=CUHO2g*l*HE5= zq-!mn!Y}+0r$c<2$ySh-G1pLQ*G1|mcaW-DVGNBL*@B+f0533_^3}9yiW9B8CibIj zCS{N5^9A|7J#iHDGWpx|44Mk-@tH#U9U=`h_o)uX`%(%Ym&%KGEW>s|71(dl)} zMO`tg`^fsL-3QdCp?o4`pOEikb#18|VH2v|2GV}&o(1slanlGIQu!$bujALm`50t0 zd5=x?{ydZ zvd6UvM?&((#3wnC2}5Fr4-!dHi6VJmLVW7Bsq+I;2TrS!p;5o6;a*RRR-N5Fddija z#6=Aqu5GYpPluu2cvW^D>g^vhAf|tmcI0W{O^EX*B_{h%HFb8%-LSOPJ(X(Ju2v;= z>guGTxxA_v@&6xp>XRd(0hQVe8PR`?C!t?|_ryI3v5DS8i-shy<)MjVykk5=6NY&C zV^qw+$z!78y%DJa->wht&@DMOAwDWT#_NfS?LRoiGb%YQYG4%fOQbZ40b{(eNe5C# zmG>Ol85PaRx+NZU8Iv$PDeBNf&zQIvZ#)}FE}y#ofUo71QvL;-(asMqaT@g@4$rA_CF@2Ef6^(J~qi=E5l=BUY>n7 zW=QCl5Sx19%Eo}y`Par|Xdamm&B{h4jM9#oUPoQdlMt=#M@2{J7|H#=^B(0H&W%VO S5EC1vL$JG(n)TiL2aZ1YTlk0 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 diff --git a/django/conf/locale/pl/LC_MESSAGES/django.po b/django/conf/locale/pl/LC_MESSAGES/django.po index 405084aa296e8..d964aae95816c 100644 --- a/django/conf/locale/pl/LC_MESSAGES/django.po +++ b/django/conf/locale/pl/LC_MESSAGES/django.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: Django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-12-11 10:11+0100\n" +"POT-Creation-Date: 2009-12-16 19:53+0100\n" "PO-Revision-Date: 2008-02-25 15:53+0100\n" "Last-Translator: Jarek Zgoda \n" "MIME-Version: 1.0\n" @@ -223,7 +223,7 @@ msgstr "chiński tradycyjny" msgid "Successfully deleted %(count)d %(items)s." msgstr "Usunięto %(count)d %(items)s." -#: contrib/admin/actions.py:67 contrib/admin/options.py:1034 +#: contrib/admin/actions.py:67 contrib/admin/options.py:1040 msgid "Are you sure?" msgstr "Jesteś pewien?" @@ -371,26 +371,37 @@ msgid "" msgstr "" "%(name)s \"%(obj)s\" dodane pomyślnie. Możesz edytować ponownie wpis poniżej." -#: contrib/admin/options.py:778 +#: contrib/admin/options.py:696 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Wykonanie akcji wymaga wybrania obiektów. Żaden obiekt nie został zmieniony." + +#: contrib/admin/options.py:710 +msgid "No action selected." +msgstr "Nie wybrano akcji." + +#: contrib/admin/options.py:784 #, python-format msgid "Add %s" msgstr "Dodaj %s" -#: contrib/admin/options.py:810 contrib/admin/options.py:1012 +#: contrib/admin/options.py:816 contrib/admin/options.py:1018 #, python-format msgid "%(name)s object with primary key %(key)r does not exist." msgstr "Obiekt %(name)s o kluczu głównym %(key)r nie istnieje." -#: contrib/admin/options.py:867 +#: contrib/admin/options.py:873 #, python-format msgid "Change %s" msgstr "Zmień %s" -#: contrib/admin/options.py:911 +#: contrib/admin/options.py:917 msgid "Database error" msgstr "Błąd bazy danych" -#: contrib/admin/options.py:947 +#: contrib/admin/options.py:953 #, python-format msgid "%(count)s %(name)s was changed successfully." msgid_plural "%(count)s %(name)s were changed successfully." @@ -398,12 +409,12 @@ msgstr[0] "%(count)s %(name)s został pomyślnie zmieniony." msgstr[1] "%(count)s %(name)s zostały pomyślnie zmienione." msgstr[2] "%(count)s %(name)s zostało pomyślnie zmienionych." -#: contrib/admin/options.py:1027 +#: contrib/admin/options.py:1033 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgstr "%(name)s \"%(obj)s\" usunięty pomyślnie." -#: contrib/admin/options.py:1064 +#: contrib/admin/options.py:1070 #, python-format msgid "Change history: %s" msgstr "Historia zmian: %s" @@ -1055,88 +1066,7 @@ msgstr "liczba %s" msgid "Fields on %s objects" msgstr "Pola obiektów %s" -#: contrib/admindocs/views.py:334 contrib/admindocs/views.py:345 -#: contrib/admindocs/views.py:347 contrib/admindocs/views.py:353 -#: contrib/admindocs/views.py:354 contrib/admindocs/views.py:356 -msgid "Integer" -msgstr "Liczba całkowita" - -#: contrib/admindocs/views.py:335 -msgid "Boolean (Either True or False)" -msgstr "Wartość logiczna (True, False - prawda lub fałsz)" - -#: contrib/admindocs/views.py:336 contrib/admindocs/views.py:355 -#, python-format -msgid "String (up to %(max_length)s)" -msgstr "Łańcuch (do %(max_length)s znaków)" - -#: contrib/admindocs/views.py:337 -msgid "Comma-separated integers" -msgstr "Liczby całkowite rozdzielone przecinkami" - -#: contrib/admindocs/views.py:338 -msgid "Date (without time)" -msgstr "Data (bez godziny)" - -#: contrib/admindocs/views.py:339 -msgid "Date (with time)" -msgstr "Data (z godziną)" - -#: contrib/admindocs/views.py:340 -msgid "Decimal number" -msgstr "Liczba dziesiętna" - -#: contrib/admindocs/views.py:341 -msgid "E-mail address" -msgstr "Adres e-mail" - -#: contrib/admindocs/views.py:342 contrib/admindocs/views.py:343 -#: contrib/admindocs/views.py:346 -msgid "File path" -msgstr "Ścieżka do pliku" - -#: contrib/admindocs/views.py:344 -msgid "Floating point number" -msgstr "Liczba zmiennoprzecinkowa" - -#: contrib/admindocs/views.py:348 contrib/comments/models.py:60 -msgid "IP address" -msgstr "Adres IP" - -#: contrib/admindocs/views.py:350 -msgid "Boolean (Either True, False or None)" -msgstr "Wartość logiczna (True, False, None - prawda, fałsz lub nic)" - -#: contrib/admindocs/views.py:351 -msgid "Relation to parent model" -msgstr "Relacja do modelu rodzica" - -#: contrib/admindocs/views.py:352 -msgid "Phone number" -msgstr "Numer telefonu" - -#: contrib/admindocs/views.py:357 -msgid "Text" -msgstr "Tekst" - -#: contrib/admindocs/views.py:358 -msgid "Time" -msgstr "Czas" - -#: contrib/admindocs/views.py:359 contrib/comments/forms.py:95 -#: contrib/flatpages/admin.py:8 contrib/flatpages/models.py:7 -msgid "URL" -msgstr "URL" - -#: contrib/admindocs/views.py:360 -msgid "U.S. state (two uppercase letters)" -msgstr "Stan USA (dwie duże litery)" - -#: contrib/admindocs/views.py:361 -msgid "XML text" -msgstr "Tekst XML" - -#: contrib/admindocs/views.py:387 +#: contrib/admindocs/views.py:356 #, python-format msgid "%s does not appear to be a urlpattern object" msgstr "%s nie jest obiektem urlpattern" @@ -1239,7 +1169,7 @@ msgid "Change password: %s" msgstr "Zmień hasło: %s" #: contrib/auth/forms.py:15 contrib/auth/forms.py:48 -#: contrib/auth/models.py:129 +#: contrib/auth/models.py:141 msgid "" "Required. 30 characters or fewer. Alphanumeric characters only (letters, " "digits and underscores)." @@ -1309,51 +1239,51 @@ msgstr "Stare hasło" msgid "Your old password was entered incorrectly. Please enter it again." msgstr "Podane stare hasło jest niepoprawne. Proszę podać je jeszcze raz." -#: contrib/auth/models.py:63 contrib/auth/models.py:86 +#: contrib/auth/models.py:70 contrib/auth/models.py:98 msgid "name" msgstr "nazwa" -#: contrib/auth/models.py:65 +#: contrib/auth/models.py:72 msgid "codename" msgstr "nazwa kodowa" -#: contrib/auth/models.py:68 +#: contrib/auth/models.py:76 msgid "permission" msgstr "uprawnienie" -#: contrib/auth/models.py:69 contrib/auth/models.py:87 +#: contrib/auth/models.py:77 contrib/auth/models.py:99 msgid "permissions" msgstr "uprawnienia" -#: contrib/auth/models.py:90 +#: contrib/auth/models.py:102 msgid "group" msgstr "grupa" -#: contrib/auth/models.py:91 contrib/auth/models.py:139 +#: contrib/auth/models.py:103 contrib/auth/models.py:151 msgid "groups" msgstr "grupy" -#: contrib/auth/models.py:129 +#: contrib/auth/models.py:141 msgid "username" msgstr "użytkownik" -#: contrib/auth/models.py:130 +#: contrib/auth/models.py:142 msgid "first name" msgstr "imię" -#: contrib/auth/models.py:131 +#: contrib/auth/models.py:143 msgid "last name" msgstr "nazwisko" -#: contrib/auth/models.py:132 +#: contrib/auth/models.py:144 msgid "e-mail address" msgstr "adres e-mail" -#: contrib/auth/models.py:133 +#: contrib/auth/models.py:145 msgid "password" msgstr "hasło" -#: contrib/auth/models.py:133 +#: contrib/auth/models.py:145 msgid "" "Use '[algo]$[salt]$[hexdigest]' or use the change " "password form." @@ -1361,19 +1291,19 @@ msgstr "" "Użyj '[algo]$[salt]$[hexdigest]' lub formularza zmiany " "hasła." -#: contrib/auth/models.py:134 +#: contrib/auth/models.py:146 msgid "staff status" msgstr "w zespole" -#: contrib/auth/models.py:134 +#: contrib/auth/models.py:146 msgid "Designates whether the user can log into this admin site." msgstr "Oznacza czy użytkownik może zalogować się do panelu admina." -#: contrib/auth/models.py:135 +#: contrib/auth/models.py:147 msgid "active" msgstr "aktywny" -#: contrib/auth/models.py:135 +#: contrib/auth/models.py:147 msgid "" "Designates whether this user should be treated as active. Unselect this " "instead of deleting accounts." @@ -1381,11 +1311,11 @@ msgstr "" "Oznacza czy użytkownika należy uważać za aktywnego. Odznacz to, zamiast " "usuwać konta." -#: contrib/auth/models.py:136 +#: contrib/auth/models.py:148 msgid "superuser status" msgstr "status administratora" -#: contrib/auth/models.py:136 +#: contrib/auth/models.py:148 msgid "" "Designates that this user has all permissions without explicitly assigning " "them." @@ -1393,15 +1323,15 @@ msgstr "" "Oznacza, że ten użytkownik ma wszystkie uprawnienia bez jawnego " "przypisywania ich." -#: contrib/auth/models.py:137 +#: contrib/auth/models.py:149 msgid "last login" msgstr "ostatnio zalogowany" -#: contrib/auth/models.py:138 +#: contrib/auth/models.py:150 msgid "date joined" msgstr "data przyłączenia" -#: contrib/auth/models.py:140 +#: contrib/auth/models.py:152 msgid "" "In addition to the permissions manually assigned, this user will also get " "all permissions granted to each group he/she is in." @@ -1409,20 +1339,20 @@ msgstr "" "Oprócz uprawnień przypisanych bezpośrednio użytkownikowi otrzyma on " "uprawnienia grup, do których należy." -#: contrib/auth/models.py:141 +#: contrib/auth/models.py:153 msgid "user permissions" msgstr "uprawnienia użytkownika" -#: contrib/auth/models.py:145 contrib/comments/models.py:50 +#: contrib/auth/models.py:157 contrib/comments/models.py:50 #: contrib/comments/models.py:168 msgid "user" msgstr "użytkownik" -#: contrib/auth/models.py:146 +#: contrib/auth/models.py:158 msgid "users" msgstr "użytkownicy" -#: contrib/auth/models.py:334 +#: contrib/auth/models.py:346 msgid "message" msgstr "wiadomość" @@ -1492,6 +1422,11 @@ msgstr "Nazwa" msgid "Email address" msgstr "Adres e-mail" +#: contrib/comments/forms.py:95 contrib/flatpages/admin.py:8 +#: contrib/flatpages/models.py:7 db/models/fields/__init__.py:917 +msgid "URL" +msgstr "URL" + #: contrib/comments/forms.py:96 msgid "Comment" msgstr "Komentarz" @@ -1510,7 +1445,7 @@ msgid "" msgstr "" "Jeżeli wpiszesz cokolwiek w to pole, Twój komentarz zostanie uznany za spam" -#: contrib/comments/models.py:22 contrib/contenttypes/models.py:74 +#: contrib/comments/models.py:22 contrib/contenttypes/models.py:81 msgid "content type" msgstr "typ zawartości" @@ -1539,6 +1474,10 @@ msgstr "komentarz" msgid "date/time submitted" msgstr "data/czas dodania" +#: contrib/comments/models.py:60 db/models/fields/__init__.py:737 +msgid "IP address" +msgstr "Adres IP" + #: contrib/comments/models.py:61 msgid "is public" msgstr "publicznie dostępny" @@ -1706,11 +1645,11 @@ msgstr "Zapisz swój komentarz" msgid "or make changes" msgstr "lub wprowadź jakieś zmiany" -#: contrib/contenttypes/models.py:70 +#: contrib/contenttypes/models.py:77 msgid "python model class name" msgstr "nazwa pythonowa modelu klasy" -#: contrib/contenttypes/models.py:75 +#: contrib/contenttypes/models.py:82 msgid "content types" msgstr "typy zawartości" @@ -1782,6 +1721,39 @@ msgstr "" "Przepraszamy, ale Twój formularz wygasł. Proszę kontynuować wypełnianie " "formularza od tej strony." +#: contrib/gis/db/models/fields/__init__.py:42 +msgid "The base GIS field -- maps to the OpenGIS Specification Geometry type." +msgstr "" +"Podstawowe pole GIS - odpowiada typowi Geometry w specyfikacji OpenGIS." + +#: contrib/gis/db/models/fields/__init__.py:264 +msgid "Point" +msgstr "Punkt" + +#: contrib/gis/db/models/fields/__init__.py:268 +msgid "Line string" +msgstr "" + +#: contrib/gis/db/models/fields/__init__.py:272 +msgid "Polygon" +msgstr "Wielobok" + +#: contrib/gis/db/models/fields/__init__.py:276 +msgid "Multi-point" +msgstr "" + +#: contrib/gis/db/models/fields/__init__.py:280 +msgid "Multi-line string" +msgstr "" + +#: contrib/gis/db/models/fields/__init__.py:284 +msgid "Multi polygon" +msgstr "" + +#: contrib/gis/db/models/fields/__init__.py:288 +msgid "Geometry collection" +msgstr "" + #: contrib/gis/forms/fields.py:17 msgid "No geometry value provided." msgstr "Brak wartości geometrii." @@ -1994,11 +1966,11 @@ msgstr "Błędny numer CNPJ." msgid "This field requires at least 14 digits" msgstr "To pole musi zawierać co najmniej 14 cyfr" -#: contrib/localflavor/ca/forms.py:17 +#: contrib/localflavor/ca/forms.py:24 msgid "Enter a postal code in the format XXX XXX." msgstr "Wpisz kod pocztowy w formacie XXX XXX." -#: contrib/localflavor/ca/forms.py:88 +#: contrib/localflavor/ca/forms.py:95 msgid "Enter a valid Canadian Social Insurance number in XXX-XXX-XXX format." msgstr "" "Wpisz poprawny numer kanadyjskiego ubezpieczenia w formacie XXX-XXX-XXXX." @@ -3767,6 +3739,14 @@ msgstr "Wpisz kod pocztowy w formacie XXXXX. lub XXXXX-XXXX." msgid "Enter a valid U.S. Social Security number in XXX-XX-XXXX format." msgstr "Wpisz poprawny numer U.S. Social Security w formacie XXX-XX-XXXX." +#: contrib/localflavor/us/models.py:8 +msgid "U.S. state (two uppercase letters)" +msgstr "Stan USA (dwie duże litery)" + +#: contrib/localflavor/us/models.py:17 +msgid "Phone number" +msgstr "Numer telefonu" + #: contrib/localflavor/za/forms.py:20 msgid "Enter a valid South African ID number" msgstr "Wpisz poprawny południowoafrykański numer ID" @@ -3875,62 +3855,139 @@ msgstr "wyświetlana nazwa" msgid "sites" msgstr "strony" -#: db/models/fields/__init__.py:356 db/models/fields/__init__.py:710 +#: db/models/fields/__init__.py:64 +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Pole typu: %(field_type)s" + +#: db/models/fields/__init__.py:350 db/models/fields/__init__.py:712 +#: db/models/fields/__init__.py:792 db/models/fields/__init__.py:802 +#: db/models/fields/__init__.py:829 +msgid "Integer" +msgstr "Liczba całkowita" + +#: db/models/fields/__init__.py:364 db/models/fields/__init__.py:728 msgid "This value must be an integer." msgstr "Ta wartość musi być liczbą całkowitą." -#: db/models/fields/__init__.py:388 +#: db/models/fields/__init__.py:382 +msgid "Boolean (Either True or False)" +msgstr "Wartość logiczna (True, False - prawda lub fałsz)" + +#: db/models/fields/__init__.py:397 msgid "This value must be either True or False." msgstr "" "Ta wartość musi być wartością logiczną (True, False - prawda lub fałsz)." -#: db/models/fields/__init__.py:427 +#: db/models/fields/__init__.py:425 db/models/fields/__init__.py:812 +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Łańcuch (do %(max_length)s znaków)" + +#: db/models/fields/__init__.py:437 msgid "This field cannot be null." msgstr "To pole nie może być puste." -#: db/models/fields/__init__.py:443 +#: db/models/fields/__init__.py:447 +msgid "Comma-separated integers" +msgstr "Liczby całkowite rozdzielone przecinkami" + +#: db/models/fields/__init__.py:454 msgid "Enter only digits separated by commas." msgstr "Wpisz tylko cyfry oddzielone przecinkami." -#: db/models/fields/__init__.py:474 +#: db/models/fields/__init__.py:463 +msgid "Date (without time)" +msgstr "Data (bez godziny)" + +#: db/models/fields/__init__.py:486 msgid "Enter a valid date in YYYY-MM-DD format." msgstr "Proszę wpisać poprawną datę w formacie RRRR-MM-DD." -#: db/models/fields/__init__.py:483 +#: db/models/fields/__init__.py:495 #, python-format msgid "Invalid date: %s" msgstr "Niepoprawna data: %s" -#: db/models/fields/__init__.py:547 db/models/fields/__init__.py:565 +#: db/models/fields/__init__.py:539 +msgid "Date (with time)" +msgstr "Data (z godziną)" + +#: db/models/fields/__init__.py:560 db/models/fields/__init__.py:578 msgid "Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format." msgstr "" "Wprowadź poprawną datę i godzinę w formacie YYYY-MM-DD HH:MM[:ss[.uuuuuu]]." -#: db/models/fields/__init__.py:601 +#: db/models/fields/__init__.py:600 +msgid "Decimal number" +msgstr "Liczba dziesiętna" + +#: db/models/fields/__init__.py:615 msgid "This value must be a decimal number." msgstr "Ta wartość musi być liczbą dziesiętną." +#: db/models/fields/__init__.py:654 +msgid "E-mail address" +msgstr "Adres e-mail" + +#: db/models/fields/__init__.py:665 db/models/fields/files.py:219 +#: db/models/fields/files.py:330 +msgid "File path" +msgstr "Ścieżka do pliku" + #: db/models/fields/__init__.py:686 +msgid "Floating point number" +msgstr "Liczba zmiennoprzecinkowa" + +#: db/models/fields/__init__.py:703 msgid "This value must be a float." msgstr "Ta wartość musi być liczbą rzeczywistą." -#: db/models/fields/__init__.py:746 +#: db/models/fields/__init__.py:752 +msgid "Boolean (Either True, False or None)" +msgstr "Wartość logiczna (True, False, None - prawda, fałsz lub nic)" + +#: db/models/fields/__init__.py:766 msgid "This value must be either None, True or False." msgstr "" "Ta wartość musi być jedną z None (nic), True (prawda) lub False (fałsz)." -#: db/models/fields/__init__.py:849 db/models/fields/__init__.py:863 +#: db/models/fields/__init__.py:834 +msgid "Text" +msgstr "Tekst" + +#: db/models/fields/__init__.py:844 +msgid "Time" +msgstr "Czas" + +#: db/models/fields/__init__.py:875 db/models/fields/__init__.py:889 msgid "Enter a valid time in HH:MM[:ss[.uuuuuu]] format." msgstr "Proszę wpisać poprawną godzinę w formacie HH:MM[:ss[.uuuuuu]]." -#: db/models/fields/related.py:869 +#: db/models/fields/__init__.py:929 +msgid "XML text" +msgstr "Tekst XML" + +#: db/models/fields/related.py:695 +msgid "Foreign Key (type determined by related field)" +msgstr "Klucz obcy (typ określony przez pole powiązane)" + +#: db/models/fields/related.py:798 +msgid "One-to-one relationship" +msgstr "Powiązanie jeden do jednego" + +#: db/models/fields/related.py:852 +msgid "Many-to-many relationship" +msgstr "Powiązanie wiele do wiele" + +#: db/models/fields/related.py:872 msgid "" "Hold down \"Control\", or \"Command\" on a Mac, to select more than one." msgstr "" "Przytrzymaj wciśnięty klawisz \"Ctrl\" lub \"Command\" na Mac'u aby " "zaznaczyć więcej niż jeden wybór." -#: db/models/fields/related.py:930 +#: db/models/fields/related.py:933 #, python-format msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." msgid_plural "" @@ -4054,7 +4111,7 @@ msgid "Select a valid choice. %(value)s is not one of the available choices." msgstr "" "Wybierz poprawną wartość. %(value)s nie jest jednym z dostępnych wyborów." -#: forms/fields.py:703 forms/fields.py:764 forms/models.py:999 +#: forms/fields.py:703 forms/fields.py:764 forms/models.py:1004 msgid "Enter a list of values." msgstr "Podaj listę wartości." @@ -4106,29 +4163,29 @@ msgstr "" msgid "Please correct the duplicate values below." msgstr "Popraw poniższe zduplikowane wartości." -#: forms/models.py:863 +#: forms/models.py:865 msgid "The inline foreign key did not match the parent instance primary key." msgstr "Osadzony klucz obcy nie pasuje do klucza głównego obiektu rodzica." -#: forms/models.py:926 +#: forms/models.py:931 msgid "Select a valid choice. That choice is not one of the available choices." msgstr "Wybierz poprawną wartość. Podana nie jest jednym z dostępnych wyborów." -#: forms/models.py:1000 +#: forms/models.py:1005 #, python-format msgid "Select a valid choice. %s is not one of the available choices." msgstr "Wybierz poprawną wartość. %s nie jest jednym z dostępnych wyborów." -#: forms/models.py:1002 +#: forms/models.py:1007 #, python-format msgid "\"%s\" is not a valid value for a primary key." msgstr "\"%s\" nie jest poprawną wartością klucza głównego." -#: template/defaultfilters.py:767 +#: template/defaultfilters.py:768 msgid "yes,no,maybe" msgstr "tak,nie,może" -#: template/defaultfilters.py:798 +#: template/defaultfilters.py:799 #, python-format msgid "%(size)d byte" msgid_plural "%(size)d bytes" @@ -4136,17 +4193,17 @@ msgstr[0] "%(size)d bajt" msgstr[1] "%(size)d bajty" msgstr[2] "%(size)d bajtów" -#: template/defaultfilters.py:800 +#: template/defaultfilters.py:801 #, python-format msgid "%.1f KB" msgstr "%.1f KB" -#: template/defaultfilters.py:802 +#: template/defaultfilters.py:803 #, python-format msgid "%.1f MB" msgstr "%.1f MB" -#: template/defaultfilters.py:803 +#: template/defaultfilters.py:804 #, python-format msgid "%.1f GB" msgstr "%.1f GB" @@ -4446,6 +4503,9 @@ msgstr "%(verbose_name)s zostało pomyślnie zmienione." msgid "The %(verbose_name)s was deleted." msgstr "%(verbose_name)s zostało usunięte." +#~ msgid "Relation to parent model" +#~ msgstr "Relacja do modelu rodzica" + #~ msgid "Comment moderation queue" #~ msgstr "Kolejka moderacji komentarzy" diff --git a/django/contrib/admindocs/tests/__init__.py b/django/contrib/admindocs/tests/__init__.py index a091ebe122fef..b4526c6a7ec4c 100644 --- a/django/contrib/admindocs/tests/__init__.py +++ b/django/contrib/admindocs/tests/__init__.py @@ -1,36 +1,30 @@ import unittest -from django.contrib.admindocs import views import fields - +from django.contrib.admindocs import views from django.db.models import fields as builtin_fields + class TestFieldType(unittest.TestCase): def setUp(self): pass - + def test_field_name(self): self.assertRaises(AttributeError, views.get_readable_field_data_type, "NotAField" ) - + def test_builtin_fields(self): self.assertEqual( views.get_readable_field_data_type(builtin_fields.BooleanField()), u'Boolean (Either True or False)' ) - + def test_custom_fields(self): self.assertEqual( views.get_readable_field_data_type(fields.CustomField()), u'A custom field type' ) self.assertEqual( - views.get_readable_field_data_type(fields.DocstringLackingField()), - u'Field of type: DocstringLackingField' - ) - - def test_multiline_custom_field_truncation(self): - self.assertEqual( - views.get_readable_field_data_type(fields.ManyLineDocstringField()), - u'Many-line custom field' + views.get_readable_field_data_type(fields.DescriptionLackingField()), + u'Field of type: DescriptionLackingField' ) diff --git a/django/contrib/admindocs/tests/fields.py b/django/contrib/admindocs/tests/fields.py index 5cab3627c630a..e59498afb5a86 100644 --- a/django/contrib/admindocs/tests/fields.py +++ b/django/contrib/admindocs/tests/fields.py @@ -1,13 +1,7 @@ from django.db import models class CustomField(models.Field): - """A custom field type""" - -class ManyLineDocstringField(models.Field): - """Many-line custom field - - This docstring has many lines. Lorum ipsem etc. etc. Four score - and seven years ago, and so on and so forth.""" + description = "A custom field type" -class DocstringLackingField(models.Field): +class DescriptionLackingField(models.Field): pass diff --git a/django/contrib/admindocs/views.py b/django/contrib/admindocs/views.py index d04030e9f0387..bcf835328779b 100644 --- a/django/contrib/admindocs/views.py +++ b/django/contrib/admindocs/views.py @@ -327,19 +327,11 @@ def get_return_data_type(func_name): return '' def get_readable_field_data_type(field): - """Returns the first line of a doc string for a given field type, if it - exists. Fields' docstrings can contain format strings, which will be - interpolated against the values of Field.__dict__ before being output. - If no docstring is given, a sensible value will be auto-generated from - the field's class name.""" - - if field.__doc__: - doc = field.__doc__.split('\n')[0] - return _(doc) % field.__dict__ - else: - return _(u'Field of type: %(field_type)s') % { - 'field_type': field.__class__.__name__ - } + """Returns the description for a given field type, if it exists, + Fields' descriptions can contain format strings, which will be interpolated + against the values of field.__dict__ before being output.""" + + return field.description % field.__dict__ def extract_views_from_urlpatterns(urlpatterns, base=''): """ diff --git a/django/contrib/contenttypes/generic.py b/django/contrib/contenttypes/generic.py index 93e85b79658cf..2f1b8efd077a3 100644 --- a/django/contrib/contenttypes/generic.py +++ b/django/contrib/contenttypes/generic.py @@ -292,15 +292,27 @@ class BaseGenericInlineFormSet(BaseModelFormSet): ct_field_name = "content_type" ct_fk_field_name = "object_id" - def __init__(self, data=None, files=None, instance=None, save_as_new=None, prefix=None): + def __init__(self, data=None, files=None, instance=None, save_as_new=None, + prefix=None, queryset=None): + # Avoid a circular import. + from django.contrib.contenttypes.models import ContentType opts = self.model._meta self.instance = instance self.rel_name = '-'.join(( opts.app_label, opts.object_name.lower(), self.ct_field.name, self.ct_fk_field.name, )) + if self.instance is None or self.instance.pk is None: + qs = self.model._default_manager.none() + else: + if queryset is None: + queryset = self.model._default_manager + qs = queryset.filter(**{ + self.ct_field.name: ContentType.objects.get_for_model(self.instance), + self.ct_fk_field.name: self.instance.pk, + }) super(BaseGenericInlineFormSet, self).__init__( - queryset=self.get_queryset(), data=data, files=files, + queryset=qs, data=data, files=files, prefix=prefix ) @@ -312,19 +324,6 @@ def get_default_prefix(cls): )) get_default_prefix = classmethod(get_default_prefix) - def get_queryset(self): - # Avoid a circular import. - from django.contrib.contenttypes.models import ContentType - if self.instance is None or self.instance.pk is None: - return self.model._default_manager.none() - qs = self.model._default_manager.filter(**{ - self.ct_field.name: ContentType.objects.get_for_model(self.instance), - self.ct_fk_field.name: self.instance.pk, - }) - if not qs.ordered: - qs = qs.order_by(self.model._meta.pk.name) - return qs - def save_new(self, form, commit=True): # Avoid a circular import. from django.contrib.contenttypes.models import ContentType diff --git a/django/contrib/gis/db/models/fields.py b/django/contrib/gis/db/models/fields.py index 0a4c46d4ee2d4..65eb1f171ca8b 100644 --- a/django/contrib/gis/db/models/fields.py +++ b/django/contrib/gis/db/models/fields.py @@ -1,4 +1,5 @@ from django.db.models.fields import Field +from django.utils.translation import ugettext_lazy as _ from django.contrib.gis import forms from django.contrib.gis.db.models.proxy import GeometryProxy from django.contrib.gis.geometry.backend import Geometry, GeometryException @@ -49,6 +50,8 @@ class GeometryField(Field): # Geodetic units. geodetic_units = ('Decimal Degree', 'degree') + description = _("The base GIS field -- maps to the OpenGIS Specification Geometry type.") + def __init__(self, verbose_name=None, srid=4326, spatial_index=True, dim=2, geography=False, **kwargs): """ @@ -287,22 +290,28 @@ def get_placeholder(self, value, connection): # The OpenGIS Geometry Type Fields class PointField(GeometryField): geom_type = 'POINT' + description = _("Point") class LineStringField(GeometryField): geom_type = 'LINESTRING' + description = _("Line string") class PolygonField(GeometryField): geom_type = 'POLYGON' + description = _("Polygon") class MultiPointField(GeometryField): geom_type = 'MULTIPOINT' + description = _("Multi-point") class MultiLineStringField(GeometryField): geom_type = 'MULTILINESTRING' + description = _("Multi-line string") class MultiPolygonField(GeometryField): geom_type = 'MULTIPOLYGON' + description = _("Multi polygon") class GeometryCollectionField(GeometryField): geom_type = 'GEOMETRYCOLLECTION' - + description = _("Geometry collection") diff --git a/django/contrib/localflavor/us/models.py b/django/contrib/localflavor/us/models.py index 01157d038b225..6ce6d3bec7049 100644 --- a/django/contrib/localflavor/us/models.py +++ b/django/contrib/localflavor/us/models.py @@ -1,16 +1,21 @@ from django.conf import settings +from django.utils.translation import ugettext_lazy as _ from django.db.models.fields import Field, CharField from django.contrib.localflavor.us.us_states import STATE_CHOICES - + class USStateField(CharField): - """U.S. state (two uppercase letters)""" + + description = _("U.S. state (two uppercase letters)") + def __init__(self, *args, **kwargs): kwargs['choices'] = STATE_CHOICES kwargs['max_length'] = 2 super(USStateField, self).__init__(*args, **kwargs) - + class PhoneNumberField(Field): - """Phone number""" + + description = _("Phone number") + def get_internal_type(self): return "PhoneNumberField" diff --git a/django/core/management/commands/dumpdata.py b/django/core/management/commands/dumpdata.py index 495dce0993394..dd20d44fceb3a 100644 --- a/django/core/management/commands/dumpdata.py +++ b/django/core/management/commands/dumpdata.py @@ -143,10 +143,15 @@ def sort_dependencies(app_list): changed = False while model_dependencies: model, deps = model_dependencies.pop() - if all((d not in models or d in model_list) for d in deps): - # If all of the models in the dependency list are either already - # on the final model list, or not on the original serialization list, - # then we've found another model with all it's dependencies satisfied. + + # If all of the models in the dependency list are either already + # on the final model list, or not on the original serialization list, + # then we've found another model with all it's dependencies satisfied. + found = True + for candidate in ((d not in models or d in model_list) for d in deps): + if not candidate: + found = False + if found: model_list.append(model) changed = True else: @@ -158,4 +163,4 @@ def sort_dependencies(app_list): ) model_dependencies = skipped - return model_list + return model_list \ No newline at end of file diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 4b4d982b6b8bf..d8b0c648c8c88 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -60,6 +60,13 @@ class Field(object): creation_counter = 0 auto_creation_counter = -1 + # Generic field type description, usually overriden by subclasses + def _description(self): + return _(u'Field of type: %(field_type)s') % { + 'field_type': self.__class__.__name__ + } + description = property(_description) + def __init__(self, verbose_name=None, name=None, primary_key=False, max_length=None, unique=False, blank=False, null=False, db_index=False, rel=None, default=NOT_PROVIDED, editable=True, @@ -369,10 +376,9 @@ def value_from_object(self, obj): return getattr(obj, self.attname) class AutoField(Field): - """Integer""" + description = ugettext_lazy("Integer") empty_strings_allowed = False - def __init__(self, *args, **kwargs): assert kwargs.get('primary_key', False) is True, "%ss must have primary_key=True." % self.__class__.__name__ kwargs['blank'] = True @@ -402,10 +408,8 @@ def formfield(self, **kwargs): return None class BooleanField(Field): - """Boolean (Either True or False)""" - empty_strings_allowed = False - + description = ugettext_lazy("Boolean (Either True or False)") def __init__(self, *args, **kwargs): kwargs['blank'] = True if 'default' not in kwargs and not kwargs.get('null'): @@ -448,7 +452,7 @@ def formfield(self, **kwargs): return super(BooleanField, self).formfield(**defaults) class CharField(Field): - """String (up to %(max_length)s)""" + description = ugettext_lazy("String (up to %(max_length)s)") def get_internal_type(self): return "CharField" @@ -471,7 +475,7 @@ def formfield(self, **kwargs): # TODO: Maybe move this into contrib, because it's specialized. class CommaSeparatedIntegerField(CharField): - """Comma-separated integers""" + description = ugettext_lazy("Comma-separated integers") def formfield(self, **kwargs): defaults = { @@ -488,10 +492,9 @@ def formfield(self, **kwargs): ansi_date_re = re.compile(r'^\d{4}-\d{1,2}-\d{1,2}$') class DateField(Field): - """Date (without time)""" + description = ugettext_lazy("Date (without time)") empty_strings_allowed = False - def __init__(self, verbose_name=None, name=None, auto_now=False, auto_now_add=False, **kwargs): self.auto_now, self.auto_now_add = auto_now, auto_now_add #HACKs : auto_now_add/auto_now should be done as a default or a pre_save. @@ -571,7 +574,7 @@ def formfield(self, **kwargs): return super(DateField, self).formfield(**defaults) class DateTimeField(DateField): - """Date (with time)""" + description = ugettext_lazy("Date (with time)") def get_internal_type(self): return "DateTimeField" @@ -637,10 +640,8 @@ def formfield(self, **kwargs): return super(DateTimeField, self).formfield(**defaults) class DecimalField(Field): - """Decimal number""" - empty_strings_allowed = False - + description = ugettext_lazy("Decimal number") def __init__(self, verbose_name=None, name=None, max_digits=None, decimal_places=None, **kwargs): self.max_digits, self.decimal_places = max_digits, decimal_places Field.__init__(self, verbose_name, name, **kwargs) @@ -694,8 +695,7 @@ def formfield(self, **kwargs): return super(DecimalField, self).formfield(**defaults) class EmailField(CharField): - """E-mail address""" - + description = ugettext_lazy("E-mail address") def __init__(self, *args, **kwargs): kwargs['max_length'] = kwargs.get('max_length', 75) CharField.__init__(self, *args, **kwargs) @@ -706,7 +706,7 @@ def formfield(self, **kwargs): return super(EmailField, self).formfield(**defaults) class FilePathField(Field): - """File path""" + description = ugettext_lazy("File path") def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs): self.path, self.match, self.recursive = path, match, recursive @@ -727,9 +727,8 @@ def get_internal_type(self): return "FilePathField" class FloatField(Field): - """Floating point number""" - empty_strings_allowed = False + description = ugettext_lazy("Floating point number") def get_prep_value(self, value): if value is None: @@ -754,9 +753,8 @@ def formfield(self, **kwargs): return super(FloatField, self).formfield(**defaults) class IntegerField(Field): - """Integer""" - empty_strings_allowed = False + description = ugettext_lazy("Integer") def get_prep_value(self, value): if value is None: @@ -781,10 +779,8 @@ def formfield(self, **kwargs): return super(IntegerField, self).formfield(**defaults) class IPAddressField(Field): - """IP address""" - empty_strings_allowed = False - + description = ugettext_lazy("IP address") def __init__(self, *args, **kwargs): kwargs['max_length'] = 15 Field.__init__(self, *args, **kwargs) @@ -798,10 +794,8 @@ def formfield(self, **kwargs): return super(IPAddressField, self).formfield(**defaults) class NullBooleanField(Field): - """Boolean (Either True, False or None)""" - empty_strings_allowed = False - + description = ugettext_lazy("Boolean (Either True, False or None)") def __init__(self, *args, **kwargs): kwargs['null'] = True Field.__init__(self, *args, **kwargs) @@ -841,7 +835,7 @@ def formfield(self, **kwargs): return super(NullBooleanField, self).formfield(**defaults) class PositiveIntegerField(IntegerField): - """Integer""" + description = ugettext_lazy("Integer") def get_internal_type(self): return "PositiveIntegerField" @@ -852,8 +846,7 @@ def formfield(self, **kwargs): return super(PositiveIntegerField, self).formfield(**defaults) class PositiveSmallIntegerField(IntegerField): - """Integer""" - + description = ugettext_lazy("Integer") def get_internal_type(self): return "PositiveSmallIntegerField" @@ -863,8 +856,7 @@ def formfield(self, **kwargs): return super(PositiveSmallIntegerField, self).formfield(**defaults) class SlugField(CharField): - """String (up to %(max_length)s)""" - + description = ugettext_lazy("String (up to %(max_length)s)") def __init__(self, *args, **kwargs): kwargs['max_length'] = kwargs.get('max_length', 50) # Set db_index=True unless it's been set manually. @@ -881,13 +873,13 @@ def formfield(self, **kwargs): return super(SlugField, self).formfield(**defaults) class SmallIntegerField(IntegerField): - """Integer""" + description = ugettext_lazy("Integer") def get_internal_type(self): return "SmallIntegerField" class TextField(Field): - """Text""" + description = ugettext_lazy("Text") def get_internal_type(self): return "TextField" @@ -898,10 +890,9 @@ def formfield(self, **kwargs): return super(TextField, self).formfield(**defaults) class TimeField(Field): - """Time""" + description = ugettext_lazy("Time") empty_strings_allowed = False - def __init__(self, verbose_name=None, name=None, auto_now=False, auto_now_add=False, **kwargs): self.auto_now, self.auto_now_add = auto_now, auto_now_add if auto_now or auto_now_add: @@ -978,7 +969,7 @@ def formfield(self, **kwargs): return super(TimeField, self).formfield(**defaults) class URLField(CharField): - """URL""" + description = ugettext_lazy("URL") def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs): kwargs['max_length'] = kwargs.get('max_length', 200) @@ -991,7 +982,7 @@ def formfield(self, **kwargs): return super(URLField, self).formfield(**defaults) class XMLField(TextField): - """XML text""" + description = ugettext_lazy("XML text") def __init__(self, verbose_name=None, name=None, schema_path=None, **kwargs): self.schema_path = schema_path diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py index 3debb25cb66d4..d3ba97541272a 100644 --- a/django/db/models/fields/files.py +++ b/django/db/models/fields/files.py @@ -209,8 +209,6 @@ def __set__(self, instance, value): instance.__dict__[self.field.name] = value class FileField(Field): - """File path""" - # The class to wrap instance attributes in. Accessing the file object off # the instance will always return an instance of attr_class. attr_class = FieldFile @@ -218,6 +216,8 @@ class FileField(Field): # The descriptor to use for accessing the attribute off of the class. descriptor_class = FileDescriptor + description = ugettext_lazy("File path") + def __init__(self, verbose_name=None, name=None, upload_to='', storage=None, **kwargs): for arg in ('primary_key', 'unique'): if arg in kwargs: @@ -325,10 +325,9 @@ def delete(self, save=True): super(ImageFieldFile, self).delete(save) class ImageField(FileField): - """File path""" - attr_class = ImageFieldFile descriptor_class = ImageFileDescriptor + description = ugettext_lazy("File path") def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs): self.width_field, self.height_field = width_field, height_field diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 7d5a41389a9ea..cc6d7dfef8946 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -708,9 +708,8 @@ def get_related_field(self): return self.to._meta.pk class ForeignKey(RelatedField, Field): - """Foreign Key (type determined by related field)""" - empty_strings_allowed = False + description = ugettext_lazy("Foreign Key (type determined by related field)") def __init__(self, to, to_field=None, rel_class=ManyToOneRel, **kwargs): try: to_name = to._meta.object_name.lower() @@ -808,13 +807,13 @@ def db_type(self, connection): return rel_field.db_type(connection=connection) class OneToOneField(ForeignKey): - """One-to-one relationship - + """ A OneToOneField is essentially the same as a ForeignKey, with the exception that always carries a "unique" constraint with it and the reverse relation always returns the object pointed to (since there will only ever be one), - rather than returning a list.""" - + rather than returning a list. + """ + description = ugettext_lazy("One-to-one relationship") def __init__(self, to, to_field=None, **kwargs): kwargs['unique'] = True super(OneToOneField, self).__init__(to, to_field, OneToOneRel, **kwargs) @@ -868,8 +867,7 @@ def set_managed(field, model, cls): }) class ManyToManyField(RelatedField, Field): - """Many-to-many relationship""" - + description = ugettext_lazy("Many-to-many relationship") def __init__(self, to, **kwargs): try: assert not to._meta.abstract, "%s cannot define a relation with abstract class %s" % (self.__class__.__name__, to._meta.object_name) diff --git a/django/db/models/loading.py b/django/db/models/loading.py index 4ab1d5005ad73..f86b691cc9129 100644 --- a/django/db/models/loading.py +++ b/django/db/models/loading.py @@ -35,6 +35,7 @@ class AppCache(object): postponed = [], nesting_level = 0, write_lock = threading.RLock(), + _get_models_cache = {}, ) def __init__(self): @@ -140,6 +141,11 @@ def get_models(self, app_mod=None, include_auto_created=False): explicit intermediate table) are not included. However, if you specify include_auto_created=True, they will be. """ + cache_key = (app_mod, include_auto_created) + try: + return self._get_models_cache[cache_key] + except KeyError: + pass self._populate() if app_mod: model_list = self.app_models.get(app_mod.__name__.split('.')[-2], SortedDict()).values() @@ -148,7 +154,8 @@ def get_models(self, app_mod=None, include_auto_created=False): for app_entry in self.app_models.itervalues(): model_list.extend(app_entry.values()) if not include_auto_created: - return filter(lambda o: not o._meta.auto_created, model_list) + model_list = filter(lambda o: not o._meta.auto_created, model_list) + self._get_models_cache[cache_key] = model_list return model_list def get_model(self, app_label, model_name, seed_cache=True): @@ -183,6 +190,7 @@ def register_models(self, app_label, *models): if os.path.splitext(fname1)[0] == os.path.splitext(fname2)[0]: continue model_dict[model_name] = model + self._get_models_cache.clear() cache = AppCache() diff --git a/django/forms/models.py b/django/forms/models.py index 81b727111e445..25e9b01e68384 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -704,7 +704,7 @@ def modelformset_factory(model, form=ModelForm, formfield_callback=lambda f: f.f class BaseInlineFormSet(BaseModelFormSet): """A formset for child objects related to a parent.""" def __init__(self, data=None, files=None, instance=None, - save_as_new=False, prefix=None): + save_as_new=False, prefix=None, queryset=None): from django.db.models.fields.related import RelatedObject if instance is None: self.instance = self.fk.rel.to() @@ -717,7 +717,9 @@ def __init__(self, data=None, files=None, instance=None, backlink_value = self.instance else: backlink_value = getattr(self.instance, self.fk.rel.field_name) - qs = self.model._default_manager.filter(**{self.fk.name: backlink_value}) + if queryset is None: + queryset = self.model._default_manager + qs = queryset.filter(**{self.fk.name: backlink_value}) super(BaseInlineFormSet, self).__init__(data, files, prefix=prefix, queryset=qs) diff --git a/docs/howto/custom-model-fields.txt b/docs/howto/custom-model-fields.txt index 13e4fff36dd0e..04fb9d24be81e 100644 --- a/docs/howto/custom-model-fields.txt +++ b/docs/howto/custom-model-fields.txt @@ -5,6 +5,7 @@ Writing custom model fields =========================== .. versionadded:: 1.0 +.. currentmodule:: django.db.models Introduction ============ @@ -165,7 +166,8 @@ behave like any existing field, so we'll subclass directly from from django.db import models class HandField(models.Field): - """A hand of cards (bridge style)""" + + description = "A hand of cards (bridge style)" def __init__(self, *args, **kwargs): kwargs['max_length'] = 104 @@ -248,7 +250,8 @@ simple: make sure your field subclass uses a special metaclass: For example:: class HandField(models.Field): - """A hand of cards (bridge style)""" + + description = "A hand of cards (bridge style)" __metaclass__ = models.SubfieldBase @@ -262,16 +265,17 @@ called when the attribute is initialized. Documenting your Custom Field ----------------------------- +.. class:: django.db.models.Field + +.. attribute:: description + As always, you should document your field type, so users will know what it is. -The best way to do this is to simply provide a docstring for it. This will -automatically be picked up by ``django.contrib.admindocs``, if you have it -installed, and the first line of it will show up as the field type in the -documentation for any model that uses your field. In the above examples, it -will show up as 'A hand of cards (bridge style)'. Note that if you provide a -more verbose docstring, only the first line will show up in -``django.contrib.admindocs``. The full docstring will, of course, still be -available through ``pydoc`` or the interactive interpreter's ``help()`` -function. +In addition to providing a docstring for it, which is useful for developers, +you can also allow users of the admin app to see a short description of the +field type via the ``django.contrib.admindocs`` application. To do this simply +provide descriptive text in a ``description`` class attribute of your custom field. +In the above example, the type description displayed by the ``admindocs`` application +for a ``HandField`` will be 'A hand of cards (bridge style)'. Useful methods -------------- diff --git a/tests/modeltests/model_formsets/models.py b/tests/modeltests/model_formsets/models.py index d6f541bfd581b..5c62885be5b48 100644 --- a/tests/modeltests/model_formsets/models.py +++ b/tests/modeltests/model_formsets/models.py @@ -644,6 +644,53 @@ def __unicode__(self): >>> formset.save() [, ] +We can provide a custom queryset to our InlineFormSet: + +>>> custom_qs = Book.objects.order_by('-title') +>>> formset = AuthorBooksFormSet(instance=author, queryset=custom_qs) +>>> for form in formset.forms: +... print form.as_p() +

+

+

+

+

+ +>>> data = { +... 'book_set-TOTAL_FORMS': '5', # the number of forms rendered +... 'book_set-INITIAL_FORMS': '3', # the number of forms with initial data +... 'book_set-0-id': '1', +... 'book_set-0-title': 'Les Fleurs du Mal', +... 'book_set-1-id': '2', +... 'book_set-1-title': 'Le Spleen de Paris', +... 'book_set-2-id': '5', +... 'book_set-2-title': 'Flowers of Evil', +... 'book_set-3-title': 'Revue des deux mondes', +... 'book_set-4-title': '', +... } +>>> formset = AuthorBooksFormSet(data, instance=author, queryset=custom_qs) +>>> formset.is_valid() +True + +>>> custom_qs = Book.objects.filter(title__startswith='F') +>>> formset = AuthorBooksFormSet(instance=author, queryset=custom_qs) +>>> for form in formset.forms: +... print form.as_p() +

+

+

+>>> data = { +... 'book_set-TOTAL_FORMS': '3', # the number of forms rendered +... 'book_set-INITIAL_FORMS': '1', # the number of forms with initial data +... 'book_set-0-id': '5', +... 'book_set-0-title': 'Flowers of Evil', +... 'book_set-1-title': 'Revue des deux mondes', +... 'book_set-2-title': '', +... } +>>> formset = AuthorBooksFormSet(data, instance=author, queryset=custom_qs) +>>> formset.is_valid() +True + # Test a custom primary key ################################################### diff --git a/tests/regressiontests/generic_inline_admin/models.py b/tests/regressiontests/generic_inline_admin/models.py index bc6764d8b2d3a..9f1bbadd3eb61 100644 --- a/tests/regressiontests/generic_inline_admin/models.py +++ b/tests/regressiontests/generic_inline_admin/models.py @@ -20,7 +20,7 @@ def __unicode__(self): class MediaInline(generic.GenericTabularInline): model = Media - + class EpisodeAdmin(admin.ModelAdmin): inlines = [ MediaInline, @@ -56,7 +56,7 @@ class MediaMaxNumInline(generic.GenericTabularInline): model = Media extra = 5 max_num = 2 - + admin.site.register(EpisodeMaxNum, inlines=[MediaMaxNumInline]) # diff --git a/tests/regressiontests/generic_inline_admin/tests.py b/tests/regressiontests/generic_inline_admin/tests.py index d28cd16e1d48d..83542d1528534 100644 --- a/tests/regressiontests/generic_inline_admin/tests.py +++ b/tests/regressiontests/generic_inline_admin/tests.py @@ -17,7 +17,7 @@ def setUp(self): self.original_template_debug = settings.TEMPLATE_DEBUG settings.TEMPLATE_DEBUG = True self.client.login(username='super', password='secret') - + # Can't load content via a fixture (since the GenericForeignKey # relies on content type IDs, which will vary depending on what # other tests have been run), thus we do it here. @@ -25,26 +25,30 @@ def setUp(self): self.episode_pk = e.pk m = Media(content_object=e, url='http://example.com/podcast.mp3') m.save() - self.media_pk = m.pk - + self.mp3_media_pk = m.pk + + m = Media(content_object=e, url='http://example.com/logo.png') + m.save() + self.png_media_pk = m.pk + def tearDown(self): self.client.logout() settings.TEMPLATE_DEBUG = self.original_template_debug - + def testBasicAddGet(self): """ A smoke test to ensure GET on the add_view works. """ response = self.client.get('/generic_inline_admin/admin/generic_inline_admin/episode/add/') self.failUnlessEqual(response.status_code, 200) - + def testBasicEditGet(self): """ A smoke test to ensure GET on the change_view works. """ response = self.client.get('/generic_inline_admin/admin/generic_inline_admin/episode/%d/' % self.episode_pk) self.failUnlessEqual(response.status_code, 200) - + def testBasicAddPost(self): """ A smoke test to ensure POST on add_view works. @@ -57,7 +61,7 @@ def testBasicAddPost(self): } response = self.client.post('/generic_inline_admin/admin/generic_inline_admin/episode/add/', post_data) self.failUnlessEqual(response.status_code, 302) # redirect somewhere - + def testBasicEditPost(self): """ A smoke test to ensure POST on edit_view works. @@ -65,17 +69,45 @@ def testBasicEditPost(self): post_data = { "name": u"This Week in Django", # inline data - "generic_inline_admin-media-content_type-object_id-TOTAL_FORMS": u"2", - "generic_inline_admin-media-content_type-object_id-INITIAL_FORMS": u"1", - "generic_inline_admin-media-content_type-object_id-0-id": u"%d" % self.media_pk, + "generic_inline_admin-media-content_type-object_id-TOTAL_FORMS": u"3", + "generic_inline_admin-media-content_type-object_id-INITIAL_FORMS": u"2", + "generic_inline_admin-media-content_type-object_id-0-id": u"%d" % self.mp3_media_pk, "generic_inline_admin-media-content_type-object_id-0-url": u"http://example.com/podcast.mp3", - "generic_inline_admin-media-content_type-object_id-1-id": u"", - "generic_inline_admin-media-content_type-object_id-1-url": u"", + "generic_inline_admin-media-content_type-object_id-1-id": u"%d" % self.png_media_pk, + "generic_inline_admin-media-content_type-object_id-1-url": u"http://example.com/logo.png", + "generic_inline_admin-media-content_type-object_id-2-id": u"", + "generic_inline_admin-media-content_type-object_id-2-url": u"", } url = '/generic_inline_admin/admin/generic_inline_admin/episode/%d/' % self.episode_pk response = self.client.post(url, post_data) self.failUnlessEqual(response.status_code, 302) # redirect somewhere - + + def testGenericInlineFormset(self): + EpisodeMediaFormSet = generic_inlineformset_factory(Media, can_delete=False, extra=3) + e = Episode.objects.get(name='This Week in Django') + + # Works with no queryset + formset = EpisodeMediaFormSet(instance=e) + self.assertEquals(len(formset.forms), 5) + self.assertEquals(formset.forms[0].as_p(), '

') + self.assertEquals(formset.forms[1].as_p(), '

') + self.assertEquals(formset.forms[2].as_p(), '

') + + # A queryset can be used to alter display ordering + formset = EpisodeMediaFormSet(instance=e, queryset=Media.objects.order_by('url')) + self.assertEquals(len(formset.forms), 5) + self.assertEquals(formset.forms[0].as_p(), '

') + self.assertEquals(formset.forms[1].as_p(), '

') + self.assertEquals(formset.forms[2].as_p(), '

') + + + # Works with a queryset that omits items + formset = EpisodeMediaFormSet(instance=e, queryset=Media.objects.filter(url__endswith=".png")) + self.assertEquals(len(formset.forms), 4) + self.assertEquals(formset.forms[0].as_p(), '

') + self.assertEquals(formset.forms[1].as_p(), '

') + + def testGenericInlineFormsetFactory(self): # Regression test for #10522. inline_formset = generic_inlineformset_factory(Media,