Django-组件功能01

目录

  1. AJAX
  2. 设置csrf_token
  3. Django内置序列化
  4. 分页器
  5. Form组件
  6. ModelForm组件

AJAX

AJAX(Asynchronous JavaScript And XML):异步的JavaScript和XML,即可以与数据库进行异步交互传输数据。
特点:异步提交,局部刷新

语法:$.ajax({name:value,...})
	name参数:
		url							发送请求的URL
		type						请求方式
		data						发送的数据
		contentType					发送数据的数据类型,json:application/json,不使用:false,发送文件时设置
		processData					当为True时内部处理文件内容,false则不处理,发送文件时设置
		success(result,status,xhr)	请求成功后执行的函数,result:接受后端返回的结果

test.html
发送请求
	发送文件和键值对
		$("#btn1").click(function (){										# 给按钮绑定点击事件
		        let form_data = new FormData();								# 创建formdata对象赋值给变量
		        form_data.append('d1', $("#d1").val());						# 往formdata内添加普通键值
		        form_data.append('file1', $("#file1")[0].files[0])			# 往formdata内添加文件
		        $.ajax({													# 启动ajax
		            url: "{% url 'test' %}",								# 反向解析url,并向该url发送请求
		            type: 'POST',											# 请求方式
		            data: form_data,										# 请求数据
		            processData: false,										# 不处理文件内容
		            contentType: false,										# 不使用数据类型
		            success: function (data){								# 请求成功后执行的函数,data为后端返回的数据
		                console.log(data)									# 控制台上打印返回的数据
		            }
		        })
		    })

	发送JSON数据
		$("#btn1").on('click', function (){							
	        $.ajax({
	            url: '',												# 空及表示向当前页面发送请求
	            type: 'POST',
	            contentType: 'application/json',						# 指定数据类型为'application/json'
	            data: JSON.stringify([1,3,4]),							# 需要将发送数据序列化成json数据
	            success: function (data){
	                console.log(data)
	            }

       	 	})
   	 	})
		

view.py
接受键值对
	request.POST

接受JSON
	request.body

接受文件
	request.FILES

返回字符串
	return HttpResponse(str)

返回JSON数据
	方法一:先转换成字符串再返回字符串
		return HttpResponse(json.dumps(dict))
	
	方法二:通过JsonResponse
		return JsonResponse(data,safe)
		当data不是字典的时候,需要将safe=False

设置csrf_token

Form表单
	在form表单内添加以下代码
		{% csrf_token %}

AJAX
方式一:获取隐藏的input标签中的csrfmiddlewaretoken值放在data中发送
	
	$("#btn1").on('click', function (){
        $.ajax({
            url: '',
            type: 'POST',
            data: {
                "user": "mimi",
                "pwd": "123",
                "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val()
                    },
            success: function (data) {
                console.log(data)
                }
	    })
    })

方法二:获得返回的cookice中的字符串,放置在请求头中发送,使用前需要导入插件jquery.cookie.js
	$("#btn1").on('click', function (){
        $.ajax({
	          url: "",
	          type: "POST",
	          headers: {"X-CSRFToken": $.cookie('csrftoken')},  	// 从Cookie取csrf_token,并设置ajax请求头
	          data: {"username": "Q1mi", "password": 123456},
	          success: function (data) {
	            console.log(data);
	          }
        })
    })

方式三:模板语法获得{{ csrf_token}}
	$("#btn1").on('click', function (){
        $.ajax({
            url: '',
            type: 'POST',
            data: {
                "user": "mimi",
                "pwd": "123",
                "csrfmiddlewaretoken": "{{ csrf_token }}"
                    },
            success: function (data) {
                console.log(data)
                }
	    })
    })

Django内置序列化

serializers:将ORM得到的对象序列化
导入:from django.core import serializers
实例:
	user_list = models.User.objects.all()				# 得到所有对象
	res = serializers.serialize('json', user_list)		# 序列化成json数据,第一个参数表示想序列化成的数据,第二个参数表示需要序列化的对象
	return HttpResponse(res)							# 返回数据

分页器

计算页数
	divmod(总数据, 每页的数据)
	得到一个元祖第一位为整数部分,第二个为余数部分,余数不为0,第一位数加一就是页数,余数为0第一位数就是页数
	>>> divmod(101, 10)
	(10, 1)					# 11页

定义分页器类
	class Pagination(object):
    	def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
	        """
	        封装分页相关数据
	        :param current_page: 当前页
	        :param all_count:    数据库中的数据总条数
	        :param per_page_num: 每页显示的数据条数
	        :param pager_count:  最多显示的页码个数
	        """
	        try:
	            current_page = int(current_page)
	        except Exception as e:
	            current_page = 1
	
	        if current_page < 1:
	            current_page = 1
	
	        self.current_page = current_page
	
	        self.all_count = all_count
	        self.per_page_num = per_page_num
	
	        # 总页码
	        all_pager, tmp = divmod(all_count, per_page_num)
	        if tmp:
	            all_pager += 1
	        self.all_pager = all_pager
	
	        self.pager_count = pager_count
	        self.pager_count_half = int((pager_count - 1) / 2)
	
	    @property
	    def start(self):
	        return (self.current_page - 1) * self.per_page_num
	
	    @property
	    def end(self):
	        return self.current_page * self.per_page_num
	
	    def page_html(self):
	        # 如果总页码 < 11个:
	        if self.all_pager <= self.pager_count:
	            pager_start = 1
	            pager_end = self.all_pager + 1
	        # 总页码  > 11
	        else:
	            # 当前页如果<=页面上最多显示11/2个页码
	            if self.current_page <= self.pager_count_half:
	                pager_start = 1
	                pager_end = self.pager_count + 1
	
	            # 当前页大于5
	            else:
	                # 页码翻到最后
	                if (self.current_page + self.pager_count_half) > self.all_pager:
	                    pager_end = self.all_pager + 1
	                    pager_start = self.all_pager - self.pager_count + 1
	                else:
	                    pager_start = self.current_page - self.pager_count_half
	                    pager_end = self.current_page + self.pager_count_half + 1
	
	        page_html_list = []
	        # 添加前面的nav和ul标签
	        page_html_list.append('''
	                    <nav aria-label='Page navigation>'
	                    <ul class='pagination'>
	                ''')
	        first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
	        page_html_list.append(first_page)
	
	        if self.current_page <= 1:
	            prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
	        else:
	            prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)
	
	        page_html_list.append(prev_page)
	
	        for i in range(pager_start, pager_end):
	            if i == self.current_page:
	                temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
	            else:
	                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
	            page_html_list.append(temp)
	
	        if self.current_page >= self.all_pager:
	            next_page = '<li class="disabled"><a href="#">下一页</a></li>'
	        else:
	            next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
	        page_html_list.append(next_page)
	
	        last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
	        page_html_list.append(last_page)
	        # 尾部添加标签
	        page_html_list.append('''
	                                           </nav>
	                                           </ul>
	                                       ''')
	        return ''.join(page_html_list)

views.py
	def get_book(request):
	   book_list = models.Book.objects.all()
	   current_page = request.GET.get("page",1)
	   all_count = book_list.count()
	   page_obj = Pagination(current_page=current_page,all_count=all_count,per_page_num=10)
	   page_queryset = book_list[page_obj.start:page_obj.end]
	   return render(request,'booklist.html',locals())

HTML
	<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            {% for book in page_queryset %}
            <p>{{ book.title }}</p>
            {% endfor %}
            {{ page_obj.page_html|safe }}
        </div>
    </div>
</div>

Form组件

对页面进行初始化,生产HTML标签,对用户提交的数据进行校验

导入:form django import forms

定义Form类
class MyForm(forms.Form):
    name = forms.CharField(label='用户名')
    pwd = forms.CharField(label='密码')

	# 重写init方法批量添加样式
	def __init__(self, *args, **kwargs):
		super(MyForm, self).__init__(*args, **kwargs)
		for field in iter(self.fields):
			self.fields[field].widget.attrs.update({"class":"form-control"})		# 给每个字段添加样式

HTML书写

方式一:通过form对象的as_p方法
	<form action="" method="post">
		{% csrf_token %}
		{{ form_obj.as_p }}
		<input type="submit">
	</form>

方法二:手动获取form对象的字段
	<form action="" method="post">
		{% csrf_token %}
		<div>
			<label for="{{ form_obj.name.id_for_label }}">{{ form_obj.name.label }}</label>	
			{{ form_obj.name }} <span>{{ form_obj.name.errors.0 }}</span>
		</div>
		<div>
			<label for="{{ form_obj.pwd.id_for_label }}">{{ form_obj.pwd.label }}</label>
			{{ form_obj.pwd }} <span>{{ form_obj.pwd.errors.0 }}</span>
		</div>
		<input type="submit">
	</form>
		
方式三:用for循环展示所有字段
	<form action="" method="post">
		{% csrf_token %}
		{% for field in form_obj %}
			<div>
			<label for="{{ field.id_for_label }}">{{field.label}}</label>
			{{field}} <span>{{ field.errors.0 }}</span>
			</div>
		{% endfor %}
		<input type="submit">
	</form>

views验证

def test(request):
    form_obj = MyForm()														# 实例化form类
    if request.method == 'POST':
        form_obj = MyForm(request.POST)										# 实力换并将POST获得的参数传进去校验
        if form_obj.is_valid():												# obj.is_valid获得校验结果
            data = form_obj.cleaned_data									# 校验的数据都在cleaned_data内
            return HttpResponse('OK')
        else:
            errors = form_obj.errors										# 错误信息都在errors里
    return render(request, 'test.html', {"form_obj": form_obj})	

常用字段

字段通用属性
	1、required:当为True时,不允许为空,反之允许
	2、label:用于生成Label标签或显示内容
	3、initial:初始值,input框里的初始值
	4、help_text:帮助信息(在标签旁边显示)
	5、disabled:当为True时,不允许编辑,反之不允许
	6、error_messages:重写错误信息,一个字典
		 error_messages={
		 "required":"不能为空",
		 "invalid":"格式错误",
		 "min_length""用户名最短3位",
		 }
		
	7、widget:HTML插件
			widget的通用属性:
				attrs:给生成的标签添加属性,传值字典,一个键值对表示一个属性
			TextInput:文本输入框
			EmailInput:邮箱输入框
			PasswordInput:密码隐藏
				pwd = forms.CharField(
						label='密码',
						widget=forms.widgets.PasswordInput())
			
			单选:
				Select:单选,下拉框
				RadioSelect:单选,圆点
				CheckboxInput:单选,方框
			
			多选:
				SelectMultiple:多选,下拉框
				CheckboxSelectMultiple:多选,方框
			
			实例:
				gender = forms.ChoiceField(
						label='性别',
						choices=((0, '男'), (1, '女')),
						widget=forms.widgets.RadioSelect())		
	8、validator:验证器,对字段进行校验
		RegexValidator
						
CharField:字符串字段
	min_length:最小长度,输入数据的最小长度
	max_length:最大长度,输入数据的最大长度
	strip:当为True时移除用户输入的空白,反之不移除
	
IntegerField:整数字段
	max_value:最大值
	min_value:最小值

DecimalField:小数字段
	max_value:最大值
	min_value:最小值

ChoiceField:单选字段
	choices:选项,如:((0, '男'), (1, '女'))

MultipleChoiceField:多选字段
	choice:选项

DateField:日期字段,格式:Y-M-D

TimeField:时间字段,格式:H:M

DateTimeField:时间日期字段,格式:Y-M-D H:M

EmailField:邮箱字段

FileField:文件字段

BooleanField:布尔字段

钩子函数

局部钩子
在Form类中定义clean_字段名()的方法,可以实现对特定字段进行校验,Form组件获得的值都在cleaned_data里
class MyForm(forms.Form):
    name = forms.CharField(min_length=5,
                           label='用户名',
                           error_messages={'required': '不能为空',
                                           'invalid': '格式错误',
                                           'min_length': '用户名最短5位'},
                           widget=forms.widgets.TextInput(attrs={"class": "form-control"}))		# 给标签添加类form-control
                           
    pwd = forms.CharField(label='sss', widget=forms.widgets.PasswordInput())

    def clean_name(self):																		# 定义局部钩子函数
        value = self.cleaned_data.get("name")													# 从cleaned_data内取出name的值
        if '666' not in value:																	# 校验数据
            raise forms.ValidationError('没有666不行的')											# 制造报错
        else:
            return value																		# 将取出的值放回
全局钩子
在Form类中定义clean()方法,可以实现全局校验
class MyForm(forms.Form):
    name = forms.CharField(
        min_length=5,
        error_messages={
            'required': '不能为空',
            'min_length': '最短5位',
            "invalid": '格式错误'},
        widget=forms.widgets.TextInput(attrs={'class': 'form-control'}))

    pwd = forms.CharField(
        min_length=5,
        widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'}, render_value=True))
        
    comfire_pwd = forms.CharField(
        min_length=5,
        widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'}, render_value=True))

    def clean(self):													# 定义全局钩子函数
        pwd = self.cleaned_data.get('pwd')								# 取出数据
        comfire_pwd = self.cleaned_data.get('comfire_pwd')
        if pwd == comfire_pwd:											# 校验数据
            return self.cleaned_data
        else:
            self.add_error('comfire_pwd', '密码不一致')					# 添加报错
            raise forms.ValidationError('密码不一致')

ModelForm组件

class BookForm(forms.ModelForm):
	
	class Meta:
		model = models.Bool
		fields = "__all__"
		labels {
			"title":"书名",
			"price":"价格"
			}
		widgets = {
			"password": forms.widgets.PasswordInput()
			}

class Meta常用参数
	model:对应的Model中的类
	fields:字段,如果是__all__,就表示列出所有字段
	exclude:排除的字段
	labels:提示信息
	help_texts:帮助提示信息
	widgets:自定义插件
	error_messages:自定义错误信息

验证
	与普通的Form表单验证类似,也可以使用钩子函数实现自定义的校验规则

save()方法
	创建新的实例
	form_obj = BookForm(request.POST)						# 根据POST数据创建一个新的form对象
	new_book = form_obj.save()								# 创建新的图书对象
	
	基于一个对象创建form对象
	edit_obj = models.Book.objects.get(id=1)
	from_obj = BookForm(request.POST, instance=edit_obj)	# 根据POST提交的数据更新数据对象
	form_obj.save()											# 更新数据对象
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值