Django(文件上传+分页+表单)
一、文件上传
form表单中需要添加 enctype="multipart/form-data"
1.media: 文件上传的文件
在settings.py 文件中配置:MEDIA_URL = '/static/media/' #媒体路径
MEDIA_ROOT = os.path.join(BASE_DIR, 'static/media') #必须是绝对路径static|-- media|-- uploads|---2019|---05|---文件名#模板中如果想引用上传的文件并展示,
在模板中可以使用{{ MEDIA_URL }}
->TEMPLATES-> 'context_processors': [ ...django.template.context_processors.media...]在主路由中添加:re_path(r'^media/(?P<path>.*)$', serve, {'document_root': MEDIA_ROOT})模板中使用
<img src="{{ MEDIA_URL }}{{ user.icon }}" alt="" id="icon">
2.模型: FileField(任何文件)
ImageField(只能是图片)---->继承自FileField
FileField(upload_to='表示文件上传的路径 uploads/%Y/%m')--->此路径是基于media_root指明的路径ImageField(upload_to='相对路径')
使用ImageField文件上传
icon = models.ImageField(upload_to='uploads/%Y/%m/%d',default="uploads/mine1.png")icon = request.FILES.get('icon') -----> 内存 的存储对象user.username = usernameuser.email = emailuser.mobile = mobileuser.icon = icon # ImageField(upload_to='')user.save()user.icon ----> 不是存储字符串,ImageFielduser.icon.name ----> 字符串值
二、系统默认用户的继承使用:
1.必须继承AbstractUser ----》auth_user ----> 系统用户
class UserProfile(AbstractUser):mobile = models.CharField(max_length=11, verbose_name='手机号码', unique=True)icon = models.ImageField(upload_to='uploads/%Y/%m/%d')class Meta:db_table = 'userprofile'verbose_name = '用户表'verbose_name_plural = verbose_name
2.必须修改settings.py
# 如果用户继承了AbstractUser,修改auth_user的模型AUTH_USER_MODEL = 'user.UserProfile'
3.然后执行迁移和同步
authenticate() (认证)---》user =====》 login(request,user)----> session保存和request.user赋值logout()----》清空session和cookie,将request.user设置成匿名的User()is_authenticated() ----> 判断用户是否被认证 request.user.is_authenticated()
三、forms 表单:
问题:使用ModelForm好像按照注册搞,不能输入数据库已存在的用户名??
Django会处理涉及表单的三个不同部分:准备并重组数据,以便下一步的渲染为数据创建HTML 表单接收并处理客户端提交的表单及数据
1.Form 和 ModelForm
Form比较灵活需要自己定义各个要验证的字段Form使用:
class UserRegisterForm(Form):username = forms.CharField(max_length=50, min_length=6, error_messages={'min_length': '用户名长度至少6位', }, label='用户名')email = forms.EmailField(required=True, error_messages={'required': '必须填写邮箱信息'}, label='邮箱')mobile = forms.CharField(required=True, error_messages={'required': '必须填写手机号码'}, label='手机')password = forms.CharField(required=True, error_messages={'required': '必须填写密码'}, label='密码',widget=forms.widgets.PasswordInput)#widget插件,密码隐藏
ModelForm是跟Model有关的,model的字段可以直接引用过来。ModelForm使用:
class RegisterForm(ModelForm):repassword = forms.CharField(required=True, error_messages={'required': '必须填写确认密码'}, label='确认密码', widget=forms.widgets.PasswordInput)class Meta:model = UserProfilefields = ['username', 'email', 'mobile', 'password'] ---->可以自己添加需要验证的字段# fields = '__all__' ----》 如果是model中的所有字段都需要验证可以使用__all__# exclude = ['first_name','date_joined','last_name'] -----> 使用exclude排除不需要验证的部分
2.定义一些指定字段的专门验证:
def clean_username(self):username = self.cleaned_data.get('username')result = re.match(r'[a-zA-Z]\w{5,}', username)if not result:raise ValidationError('用户名必须字母开头')return username或者def clean_username(self):username = self.cleaned_data.get('username')if not UserProfile.objects.filter(username=username).exists():raise ValidationError('用户名不存在')return username或者验证密码与确认密码是否一致def clean_password(self):repassword = self.cleaned_data.get('repassword')password = self.cleaned_data.get('psssword')if password != repassword:raise ValidationError('密码不一致')return password在views中接收用rform.is_valid()
3.密码加密和检查密码:
check_password(原文密码,加密密码) -----》返回结果是booleanmake_password(原文密码) -----》加密密码返回结果是加密后的密码
cookies实现登录退出
https://www.cnblogs.com/banshaohuan/p/9493021.html
https://blog.csdn.net/weixin_33918357/article/details/85629371?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control
4.session的使用:
request.session request里面的一个属性,而且是字典类型设置session的值:request.session['key']=value取值:value = request.session.get(key)清除session:request.session.clear() # 删除字典request.session.flush() # 删除django_session + cookie +字典del request.session[key] # 删除指定的key
5.继承abstractuser的用户
from django.contrib.auth import logout,login,authenticateauthenticate+login 先使用authenticate 进行用户的数据库查询判断,如果有则返回用户对象login(request,user) ---->类似session 只不过: request.user=user#将用户对象保存在底层的request中request.user.is_authenticated 是否是认证过的用户返回值是True,False两种方式登录username = lform.cleaned_data.get('username')password = lform.cleaned_data.get('password')# 方式一# user = UserProfile.objects.filter(username=username).first()# print(password, user.password, make_password(password))# flag = check_password(password, user.password)# if flag:# request.session['username'] = username# 方式二user=authenticate(username=username,password=password)【必须是明文密码,从数据库中取出来加密的不可以】if user:login(request,user)return redirect(reverse('index'))return render(request, 'user/login.html', context={'msg': "用户名或密码有误"})两种方式注销:# 方式一:# request.session.flush()# 方式二:logout(request)两种方式验证是否登录:{# 方式一#}
{# {% if request.session.username %}#}
{# 欢迎!<a href="">{{ request.session.username }}</a> #}
{# <a href="{% url 'user:logout' %}">注销</a>#}{# 方式二#}{% if request.user.is_authenticated %}欢迎!<a href="">{{ request.user.username }}</a> <a href="{% url 'user:logout' %}">注销</a>{% else %}<a href="{% url 'user:login' %}">登录</a> <a href="{% url 'user:register' %}">注册</a>{% endif %}
四、发送手机验证码:第三方
写账号密码登陆和验证码登陆的切换页
使用网易云信:
https://dev.yunxin.163.com/docs/product/%E7%9F%AD%E4%BF%A1/%E7%9F%AD%E4%BF%A1%E6%8E%A5%E5%8F%A3%E6%8C%87%E5%8D%97模拟浏览器发送请求:
pip install requests
1.流程
发送验证码:
---》 send_code ----> ajax ----》sendcode + mobile
-----》后台:mobile -----》使用requests(浏览器)
2.定义工具类
#作用就是向网易云信发送请求,帮助后台发送短信息给客户
def util_sendmsg(mobile):url ='https://api.netease.im/sms/' ---->访问网易云信的url地址data={'mobile':你的手机号码} ----AppKey =‘’ #开发者平台发布的Nonce=‘’ #随机数CurTime=str(time) #时间戳AppSecret=''content=AppSecrect+Nonce+CurTimeCheckSum=hashlib.sha1(appsecret+Nonce+CurTime)headers={} -----》4 部分response = requests.post(url,data,headers)str = response.Textjson = json.loads(str)json.codejson.obj ----> 发送的验证码保存到session
五、生成图形验证码(使用插件)
文档地址:
https://django-simple-captcha.readthedocs.io/en/latest/usage.html
1.插件安装步骤
1.pip install django-simple-captcha2.Add captcha to the INSTALLED_APPS in your settings.py3.Run python manage.py migrate------》数据库自动添加表(captcha-captchastore)4。Add an entry to your urls.py:re_path(r'^captcha/',include('captcha.urls'))
2.使用验证码插件步骤
Form使用
1.# 验证码captcha的Form
class CaptchaTestForm(forms.Form):email = EmailField(required=True, error_messages={'required': '必须填写邮箱'},label='邮箱')captcha = CaptchaField()产生的图形就是一张图片。img+hidden2.使用CaptchaTestForm渲染页面:if request.method == 'GET':form = CaptchaTestForm()return render(request, 'user/forget_pwd.html', context={'form': form})3.页面中使用captcha:
<div class="w3layouts-main"><p>{{ msg }} {{ errors }}</p><form action="{% url 'user:forget_pwd' %}" method="post"> {% csrf_token %}{{ form.email }}{{ form.captcha }}<input type="submit" value="找回密码"></form></div>
3.刷新验证
$('.captcha').click(function(){var img= $(this);$.getJSON('/captcha/refresh',function(data){console.log(data)img.attr('src',data['image_url']); #attr是一个属性$('#id_captcha_0').val(data['key'])})});
4.验证验证码是否正确
$('#id_captcha_1').blur(function(){var $this = $(this);var key = $('#id_captcha_0').val();var code = $(this).val();$.getJSON('{% url 'user:valide_code' %}',{key:key,code:code},function(data){console.log(data)if(data.status==1){$this.after('<span>验证码正确</span>')}else{$this.after('<span>验证码错误</span>')}})})路由:valide_code# 定义一个路由验证验证码
def valide_code(request):if request.is_ajax():key = request.GET.get('key')code = request.GET.get('code')# CaptchaStore 模型对象captche = CaptchaStore.objects.filter(hashkey=key).first()if captche.response == code.lower():# 正确data = {'status': 1}else:# 错误的data = {'status': 0}return JsonResponse(data)
六、发送邮件
1.邮件的配置
在settings.py中配置:EMAIL_HOST = 'smtp.126.com'EMAIL_HOST_USER = 'student1902@126.com'EMAIL_HOST_PASSWORD = 'student1902' #邮箱的授权码EMAIL_PORT = 25EMAIL_USE_TLS = TrueEMAIL_USE_SSL = False # 126,QQ: 465 163:454
2.调用方法
send_mail(subject,message,from,to_list)发送成功就是1 否则0message与html_message的区别ran_code = uuid.uuid4()ran_code = str(ran_code)ran_code =ran_code.replace('-','')request.session[ran_code] = user.id
3.进行激活
密码和确认密码+ 隐藏表单域(code)code = request.POST.get('code')uid = request.session.get(code)user = UserProfile.objects.get(pk=uid)# 获取密码pwd = request.POST.get('password')repwd = request.POST.get('repassword')if pwd == repwd and user:pwd = make_password(pwd)user.password = pwduser.save()return render(request, 'user/update_pwd.html', context={'msg':'用户密码更新成功!'})else:return render(request, 'user/update_pwd.html', context={'msg': '更新失败!'})
七、中间件(类似flask 钩子函数)
https://www.cnblogs.com/sui776265233/p/9664642.html
1.中间件应用场景
由于中间件工作在 视图函数执行前、执行后适合所有的请求/一部分请求做批量处理。1、做IP限制放在中间件类的列表中,阻止某些IP访问了;2.URL访问过滤如果用户访问的是login视图(放过)如果访问其他视图(需要检测是不是有session已经有了放行,没有返回login),这样就省得在 多个视图函数上写装饰器了!3、缓存(CDN)客户端请求来了,中间件去缓存看看有没有数据,有直接返回给用户,没有再去逻辑层 执行视图函数
2.进行用户的登录验证
中间件进行用户的登录验证
步骤:1. middreware文件夹----》 xxxmiddleware.py ---->定义类继承MiddlewareMixin2. 重写:如果仅仅是对请求做处理则重写的方法名:process_request(self,request)3. 参数request:参数request是请求对象request.pathrequest.methodrequest.is_ajax()request.META.get('REMOTE_ADDR')if path in login_list:print(request.user) # AnonymousUser 未登录print(type(request.user))print(request.user.username) # 认为就是用户登录的对象if not request.user.is_authenticated:return redirect(reverse('user:login'))
使用装饰器进行用户的登录验证
@login_required 前提(要验证的用户必须是继承自AbstractUser)login(request,user)request.user.is_authenticated@login_requireddef user_center(request):return HttpResponse('用户中心')改变页面跳转需要在settings.py文件中设置:LOGIN_URL = '/user/login'# 添加一个登陆路由 结合 @login_required
3.中间件的默认可以自定义的函数
Request预处理函数: process_request(self, request)
这个方法的调用时机在Django接收到request之后,但仍未解析URL以确定应当运行的视图函数。Django向它传入相应的Request对象,以便在方法中修改。如果返回None,Django将继续处理这个request,执行后续的中间件, 然后调用相应的 view。如果返回HttpResponse对象,Django将不再执行任何除了process_response以外其它的中间件以及相应的view,Django将立即返回该HttpResponse。
View预处理函数: process_view(self, request, callback)
callback_args,callback_kwargs)这个方法的调用时机在 Django 执行完 request 预处理函数并确定待执行的 view (即callback参数)之后,但在 view 函数实际执行之前。request:HttpRequest 对象。callback:Django将调用的处理request的python函数. 这是实际的函数对象本身, 而不是字符串表述的函数名。args:将传入view的位置参数列表,但不包括request参数(它通常是传入view的第一个参数)。kwargs:将传入view的关键字参数字典。process_view() 应当返回None或 HttpResponse 对象。如果返回 None, Django将继续处理这个request ,执行后续的中间件, 然后调用相应的view。如果返回 HttpResponse 对象,Django 将不再执行任何其它的中间件(不论种类)以及相应的view,Django将立即返回。
Template模版渲染函数:process_template_response()
默认不执行,只有在视图函数的返回结果对象中有render方法才会执行,并把对象的render方法的返回值返回给用户(注意不返回视图函数的return的结果了,而是返回视图函数 return值(对象)中rende方法的结果)
Exception后处理函数:process_exception(self, request, exception)
这个方法只有在 request 处理过程中出了问题并且view 函数抛出了一个未捕获的异常时才会被调用。这个钩子可以用来发送错误通知,将现场相关信息输出到日志文件,或者甚至尝试从错误中自动恢复。这个函数的参数除了一贯的request对象之外,还包括view函数抛出的实际的异常对象exception 。process_exception() 应当返回None或HttpResponse对象。如果返回None,Django将用框架内置的异常处理机制继续处理相应request。如果返回HttpResponse对象,Django将使用该response对象,而短路框架内置的异常处理机制。
Response后处理函数:process_response(self, request, response)
这个方法的调用时机在 Django 执行 view 函数并生成 response 之后。该处理器能修改response 的内容;一个常见的用途是内容压缩,如gzip所请求的HTML页面。这个方法的参数相当直观:request是request对象,而response则是从view中返回的response对象。process_response() 必须返回 HttpResponse 对象. 这个 response 对象可以是传入函数的那一个原始对象(通常已被修改),也可以是全新生成的
九、云存储(七牛云)
1.注册用户
2.创建存储空间,测试域名(30天)
3.文档中心:https://developer.qiniu.com/kodo/sdk/1242/python
4.在项目中使用:
#上传图片到七牛云def upload_image(storeobj):# 只要注册用户就会有默认的access_key,secret_keyaccess_key = '1fXvG9wkbN7AgRUG6usHDcRP5Bb85apcovRAIITP'secret_key = 'Aqf1lPAmUG72EdZJ7PxKtWHfWDYNdUycZP1TaAIN'# 构建鉴权对象q = Auth(access_key, secret_key)# 要上传的空间bucket_name = 'myblog'# 上传后保存的文件名key = storeobj.name# 生成上传 Token,可以指定过期时间等token = q.upload_token(bucket_name, key, 3600)# 要上传文件的本地路径# localfile = os.path.join(MEDIA_ROOT, imagepath) # 本地图片路径ret, info = put_data(token, key, storeobj.read()) # 第三个参数是二进制流ret,info = put_file(token,key,localfile) # 第三个参数是文件的路径print(ret, info)filename = ret.get('key')save_path = 'http://pr67kkhq9.bkt.clouddn.com/'+filenamereturn save_path
接口:
模板:给用户看的model 模型view 视图 + url路由 ----》 类视图url:------》 json ----》前端app(vue) + 后端 --------》 前后端分离
十、xadmin与admin
https://xadmin.readthedocs.io/en/docs-chinese/quickstart.html#id1git里下载zip并解压
cmd进入requirements.txt文件夹
workon 切换到虚拟环境
pip install -r requirements.txt
将解压后文件夹中的xadmin文件夹复制到项目下
使用:
https://blog.csdn.net/xinyan233/article/details/80399534
xadmin就是admin的升级版,样式,操作方便
1.xadmin的安装
不推荐:pip install xadmin推荐源码安装:xxxdjango2.0-xadmin.zip|--django2.0-xadmin|--- xadmin|---requirements.txtpip install -r requirements.txtxadmin复制到项目下
2.相关配置
配置settings.py
INSTALLED_APPS=[...'xadmin','crispy_forms']
配置主路由
主路由:path('xadmin/',xadmin.site.urls)
迁移同步
python manage.py makemigrations python manage.py migrate
注册models
你的app|--admin.py|--xadmin.py -----> xadmin.site.register(xxxModel)xadmin.site.register(Article,ArticleAdmin)xadmin.site.register(Tag)
3.相关设置
article/adminx.py
class ArticleAdmin(object):list_display = ['title', 'click_num', 'love_num', 'user']#显示自己想看的列search_fields= ['title','id'] #用于检索的列list_editable= ['click_num','love_num'] #可编辑的列list_filter=['date','user'] #可用于过滤的列
acticle/apps.py
class ArticleConfig(AppConfig):name = 'article'verbose_name = '文章操作'
init.py
default_app_config = 'article.apps.ArticleConfig'
user/adminx.py:主题设置
class BaseSettings(object):enable_themes = Trueuse_bootswatch = Trueclass GlobalSettings(object):site_title = '博客后台管理'site_footer = '达达的博客公司'# 注册 xadmin.site.register(views.BaseAdminView, BaseSettings) xadmin.site.register(views.CommAdminView, GlobalSettings)
十一、分页:Paginator,Page
分页器
paginator = Paginator(articles, 3) # Paginator(对象列表,每页几条记录)
分页器属性
print(paginator.count) # 总的条目数 总的记录数print(paginator.num_pages) # 可以分页的数量 总的页码数print(paginator.page_range) # 页面的范围
方法: get_page()
page = request.GET.get('page',1)page = paginator.get_page(page) # 返回的是page对象 参数就是页码数
方法
page.has_next() # 有没有下一页page.has_previous() # 判断是否存在前一页page.next_page_number() # 获取下一页的页码数page.previous_page_number() # 获取前一页的页码数
属性:
object_list 当前页的所有对象 number 当前的页码数 paginator 分页器对象
十二、富文本:ckeditor
https://www.jianshu.com/p/f965853ecba1
https://www.cnblogs.com/ianduin/p/7732983.html
https://zhuanlan.zhihu.com/p/78705834
安装
pip install django-ckeditor
注册应用
在settin.py中添加INSTALLED_APPS = [...'ckeditor', #注册应用,添加ckeditor富文本编辑器‘ckeditor_uploader', #文件上传需要]
文件上传配置
配置MEDIA_URL和MEDIA_ROOT, 上传路径的根目录就是以MEDIA_ROOTCKEDITOR_UPLOAD_PATH = "uploads/",
设置urls.py路径
re_path(r'^ckeditor/', include('ckeditor_uploader.urls')),
在models.py中设置
content=RichTextUploadingField(verbose_name=’内容‘)class Article(models.Model):title = models.CharField(max_length=100, verbose_name='标题')desc = models.CharField(max_length=256, verbose_name='简介')content = RichTextUploadingField(verbose_name='内容')
迁移和同步
访问:xadmin后台
十三、富文本:ueditor
1、安装方法
* 将github整个源码包下载下来git clone https://github.com/cooljacket/DjangoUeditor
* 然后,假设你的python安装目录是PYTHON_ROOT(我的是D:\soft\py3.5),直接复制DjangoUeditor文件夹到PYTHON_ROOT\Lib\site-packages\下就好了,比如我的就是D:\soft\py3.5\Lib\site-packages\
* 之所以不使用原来的setup.py来安装,是因为我发现,用它的setup脚本会改动代码成原来的样子,也没去深究为什么,最后发现只需要直接复制过去就好了,而且卸载也很方便,直接删除就好了,没有什么依赖项和设置!
2.在Django中安装DjangoUeditor
在INSTALL_APPS里面增加DjangoUeditor app,如下:INSTALLED_APPS = (#........'DjangoUeditor',)
3、配置urls
url(r'^ueditor/',include('DjangoUeditor.urls' )),
4、在models中的使用
from DjangoUeditor.models import UEditorFieldclass Blog(models.Model):Name=models.CharField(,max_length=100,blank=True)Content=UEditorField(u'内容 ',width=600, height=300, toolbars="full", imagePath="", filePath="", upload_settings={"imageMaxSize":1204000},settings={},command=None,event_handler=myEventHander(),blank=True)
Django(文件上传+分页+表单)相关推荐
- SpringMVC的请求-文件上传-客户端表单实现
文件上传客户端表单需要满足: 表单项type="file" 表单的提交方式是post 表单的enctype属性是多部分表单形式,及enctype="multipart/f ...
- vueform表单文件上传_峰哥说技术系列-8.Spring Boot文件上传(Form表单和Ajax方式)
今日份主题 Spring Boot文件上传(Form表单和Ajax方式) 在Spring Boot中,和文件上传的主要和MultipartResolver接口有关,他有两个实现类 StandardSe ...
- ajax实现文件上传和表单提交
1. ajax提交表单 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html ...
- spring mvc 文件上传 form表单
jsp页面 <form class="form-horizontal" role="form" id="form" enctype=& ...
- Android之解决PC端上传http表单格式文件手机解析文件名乱码问题和PC浏览器下载文件的文件名显示乱码问题
1 问题 问题1. 手机写socket作为服务器,PC浏览器上传http表单格式文件,然后手机端解析携带中文的文件名我解析是乱码. 问题2. 手机写了socket作为服务器,PC浏览器下载文件,但是浏 ...
- django文件上传到服务器,django上传文件的三种方式
Django文件上传需要考虑的重要事项 文件或图片一般通过表单进行.用户在前端点击文件上传,然后以POST方式将数据和文件提交到服务器.服务器在接收到POST请求后需要将其存储在服务器上的某个地方.D ...
- Django文件上传***
分别用三种Django文件上传方式(form方式.jQuery+jQuery.ajax方式.原生JS+原生ajax方式)做上传功能示例 文件 文件释义 form_upload.html form上传文 ...
- WM6不支持SendRequestEx,怎么上传HTTP表单?
即http协议里Post用这种方式 Content-Type: multipart/form-data 看到的例子用的是CHttpFile::SendRequestEx这个函数,但是WM6不支持. 那 ...
- 前后端分离 -- 深入浅出 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~
前后端分离 – 深入浅出系列 Spring Boot + Vue + ElementUI 实现相册管理系统[文件上传 分页 ] 文件上传也不过如此~ 引言 Hello,我是Bug终结者,一名热爱后端J ...
最新文章
- 05 Java程序员面试宝典视频课程之Jquery
- 【Java 并发编程】线程池机制 ( 线程池状态分析 | 线程池状态转换 | RUNNING | SHUTDOWN | STOP | TIDYING | TERMINATED )
- 网工基础测试题(附HCIA题库)
- ES语法及-IK分词器
- 获取本地 qt_用QT实现视频/音乐播放组件
- 程序员面试金典 - 面试题 17.17. 多次搜索(Trie树)
- python获取mysql数据为excel中的sheet_python 从excel、csv、mysql、txt获取数据源
- 数据挖掘:模型选择——XGBoost与LightBGM
- bzoj 5281: [Usaco2018 Open]Talent Show【dp】
- delphi2007不使用msbuild的方法
- Kettle下载和安装
- H3C 无线控制器WX2510H-F与无线接入点WA5320-C-EI的安装与关联详细指导书
- [jbb0523整理]压缩感知中的数学知识:NP-hard问题
- lbs与gis的计算机存储模式,什么是LBS、GIS
- 互联网十大网络流行语
- wp网站,wordpress网站搭建,wp网站建设教程
- linux的lilo,深入Linux的LILO
- ArcGIS遇到严重的应用程序错误的解决办法
- 偷偷看了同事的代码找到了优雅代码的秘密
- pinctrl 子系统介绍