mUqu;{w6Tg>bK4LTjxXTF5723#q}M<&<@SNR8Ma$5O#GCv- zia $1|1nJA5<{}aSHB9gwH;}H8bOgpQ!FS!2z+zk#DHovW zOz{XmL*{HE#xhoTD@|~`ku0KUYi>ay=}G~qocMstWyXQG!33!< w>Rgs_Rns#qOey|L?+$+dtkt)?IQp72HiT?Vs -&e zbGI$HS4}icwp?hLbFZayTGRGoV|y{sp}9N$wLl35Q}j6S9||;Oq6b)4S`|kKqfxw7 z{v)u0Mc_U%S!N&b*_7Q_R~=Q81+Bz)RPqX=EoHI|Lj%mmX1w!_ AVd z66?q_f<4bBnX3-N8>D)*WNHLwp8XJg3;-~|2(GK{D_q$rSdmPjP4Ecb<)`I+Jv6V9 z6L6(D0<8CEKfC|?cNc&7N%>t4T$W1!Pu1-byiDT*qK=k`XWgDCGhx7El9;+f5c}h~ zw5sGbz~kNDyubL<$;Hn;S@`^e#mk>A{_5xVuYIxj@rO&leCPh`IiLnPa_oiQP2c{0& zNDvmsFD#9myE{6u_~T2wo6?zb*^%7Qxs*(pHjZZmS<-DvT*{_J7*${c1G-H}4kT3t zlTeo{)St@&{}5v`j+JW_lhl9>H4zh9j~yT>B;}wK%Y|4=KN{%1VwF3>d%@r(VmS#N zl%zW_erW8_c<)&6R9Dg6G_wComw(>ZFx{uMA1E|-6@3Ra$H6-u-}v#d 7S zjMYRAE`%Jf3Q&5mVn9B5BDnIogvkYCaz?xxI@3!+#$tp}NP2ZZ{Kz*?`HuC*ilZ`N z5=5|#tAKid!)g|j?+T!Iz{nI#(Uinj4^-A9WZ-YflMw>Jn0#(f%15bzzGelRNacqq z{1QS&2?E7R8l7JtdVU(h$Bx}#olA=^;X_~vm4TGg&^@p)409WG6i~-4^xU732mWrM z=38j}E!24%J$oB<7EtFc)bf?Ru4oU9a1Wh`t)IwE^-st}ruiXT$LxG$LF}dnMEct{ YmRbGKvE0JL?5J1}X|0oanW6jo2mQ`-c>n+a delta 764 zcmbVJziSjh6rQ>LdHW-|904IsRz#D{nT=p!6BPutOQT3wgmc}U++CQxJ>Sd~if|Sd zmf{w%v<+hApI|9UAl>R!R(9fbR=!#86kCUxZ@zi&&Ae~k`@H_nn|$ soHuEko-HLk}x+B9y&2JSjHb1SycXJjU~^Jd&c zZapWlli7%F) #tKh0@4u4dIB$Kfb3Z= RP#PbS6d}1U{adxWqETGxF74dAad=_tf1y z(KlykBL6GG2i6-1$>6UJP(`j41hDNPuk1w-wD71*|LC}W>UK`_4lKR@;2cn^GFYAr zco}(DX}jd!1G-v%@~(K5cKhbtO6xHRM%nVW?%V2Zt9W?GQYos|c$6iQbqnaGz>tB7 z{!jxKH)tz3gCJC?f*^oeSzBNqx^=#8nv7)HPvATTESInRH y1T!8vQ-JH5Ib?RdR zDlh80MaVCE7bC} l!gi}&P<2ip!G|? E0Rqsef&c&j diff --git a/DjangoBlogs/auth1/forms.py b/DjangoBlogs/auth1/forms.py new file mode 100644 index 0000000..c603672 --- /dev/null +++ b/DjangoBlogs/auth1/forms.py @@ -0,0 +1,38 @@ +from django import forms +from django.contrib.auth import get_user_model +from .models import CaptchaModel + +User = get_user_model() + + +class RegisterForm(forms.Form): + username = forms.CharField(max_length=20, min_length=2, error_messages={ + 'required': '请传入用户名!', + "max_length":'用户名长度在2~20之间!', + "min_length": '用户名长度在2~20之间!' + }) + email = forms.EmailField(error_messages={"required": '请传入邮箱!', 'invalid': '请传入一个正确的邮箱!'}) + captcha = forms.CharField(max_length=4, min_length=4) + password = forms.CharField(max_length=20, min_length=6) + + def clean_email(self): + email = self.cleaned_data.get('email') + exists = User.objects.filter(email=email).exists() + if exists: + raise forms.ValidationError('邮箱已经被注册!') + return email + + def clean_captcha(self): + captcha = self.cleaned_data.get('captcha') + email = self.cleaned_data.get('email') + + captcha_model = CaptchaModel.objects.filter(email=email, captcha=captcha).first() + if not captcha_model: + raise forms.ValidationError("验证码和邮箱不匹配!") + captcha_model.delete() + return captcha + +class LoginForm(forms.Form): + email = forms.EmailField(error_messages={"required": '请传入邮箱!', 'invalid': '请传入一个正确的邮箱!'}) + password = forms.CharField(max_length=20, min_length=6) + remember = forms.IntegerField(required=False) \ No newline at end of file diff --git a/DjangoBlogs/auth1/urls.py b/DjangoBlogs/auth1/urls.py index 06cc34f..677919b 100644 --- a/DjangoBlogs/auth1/urls.py +++ b/DjangoBlogs/auth1/urls.py @@ -4,7 +4,8 @@ from .import views app_name = 'auth1' urlpatterns=[ - path('login',views.login, name='login'), + path('login',views.login1, name='login'), + path('logout',views.logout1, name='logout'), path('register',views.register, name='register'), path('captcha', views.send_email_captcha, name='email_captcha') ] \ No newline at end of file diff --git a/DjangoBlogs/auth1/views.py b/DjangoBlogs/auth1/views.py index c1b0e1d..752562f 100644 --- a/DjangoBlogs/auth1/views.py +++ b/DjangoBlogs/auth1/views.py @@ -1,16 +1,63 @@ -from django.shortcuts import render +from django.shortcuts import render, redirect, reverse from django.http.response import JsonResponse import string import random from django.core.mail import send_mail from .models import CaptchaModel +from django.views.decorators.http import require_http_methods +from .forms import RegisterForm, LoginForm +from django.contrib.auth import get_user_model, login, logout +from django.contrib.auth.models import User + +User = get_user_model() + + # Create your views here. -def login(request): - return render(request, 'login.html') +@require_http_methods(['GET', 'POST']) +def login1(request): + if request.method == 'GET': + return render(request, 'login.html') + else: + form = LoginForm(request.POST) + if form.is_valid(): + email = form.cleaned_data.get('email') + password = form.cleaned_data.get('password') + remember = form.cleaned_data.get('remember') + user = User.objects.filter(email=email).first() + if user and user.check_password(password): + # 登录 + login(request, user) + # 判断是否需要记住我 + if not remember: + # 如果没有点击记住我,那么就要设置过期时间为0,即浏览器关闭后就会过期 + request.session.set_expiry(0) + # 如果点击了,那么就什么都不做,使用默认的2周的过期时间 + return redirect('/') + else: + print('邮箱或密码错误!') + return redirect(reverse('auth1:login')) + + +def logout1(request): + logout(request) + return redirect('/') +@require_http_methods(['GET', 'POST']) def register(request): - return render(request, 'register.html') + if request.method == 'GET': + return render(request, 'register.html') + else: + form = RegisterForm(request.POST) + if form.is_valid(): + email = form.cleaned_data.get('email') + username = form.cleaned_data.get('username') + password = form.cleaned_data.get('password') + User.objects.create_user(email=email, username=username, password=password) + return redirect(reverse('auth1:login')) + else: + print(form.errors) + return redirect(reverse('auth1:register')) def send_email_captcha(request): diff --git a/DjangoBlogs/blog/__pycache__/models.cpython-312.pyc b/DjangoBlogs/blog/__pycache__/models.cpython-312.pyc index e92a6ce197f08170e34fb7fc821bba9c4864385a..31b03fb6eef4fd7fbff8ecadc8c84dc29d403e99 100644 GIT binary patch literal 1985 zcmb7_O=ufO6vua^)#t9HG@qpwsvFZZD#5+9h89yur8o|yA`nFfVZ2D%i7X>&lT0ba 0PUfaOgSLoF5vRk +peU_w*sqkzfpVo0%g{dUyl$nds%Oz@uXf9|Jj)GhlI`U9utSt{U<)P)mYM>=g zUJKK=wgY$NYX^#dq5J>mi{}-Sv!`iN!?q%t&Nv)6WdFdP5O~$>nxo;|$-axn9ey>A z$T0rxSN)o+;obqzGjOzbz-alU(Y}%r^e_oiOdas0BBpbF`P<&zC5qf^;d}Syjqbfi zb&=vlh;DHx?ksj!zge&T+^hZsP$-F_p{sfQYc-*1Jd96dq67UdJ+A`A#2~zr&-&Ld z-~U~{5eXikGE7TxR_Z}PK&Tgl*^G>lCCn8iR}2#tM@r8dByTWJ7(k6?a>VpIFBg-l z0k6zGp;MAc=f5N-B+L;yeIax@e1 d{{Vj{;9)(=DG0U7kQC*7gLNp1_h(o4 z (gr=K26QFWLggIM+$y15_B<_#tY`CmNcvEq5eBw8k$LtBJdPX zitm8gzQVs2vy}2J^5yT|(hKLfS;s%8AHhJZZH03n|5!y)d?xsx38Q~Fj{NR8R+cs; tQ9LIuj8(@M$2SGEH=Q;yCRWDojNbwe+M5R@(1jD#Q;Vmz1hhHp{{i>Xu{r<% delta 141 zcmX@eznL-aG%qg~0}$BQ`=r?b>Bk@r3@||%p9O%7=?p0hDU3M`xr|Yaj0}}bn#?aj z(wdC7*mCnzQge#^G?{L3rer1NrRVFVBo#3OB_|(ZG*JD;VFOf9nv-f*!~qmz1ma>4 R;{!7zBjY^=nIbkI2LN0!92x)s diff --git a/DjangoBlogs/blog/__pycache__/views.cpython-312.pyc b/DjangoBlogs/blog/__pycache__/views.cpython-312.pyc index cdcde863f9873a57ccc6efcfc7a28e7977df668b..4e63bfcac0e36070db712b13ff1d2adef627ed15 100644 GIT binary patch delta 497 zcmX|6Jxe4(5bc_;9i3g>z2HCt5e#Jf7&B22Lqm^C3?^A-w_6>V+0p75VNEpf2RMjm zBpAwt_cJb8*lf7X4h}K#BQvtPQ46|w_3G8D>eBx0H2yRi zsuSw<*^QChT9zhk`rj>=TD>zvjCSioS=+LDAy^ zeW>avjs;55PNI`O)e}j!7x&sIoTDN}!7uM%t-Shado*a5kLlJJfvVOaSv%&^plWs& z)#a6^NiOmzPH>VKm!51=I%9vm*2Vl_dTHn_53FUZU*5uxQ{4yZe;BxjMW?MyutlWW zD3#3_`=_RFR)*ffz*@jMaohe_)#L|JZ!ZhveujCs$R%3T`JxL AL?$_ z%Q5Z*QPI!$11`E5MtO!39a5oMs&CgP+%vsQfA7uRNHbm}ViUiUNS!TLC_R|~Fk*8f g=8xF=iv{4nH~_)3!;Iz-TF(Z+;;YGwZyIUCcjESYkN^Mx delta 335 zcmdnYHj$P0G%qg~0}!0O>60ckkyp}O3CNkwkiw9{n8T3E7{$oQkiyi$5XF?j3?!LT zSb!u;C95XeOOURWjJMc|Qu9($izdHkw3zrfkd+fC$}-uKG1rY9$hyUzl#`zxpP5q3 z1mr0w6mftAxxs=dsU?Y-IYqoc5s=bi0U*)9aEDuPg8Bt1oy*+17g%(QxF)}0^si?F z$uj~8r~w=WrAhH1LyGu;f*|)7gBVcVGxRTWYh7T`DgsIPX|moDNXbgfOV8IU&d4t+ zNiHoZE@A=76oH%ywjONCN(QicunT{2*yQG?l;)(`6$t?qse-I776%d^m>C%v?=mQV RVq;{~1QB|lfrK_#CjcusOt=65 diff --git a/DjangoBlogs/blog/migrations/0001_initial.py b/DjangoBlogs/blog/migrations/0001_initial.py new file mode 100644 index 0000000..a3e0d0b --- /dev/null +++ b/DjangoBlogs/blog/migrations/0001_initial.py @@ -0,0 +1,45 @@ +# Generated by Django 5.0.6 on 2024-05-29 08:39 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='BlogCategory', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200, verbose_name='分类名称')), + ], + ), + migrations.CreateModel( + name='Blog', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200, verbose_name='标题')), + ('content', models.TextField(verbose_name='内容')), + ('pub_time', models.DateTimeField(auto_now_add=True, verbose_name='发布时间')), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='作者')), + ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='blog.blogcategory', verbose_name='分类')), + ], + ), + migrations.CreateModel( + name='BlogComment', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('content', models.TextField(verbose_name='内容')), + ('pub_time', models.DateTimeField(auto_now_add=True, verbose_name='发布时间')), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='作者')), + ('blog', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='blog.blog', verbose_name='所属博客')), + ], + ), + ] diff --git a/DjangoBlogs/blog/migrations/__pycache__/0001_initial.cpython-312.pyc b/DjangoBlogs/blog/migrations/__pycache__/0001_initial.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c24827000cea75ce2402715ed89b31a7f3464471 GIT binary patch literal 2824 zcmds3O>7%Q6rNq%>$T&gc1YvevC|)gHnxJ*03i)RsA>M_PtuU4p|uhg+cR<3*j}?< zr*#hyL|e+CBAgl_gitSlVpWNRXsQaqu@aYE5ox255S73!xmilN^u)}r-K1)u^wI-+ zn4S0b{eADfnYTaJ*E<1uZmmsB&+q{JPKnxMt8UiE$mS}505WM1WyqUNvl&a&!cd+i zZOz!CwhR~L7{G!d0Ie4Qv>{unp=M~~y 5T)~p4FdqUtHk=Gl}3e(h@vcHq81h)Ys$d0SpfjVZ5az=N+p>nZ)i3? zszoWtLTc5SYTn`-0~u(Awi35MBB9ST3+;yV4wK%zLLNFw&IQ)wO|wb1R9B<^(Yxy@ zz1RPX_lC{h;Wk6kzd1s458WltLNzl4Pop6h*g}qh&y|{L2#Dl%L$dX8N#suLd7PVS z+Je`%1#j=;yshgAn@iqWf01~0JiB u$8WBw@GUkTx2O CWNTY00IV00cG{nl=$P07RB1*$Nw$f0rO%ateDsbe>-LF1gyEc#Q2`Q_ftYYxW zmoApC-wZK^1 )%CBFf{sKBLaVbS}wsK$5-?lf9$^25D`uqwh>iu5QQCImO)8_mj}aN%l?B zIVj0UOlFUg7U5tjmQ6~Sg>lRq$t9By+xvP?^!4@+V5gKr)oJ)GSSS9#g9H7qPL38w zWhsRc%4ENxPLrFTq* E~9BZ(a55yyMxfdc$)wx;LzO!^_s& zZE93dv+{~Juez00k5~1D=9_h2Nb`jjPyF=$if=-7zg4kWni}rgIES;+@Q6L{lkDwK z{o(n&x<9P>!;6XA{EGig)jhWA@vDK3`9VF @a&DfWQb#2+wiWFdd<$BU&)B-29{OrcduVto0n$d&ab$F})|M^+Z)cCgO+K zBUHEbsG)m|t<>8ocqakh{0R8gCxL(FAW8MYw0dF97hasWaeC>r-Zh|g4d`7XTGxo) zHKBD)s7O+k4+zfV>=ec6f7`$*u$4NF;&c$4`+|+!heza>YE2j7vCnMw2#iO}Kf6e+ z
O2c^n-NHH?#M967U(U!-;o<1drl1O7Gh