Django基础06-day21

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django基础06-day21相关的知识,希望对你有一定的参考价值。

写在前面



上课第21天,打卡:

    Don‘t try so hard, the best things come when you least expect them to.



 

 

技术分享
  1 s17day21
  2 内容回顾:
  3     FBV,CBV
  4     序列化
  5         - Django内置
  6         - json.dumps(xxx,cls=)
  7     Form验证
  8         -  9             class LoginForm(Form):
 10                 user = fields.CharField(...)
 11                 email = fields.EmailField(...)
 12                 email = fields.ChoiceField(
 13                     choices=[()..]
 14                 )
 15         - 添加用户: GET
 16             form = LoginForm()
 17             
 18             {{form.user}}    <input type=text name=user />
 19             
 20             等待用户输入内容,提交
 21             
 22         - 添加用户: POST
 23             form = LoginForm(data=request.POST)
 24             form.is_valid()
 25             form.cleaned_data
 26             form.errors
 27             
 28         - 修改用户: GET   /edit/9
 29             obj = models.User.objects.get(id=9)
 30             
 31             form = LoginForm(initial={user:obj.user})
 32             
 33             {{form.user}}    <input type=text name=user value=数据库中的用户名 />
 34             
 35             等待用户输入内容,提交
 36             
 37         - 修改用户: POST   /edit/9
 38             form = LoginForm(data=request.POST)
 39             form.is_valid()
 40             form.cleaned_data
 41                 models.User.objects.filter(id=9).update(**form.cleaned_data)
 42             form.errors
 43             
 44         - 补充:可以显示select,但是数据无法实时更新
 45             class LoginForm(Form):
 46                 user = fields.CharField(...)
 47                 email = fields.EmailField(...)
 48                 hobby = fields.ChoiceField(
 49                     choices=[()..]
 50                 )
 51                 
 52                 def __init__(self,*args,**kwargs):
 53                     super..
 54                     self.fields[hobby].choices = ....
 55             
 56 
 57 今日内容概要:
 58 
 59     - Form验证(二)
 60         - 自定义验证规则
 61             a. 对象
 62                 # phone = fields.CharField(validators=[RegexValidator(r‘^[0-9]+$‘, ‘请输入数字‘),])
 63             b. 函数
 64             c. clean_字段名称 方法
 65                     def clean_phone(self):
 66                     """
 67 
 68                     :return: 必须有返回值,
 69                     """
 70                     # 去取用户提交的值:可能是错误的,可能是正确
 71                     value = self.cleaned_data[phone]
 72                     mobile_re = re.compile(r^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$)
 73                     if not mobile_re.match(value):
 74                         raise ValidationError(手机号码格式错误)
 75 
 76                     if models.UserInfo.objects.filter(phone=value).count():
 77                         raise ValidationError(手机号码已经存在)
 78 
 79                     return value
 80                 **********方法中只能取当前字段的值 **********
 81         - 验证规则执行顺序
 82             - 第一个字段的正则,钩子函数(方法中只能取当前字段的值)
 83             - 第二个字段的正则,钩子函数
 84         - 整体验证: clean,必须有返回值,   给指定字段添加错误信息
 85             class RegisterForm(Form):
 86                 name = fields.CharField()
 87                 email = fields.EmailField()
 88                 phone = fields.CharField()
 89                 pwd = fields.CharField()
 90                 pwd_confirm = fields.CharField()
 91 
 92                 def clean(self):
 93                     pwd = self.cleaned_data[pwd]
 94                     pwd_confirm = self.cleaned_data[pwd_confirm]
 95                     if pwd == pwd_confirm:
 96                         return self.cleaned_data
 97                     else:
 98                         from django.core.exceptions import ValidationError
 99                         # self.add_error(‘pwd‘, ValidationError(‘密码输入不一致‘))
100                         self.add_error(pwd_confirm, ValidationError(密码输入不一致))
101                         return self.cleaned_data
102             
103         - 常用插件
104             
105             class RegisterForm(Form):
106                 name = fields.CharField(
107                     widget=widgets.TextInput(attrs={class: c1})
108                 )
109                 email = fields.EmailField(
110                     widget=widgets.EmailInput(attrs={class:c1})
111                 )
112                 phone = fields.CharField(
113                     widget=widgets.Textarea(attrs={class:c1})
114                 )
115                 pwd = fields.CharField(
116                     widget=widgets.PasswordInput(attrs={class:c1})
117                 )
118                 pwd_confirm = fields.CharField(
119                     widget=widgets.PasswordInput(attrs={class: c1})
120                 )
121                 # 单选:select
122                 # city = fields.ChoiceField(
123                 #     choices=[(0,"上海"),(1,‘北京‘)],
124                 #     widget=widgets.Select(attrs={‘class‘: ‘c1‘})
125                 # )
126                 # 多选:select
127                 # city = fields.MultipleChoiceField(
128                 #     choices=[(1,"上海"),(2,‘北京‘)],
129                 #     widget=widgets.SelectMultiple(attrs={‘class‘: ‘c1‘})
130                 # )
131                 
132                 # 单选:checkbox
133                 # city = fields.CharField(
134                 #     widget=widgets.CheckboxInput()
135                 # )
136 
137                 # 多选:checkbox
138                 # city = fields.MultipleChoiceField(
139                 #     choices=((1, ‘上海‘), (2, ‘北京‘),),
140                 #     widget=widgets.CheckboxSelectMultiple
141                 # )
142 
143                 # 单选:radio
144                 # city = fields.CharField(
145                 #     initial=2,
146                 #     widget=widgets.Radioselect(choices=((1,‘上海‘),(2,‘北京‘),))
147                 # )
148         
149             注意:写默认值时,多选值对应列表
150             
151             # form = RegisterForm(initial={‘city‘:[1,2],‘name‘:‘alex‘})
152             form = RegisterForm()
153         
154       参考博客:http://www.cnblogs.com/wupeiqi/articles/6144178.html 
155 
156     - 中间件
157         - 中间件执行时机:请求到来,请求返回时
158         - 中间件是一个类:
159                 def process_request(self,request):
160                     print(m2.process_request)
161 
162                 def process_response(self,request, response):
163                     print(m2.prcess_response)
164                     return response
165                     
166         - 应用:
167             - 请求日志
168             - 用户登录认证
169     
170     - 缓存
171         - 配置
172             - 开发调试
173             - 内存中 全局变量
174             - 文件中
175             - 数据库
176             - Memcached
177         - 使用
178             - 全局
179                 MIDDLEWARE = [
180                     django.middleware.cache.UpdateCacheMiddleware,
181                     # 其他中间件
182                     django.middleware.cache.FetchFromCacheMiddleware,
183                 ]
184             - 视图函数
185             
186                 from django.views.decorators.cache import cache_page
187 
188                 @cache_page(10)
189                 def test1(request):
190                     import time
191                     ctime = time.time()
192                     return render(request,test1.html,{ctime:ctime})
193             - 局部模板
194                 {% load cache %}
195                 <!DOCTYPE html>
196                 <html lang="en">
197                 <head>
198                     <meta charset="UTF-8">
199                     <title>Title</title>
200                 </head>
201                 <body>
202                     <h1>TEST1 -> {{ ctime }}</h1>
203 
204 
205                     {% cache 10 "asdfasdfasdf" %}
206                         <h1>TEST1 -> {{ ctime }}</h1>
207                     {% endcache %}
208                 </body>
209                 </html>
210         
211     - 信号
212         问题:如何在数据库中做增加操作时,记录日志
213       参考博客:http://www.cnblogs.com/wupeiqi/articles/5246483.html 
214 
215     - Admin
216       参考博客:http://www.cnblogs.com/wupeiqi/articles/7444717.html 
217 
218     - ModelForm(下周讲)
219       参考博客:http://www.cnblogs.com/wupeiqi/articles/6229414.html 
220 
221     - BBS项目练习:
222         地址:http://dig.chouti.com/ 
223         要求:
224             表结构设计
225             功能开发:
226                 页面样式和布局
227                 文章列表(分页)
228                 点赞:思路,发送ajax请求:
229                             - 判断:
230                                 已经存在: like表中删除一条记录,new中like_count,自减1
231                                 不存在: like表中天剑一条记录,new中like_count,自加1
232                             - 登录之后才能点赞
233                 
234                 发布文章(上传图片)
235                     1. 根据URL,自动获取标题和摘要
236                        pip3 install beautifulsoup4
237                        pip3 install requests
238                        点击:
239                             发送Ajax请求,将 http://music.163.com/#/song?id=188057 发送到后台
240                             def get_title_summary(request):
241                                 url = request.POST.get(url)
242                                 import requests
243                                 from bs4 import BeautifulSoup
244 
245 
246                                 response = requests.get(http://music.163.com/#/song?id=188057)
247                                 soup = BeautifulSoup(response.text,html.parser)
248                                 title = soup.find(title).text
249                                 desc = soup.find(meta,attrs={name: description}).get(content)
250                                 print(title)
251                                 print(desc)
252                                 data = {title:title,desc:decc}
253                                 return HttpResponse(json.dumps(data))
254                     2. 基于Ajax实现图片上传    
255                         隐藏的Input框,放置头像路径
256                     
257                 评论
258                 
武Sir - 笔记

 

Django 中间件处理流程:

技术分享

 

################
# 2017-09-17 - 课上笔记
################


day21课上笔记 .. 2017-09-17


课前回顾:
	- Form组件验证
		参考:http://www.cnblogs.com/wupeiqi/articles/6144178.html
		- 先写好类:
			class LoginForm(Form):
				user = fields.CharField(...)
				emial = fields.EmailField(...)
				...
		- 使用之添加用户
			- 先实例化一个对象:form = LoginForm()
				前端:{{ form.user }} -> <input type=‘text‘ name=‘user‘ />
			- 等待用户输入,提交
			-添加,POST
				form = LoginForm(data=request.POST)
				form.is_valid()
				form.cleaned_data
				form.errors


		"""这里需要再练习下!!!"""
		- 修改用户:先发一个GET请求,/edit_user/user_id
			obj = models.UserInfo.objects.get(id=user_id)
			form = LoginForm(initial={‘user‘:obj.user})

			{{form.user}} -> <input type=‘text‘ name=‘user‘ value=‘数据库中的用户名‘ />

			等待用户输入内容,提交

		- 修改用户:再发一个POST请求,/edit_user/user_id
			form = LoginForm(data=request.POST)
			form.is_valid()
			form.cleaned_data:
				models.UserInfo.objects.filter(id=user_id).update(**cleaned_data)


		- 下拉框无法自动刷新的问题:
			‘‘‘
				dp_id = fields.ChoiceField(
			        required=True,
			        choices = [],
			    )
			    def __init__(self, *args, **kwargs):
			        # 找到类中的所有静态字段,然后拷贝并且赋值给 self.fields
			        super(UserInfoForm,self).__init__(*args, **kwargs)
			        self.fields[‘dp_id‘].choices = models.Depart.objects.values_list(‘id‘, ‘title‘)
			‘‘‘



	- FBV & CBV(用到了反射)
	- 序列化
		- Django内置的 serializers
		- json.dumps(xxx,cls=JsonCustomEncoder)
			- JsonCustomEncoder 在这个函数里自定义一些规则






day21今日内容
	- Form组件进行验证之进阶
	‘‘‘
		import re
		from django.forms import Form
		from django.forms import fields
		from django.forms import widgets
		from app01 import models
		from django.core.validators import RegexValidator
		from django.core.exceptions import ValidationError
	‘‘‘
		- 自定义验证规则方式一:使用RegexValidator对象
			‘‘‘
				自定义验证规则方式一:通过RegexValidator对象
			    phone = fields.CharField(
			        required=True,
			        validators=[RegexValidator(r‘^[0-9]+$‘, ‘请输入数字‘), RegexValidator(r‘^159[0-9]+$‘, ‘数字必须以159开头‘)],
			    )
			‘‘‘
		- 自定义验证规则方式二:自定义验证函数
			‘‘‘
				# 自定义验证规则函数,优点是可以有数据库操作
				def phone_validate(value):
				    mobile_re = re.compile(r‘^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$‘)
				    if not mobile_re.match(value):
				        raise ValidationError(‘手机号码格式错误‘)
				    if models.UserInfo.objects.filter(phone=value).count():
			            raise ValidationError(‘手机号码已经存在‘)

			    phone = fields.CharField(validators=[phone_validate,]) 
			‘‘‘
		- 自定义验证规则方式三:在当前类中使用钩子函数,函数名称必须符合 "clean_字段名称"
			‘‘‘
				phone = fields.CharField()
			    # 钩子方法
			    def clean_phone(self,):
			        """
			        只能取当前字段的值,切勿取其他的值
			        必须得有返回值
			        :return: 
			        """
			        # 需要要验证的值,自己写正则进行验证
			        # 去取用户提交的值
			        value = self.cleaned_data[‘phone‘]
			        mobile_re = re.compile(r‘^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$‘)
			        if not mobile_re.match(value):
			            raise ValidationError(‘手机号码格式错误‘)
			        if models.UserInfo.objects.filter(phone=value).count():
			            raise ValidationError(‘手机号码已经存在‘)
			        return value
			‘‘‘


		- 是否可以共存?   可以
		- 顺序是怎样的?
		# 看源码		

		1. form.is_valid()
		2. self.errors
		3. self.full_clean()
			- self._clean_fields()  # 即对 self.fields 进行循环验证,依次验证每一个字段:
				先执行自己字段的正则,再执行钩子函数
				先执行自己字段的正则,再执行钩子函数
				...

		    - self._clean_form()    # 字段都验证完后,再对整个form进行验证:
		    	- self.clean()
		    	- self.add_error(self, field, error)  # 如果有错误则把错误加到add_error里

		‘‘‘
			class RegisterForm(Form):
			    name = fields.CharField(
			        widget=widgets.TextInput(attrs={‘class‘: ‘c1‘})
			    )
			    email = fields.EmailField(
			        widget=widgets.EmailInput(attrs={‘class‘:‘c1‘})
			    )
			    phone = fields.CharField(
			        widget=widgets.Textarea(attrs={‘class‘:‘c1‘})
			    )
			    pwd = fields.CharField(
			        widget=widgets.PasswordInput(attrs={‘class‘:‘c1‘})
			    )
			    pwd_confirm = fields.CharField(
			        widget=widgets.PasswordInput(attrs={‘class‘: ‘c1‘})
			    )
			    
			    # 写在RegisterForm类里作用于 RegisterForm
			    # 以用户注册为例:用户输入密码,再次输入密码,这时候需要对两次密码进行比对
			    def clean(self):
			        pwd = self.cleaned_data[‘pwd‘]
			        pwd_confirm = self.cleaned_data[‘pwd_confirm‘]
			        if pwd == pwd_confirm:
			            return self.cleaned_data
			        else:
			            from django.core.exceptions import ValidationError
			            self.add_error(‘pwd‘, ValidationError(‘密码输入不一致‘))
			            self.add_error(‘pwd_confirm‘, ValidationError(‘密码输入不一致‘))
			            return self.cleaned_data
		‘‘‘



		    - self._post_clean()  	# 等同于 self._clean_form() ,可忽略


		‘‘‘
		# 源代码如下:
			def is_valid(self):
		        """
		        Returns True if the form has no errors. Otherwise, False. If errors are
		        being ignored, returns False.
		        """
		        return self.is_bound and not self.errors

			@property
		    def errors(self):
		        "Returns an ErrorDict for the data provided for the form"
		        if self._errors is None:
		            self.full_clean()
		        return self._errors

	        def full_clean(self):
		        """
		        Cleans all of self.data and populates self._errors and
		        self.cleaned_data.
		        """
		        self._errors = ErrorDict()
		        if not self.is_bound:  # Stop further processing.
		            return
		        self.cleaned_data = {}
		        # If the form is permitted to be empty, and none of the form data has
		        # changed from the initial data, short circuit any validation.
		        if self.empty_permitted and not self.has_changed():
		            return

		        self._clean_fields()
		        self._clean_form()
		        self._post_clean()

			def _clean_fields(self):
		        for name, field in self.fields.items():
		            # value_from_datadict() gets the data from the data dictionaries.
		            # Each widget type knows how to retrieve its own data, because some
		            # widgets split data over several HTML fields.
		            if field.disabled:
		                value = self.get_initial_for_field(field, name)
		            else:
		                value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
		            try:
		                if isinstance(field, FileField):
		                    initial = self.get_initial_for_field(field, name)
		                    value = field.clean(value, initial)
		                else:
		                    value = field.clean(value)
		                self.cleaned_data[name] = value
		                if hasattr(self, ‘clean_%s‘ % name):
		                    value = getattr(self, ‘clean_%s‘ % name)()
		                    self.cleaned_data[name] = value
		            except ValidationError as e:
		                self.add_error(name, e)

		    def _clean_form(self):
		        try:
		            cleaned_data = self.clean()
		        except ValidationError as e:
		            self.add_error(None, e)
		        else:
		            if cleaned_data is not None:
		                self.cleaned_data = cleaned_data

		    def clean(self):
		        """
		        Hook for doing any extra form-wide cleaning after Field.clean() has been
		        called on every field. Any ValidationError raised by this method will
		        not be associated with a particular field; it will have a special-case
		        association with the field named ‘__all__‘.
		        """
		        return self.cleaned_data
		‘‘‘

		# 添加新用户demo
		‘‘‘
		# models.py
			class Depart(models.Model):
			    """部门表"""
			    title = models.CharField(max_length=32) # 数据库里就是string类型

			    class Meta:
			        verbose_name_plural = "部门表"

			class UserInfo(models.Model):
			    """用户表"""
			    name = models.CharField(max_length=32)
			    email = models.CharField(max_length=32)
			    phone = models.CharField(max_length=32)
			    pwd = models.CharField(max_length=64)
			    dp = models.ForeignKey(to=‘Depart‘,to_field=‘id‘)


		# forms.py
			import re
			from django.forms import Form
			from django.forms import fields
			from django.forms import widgets
			from app01 import models
			from django.core.validators import RegexValidator
			from django.core.exceptions import ValidationError

			class UserInfoForm(Form):
			    name = fields.CharField(
			        required=True,
			        min_length=2,
			        max_length=12,
			        error_messages={‘required‘: ‘用户名不能为空‘},
			        widget=widgets.TextInput(attrs={‘class‘: ‘form-control‘})
			    )   # 用户提交数据是字符串
			    pwd = fields.CharField(
			        required=True,
			        min_length=2,
			        max_length=12,
			        error_messages={‘required‘: ‘密码不能为空‘},
			        widget=widgets.PasswordInput(attrs={‘class‘: ‘form-control‘})
			    )
			    pwd_confirm = fields.CharField(
			        required=True,
			        min_length=2,
			        max_length=12,
			        error_messages={‘required‘: ‘确认密码不能为空‘},
			        widget=widgets.PasswordInput(attrs={‘class‘: ‘form-control‘})
			    )
			    email = fields.EmailField(
			        required=True,
			        error_messages={‘required‘: ‘邮箱不能为空‘, ‘invalid‘: ‘邮箱格式错误‘},
			        widget=widgets.TextInput(attrs={‘class‘: ‘form-control‘})
			    )
			    

			    # 自定义验证规则方式三:在当前类的方法中:clean_字段名称
			    dp_id = fields.ChoiceField(
			        choices=[],
			        error_messages={‘required‘: ‘请选择归属部门‘},
			        widget=widgets.Select(attrs={‘class‘: ‘form-control‘})
			    )
			    phone = fields.CharField(error_messages={‘required‘: ‘手机号不能为空‘})
			    # 钩子方法
			    def clean_phone(self,):
			        """
			        只能取当前字段的值,切勿取其他的值
			        必须得有返回值
			        :return: 
			        """
			        # 需要要验证的值,自己写正则进行验证
			        # 去取用户提交的值
			        value = self.cleaned_data[‘phone‘]
			        mobile_re = re.compile(r‘^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$‘)
			        if not mobile_re.match(value):
			            raise ValidationError(‘手机号码格式错误‘)
			        if models.UserInfo.objects.filter(phone=value).count():
			            raise ValidationError(‘手机号码已经存在‘)
			        return value

			    def __init__(self, *args, **kwargs):
			        # 找到类中的所有静态字段,然后拷贝并且赋值给 self.fields
			        super(UserInfoForm,self).__init__(*args, **kwargs)
			        # self.fields[‘dp_id‘].chioces = models.Depart.objects.all()
			        self.fields[‘dp_id‘].choices = models.Depart.objects.values_list(‘id‘, ‘title‘)

			    def clean(self):
			        print(self.cleaned_data,‘=====================‘)
			        pwd = self.cleaned_data.get(‘pwd‘)
			        pwd_confirm = self.cleaned_data.get(‘pwd_confirm‘)
			        if pwd == pwd_confirm:
			            return self.cleaned_data
			        else:
			            from django.core.exceptions import ValidationError
			            # self.add_error(‘pwd‘, ValidationError(‘密码输入不一致‘))
			            self.add_error(‘pwd_confirm‘, ValidationError(‘密码输入不一致‘))
			            return self.cleaned_data

		# add_user.html
			<form method="POST" novalidate>
		        {% csrf_token %}
		        <p> 用户名:{{ form.name }} {{ form.errors.name.0 }} </p>
		        <p> 密码:{{ form.pwd }} {{ form.errors.pwd.0 }} </p>
		        <p> 确认密码:{{ form.pwd_confirm }} {{ form.errors.pwd_confirm.0 }} </p>
		        <p> 邮箱:{{ form.email }} {{ form.errors.email.0 }}</p>
		        <p> 手机:{{ form.phone }} {{ form.errors.phone.0 }}</p>
		        <p> 部门:{{ form.dp_id }} {{ form.errors.dp_id.0 }}</p>
		        <input type="submit" value="提交" />
		    </form>

		# views.py
			def add_user(request):
			    if ‘GET‘ == request.method:
			        form = UserInfoForm()
			        return render(request, ‘add_user.html‘, {‘form‘: form})
			    else:
			        form = UserInfoForm(data=request.POST)
			        if form.is_valid():
			            form.cleaned_data.pop(‘pwd_confirm‘)
			            models.UserInfo.objects.create(**form.cleaned_data)
			            return redirect(‘/userinfo/‘)
			        return render(request, ‘add_user.html‘, {‘form‘: form})
		‘‘‘




		- 常用插件
			参考:http://www.cnblogs.com/wupeiqi/articles/6144178.html

			from django.forms import widgets

			# 单选:select
		    # city = fields.ChoiceField(
		    #     choices=[(0,"上海"),(1,‘北京‘)],
		    #     widget=widgets.Select(attrs={‘class‘: ‘c1‘})
		    # )
		    # 多选:select
		    # city = fields.MultipleChoiceField(
		    #     choices=[(1,"上海"),(2,‘北京‘)],
		    #     widget=widgets.SelectMultiple(attrs={‘class‘: ‘c1‘})
		    # )

		    # 单选:checkbox
		    # city = fields.CharField(
		    #     widget=widgets.CheckboxInput()
		    # )

		    # 多选:checkbox
		    # city = fields.MultipleChoiceField(
		    #     choices=((1, ‘上海‘), (2, ‘北京‘),),
		    #     widget=widgets.CheckboxSelectMultiple
		    # )

		    # 单选:radio
		    # city = fields.CharField(
		    #     initial=2,
		    #     widget=widgets.RadioSelect(choices=((1,‘上海‘),(2,‘北京‘),))
		    # )

		- 初始化的时候赋值,包括单值和多值

		注意:写默认值时,多选的值对应一个列表



	- 中间件
		- 中间件的执行时机:请求到来和请求返回时执行
		- 中间件就是一个类,里面有2个方法(也可以没有):
			process_request(self,request)
				默认不写return,这本质上是 return None
			process_reponse(self,request,response)
				必须要写 return response

			另外还有:
			# 依次处理完所有request之后就进行路由匹配,然后再跳转到开头依次进行process_view函数处理
			process_view(self, request, callback, callback_args, callback_kwargs)

			# 捕获异常,自定义返回页面
			process_exception(self,request,exception)


		# Django中间件处理流程
		"""
			1. 循环中间件MIDDLEWARE列表里的中间件,依次执行每个中间件类的process_request(self,request)
			2. 进行路由匹配,拿到对应的视图函数
			3. 再次循环中间件MIDDLEWARE列表里的中间件,再从头依次执行每个中间件类的process_view(self, request, callback, callback_args, callback_kwargs)
			4. 执行对应的视图函数
			5. 逆序循环MIDDLEWARE列表里的中间件,依次执行每个中间件类的process_exception(self,request,exception)
			6. 再次逆序循环MIDDLEWARE列表里的中间件,依次执行每个中间件类的process_template_response(...)
			7. 再次逆序循环MIDDLEWARE列表里的中间件,依次执行每个中间件类的process_reponse(self,request,response)
		"""


		- 应用:
			- 记录访问日志
			- 判断用户是否登录

		# 中间件要继承 MiddlewareMixin类
		‘‘‘
		class MiddlewareMixin(object):
		    def __init__(self, get_response=None):
		        self.get_response = get_response
		        super(MiddlewareMixin, self).__init__()

		    def __call__(self, request):
		        response = None
		        if hasattr(self, ‘process_request‘):
		            response = self.process_request(request)
		        if not response:
		            response = self.get_response(request)
		        if hasattr(self, ‘process_response‘):
		            response = self.process_response(request, response)
		        return response
		‘‘‘



		‘‘‘
		HttpRequest.META

		一个标准的Python 字典,包含所有的HTTP 头部。具体的头部信息取决于客户端和服务器,下面是一些示例:

		CONTENT_LENGTH 			—— 请求的正文的长度(是一个字符串)。
		CONTENT_TYPE 			—— 请求的正文的MIME 类型。
		HTTP_ACCEPT 			—— 响应可接收的Content-Type。
		HTTP_ACCEPT_ENCODING	—— 响应可接收的编码。
		HTTP_ACCEPT_LANGUAGE 	—— 响应可接收的语言。
		HTTP_HOST 				—— 客服端发送的HTTP Host 头部。
		HTTP_REFERER 			—— Referring 页面。
		HTTP_USER_AGENT 		—— 客户端的user-agent 字符串。
		QUERY_STRING 			—— 单个字符串形式的查询字符串(未解析过的形式)。
		REMOTE_ADDR 			—— 客户端的IP 地址。
		REMOTE_HOST 			—— 客户端的主机名。
		REMOTE_USER 			—— 服务器认证后的用户。
		REQUEST_METHOD			—— 一个字符串,例如"GET" 或"POST"。
		SERVER_NAME 			—— 服务器的主机名。
		SERVER_PORT 			—— 服务器的端口(是一个字符串)。
		‘‘‘

		# 中间件示例1
		‘‘‘
		# settings.py
		MIDDLEWARE = [
			...
		    ‘middle.middleware.my_middleware1‘,
		    ‘middle.middleware.my_middleware2‘,
		]



		# ..\\middle\\middleware.py
		from django.shortcuts import render,HttpResponse,redirect
		from django.utils.deprecation import MiddlewareMixin

		class my_middleware1(MiddlewareMixin):
		    def process_request(self,request):
		        print(‘my_middleware1.process_request...‘)
		        print(request.path)
		        print(request.path_info)
		        print(request.method)
		        print(request.META[‘REMOTE_ADDR‘])
		        print(request.META[‘REMOTE_HOST‘])
		        print(request.META[‘REQUEST_METHOD‘])
		        print(request.META[‘HTTP_USER_AGENT‘])
		        print(request.META[‘HTTP_HOST‘])

		    def process_response(self,request,response):
		        print(‘my_middleware1.process_response...‘)
		        return response


		class my_middleware2(MiddlewareMixin):
		    def process_request(self,request):
		        print(‘my_middleware2.process_request...‘)

		    def process_response(self,request,response):
		        print(‘my_middleware2.process_response...‘)
		        return response
		‘‘‘
		
		# 中间件示例2 : 代替登录验证装饰器
		‘‘‘
		class my_middleware2(MiddlewareMixin):
		    def process_request(self,request):
		        if ‘/login/‘ == request.path_info:
		            return None
		        user_info = request.session.get(‘user_info‘)
		        if not user_info:
		            return redirect(‘/login/‘)

		    def process_response(self,request,response):
		        print(‘my_middleware2.process_response...‘)
		        return response
		‘‘‘




	- Django的缓存
	参考:http://www.cnblogs.com/wupeiqi/articles/5246483.html
		- 配置(默认不支持redis)
			- 开发调试,相当于没有
			- 本机内存中
			‘‘‘
				# 此缓存将内容保存至内存的变量中
			    # 配置:
			        CACHES = {
			            ‘default‘: {
			                ‘BACKEND‘: ‘django.core.cache.backends.locmem.LocMemCache‘,
			                ‘LOCATION‘: ‘unique-snowflake‘,
			            }
			        }
			‘‘‘
			- 本地文件中
			- 数据库中
			- Memcached
		- 使用
			- 全局 
				MIDDLEWARE = [
			        ‘django.middleware.cache.UpdateCacheMiddleware‘,
			        # 其他中间件...
			        ‘django.middleware.cache.FetchFromCacheMiddleware‘,
			    ]

			    CACHE_MIDDLEWARE_SECONDS = 10 # 设置缓存时间

			- 视图函数
				 from django.views.decorators.cache import cache_page

        		@cache_page(60 * 15)
        		def xxx(request):
        			pass

			- 局部模板
				a. 引入TemplateTag
			        {% load cache %}

			    b. 使用缓存
			        {% cache 5000 缓存key %}
			            缓存内容
			        {% endcache %}






	- 信号
		参考:http://www.cnblogs.com/wupeiqi/articles/5246483.html
		Django中提供了“信号调度”,用于在框架执行操作时解耦。
		通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。

		需求:在对数据库做增加操作时,记录操作日志


		推荐把信号的注册写到 项目目录下的 __init__()函数里

	‘‘‘
	# Django内置信号

	Model signals
	    pre_init                    # django的modal执行其构造方法前,自动触发
	    post_init                   # django的modal执行其构造方法后,自动触发
	    pre_save                    # django的modal对象保存前,自动触发
	    post_save                   # django的modal对象保存后,自动触发
	    pre_delete                  # django的modal对象删除前,自动触发
	    post_delete                 # django的modal对象删除后,自动触发
	    m2m_changed                 # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
	    class_prepared              # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
	Management signals
	    pre_migrate                 # 执行migrate命令前,自动触发
	    post_migrate                # 执行migrate命令后,自动触发
	Request/response signals
	    request_started             # 请求到来前,自动触发
	    request_finished            # 请求结束后,自动触发
	    got_request_exception       # 请求异常后,自动触发
	Test signals
	    setting_changed             # 使用test测试修改配置文件时,自动触发
	    template_rendered           # 使用test测试渲染模板时,自动触发
	Database Wrappers
	    connection_created          # 创建数据库连接时,自动触发
	‘‘‘

	‘‘‘
	信号模块引入位置:
	在项目文件加下的 __init__.py 文件里引入,并注册相关操作


	信号模块引入方式:

	from django.core.signals import request_finished
	from django.core.signals import request_started
	from django.core.signals import got_request_exception

	from django.db.models.signals import class_prepared
	from django.db.models.signals import pre_init, post_init
	from django.db.models.signals import pre_save, post_save
	from django.db.models.signals import pre_delete, post_delete
	from django.db.models.signals import m2m_changed
	from django.db.models.signals import pre_migrate, post_migrate

	from django.test.signals import setting_changed
	from django.test.signals import template_rendered

	from django.db.backends.signals import connection_created

	‘‘‘


	# 信号示例:旨在对数据库执行插入数据之前和之后触发各自的操作
	‘‘‘
		from django.db.models.signals import pre_save, post_save

		def pre_save_callback(sender, **kwargs):
		    print(">>>>>>>>>>> pre_save")
		    print(sender)
		    print(kwargs)

		def post_save_callback(sender, **kwargs):
		    print("################# post_save")
		    print(sender)
		    print(kwargs)

		pre_save.connect(pre_save_callback)
		post_save.connect(post_save_callback)
	‘‘‘

	# 执行结果:
	‘‘‘
	[18/Sep/2017 22:20:32] "POST /add_user/ HTTP/1.1" 200 1268
	>>>>>>>>>>> pre_save
	<class ‘app01.models.UserInfo‘>
	{‘signal‘: <django.db.models.signals.ModelSignal object at 0x0000000002CE79E8>, ‘instance‘: <UserInfo: UserInfo object>, ‘using‘: ‘default‘, ‘raw‘: False, ‘update_fields‘: None}
	################# post_save
	<class ‘app01.models.UserInfo‘>
	{‘signal‘: <django.db.models.signals.ModelSignal object at 0x0000000002CE7A90>, ‘instance‘: <UserInfo: UserInfo object>, ‘update_fields‘: None, ‘using‘: ‘default‘, ‘created‘: True, ‘raw‘: False}
	[18/Sep/2017 22:20:49] "POST /add_user/ HTTP/1.1" 302 0
	‘‘‘



	- Admin
		Django内置的Admin是对于model中对应的数据表进行增删改查提供的组件

		# 创建超级用户
		‘‘‘
			D:\\soft\\work\\Python_17\\day21\\form_demo>python manage.py createsuperuser
			Username (leave blank to use ‘liulixin‘): root
			Email address:
			Password:
			Password (again):
			This password is too short. It must contain at least 8 characters.
			Password:
			Password (again):
			>>>>>>>>>>> pre_save
			<class ‘django.contrib.auth.models.User‘>
			{‘signal‘: <django.db.models.signals.ModelSignal object at 0x0000000002CEA7F0>, ‘using‘: ‘default‘, ‘instance‘: <User: root>, ‘
			raw‘: False, ‘update_fields‘: None}
			################# post_save
			<class ‘django.contrib.auth.models.User‘>
			{‘signal‘: <django.db.models.signals.ModelSignal object at 0x0000000002CEA898>, ‘created‘: True, ‘update_fields‘: None, ‘instan
			ce‘: <User: root>, ‘using‘: ‘default‘, ‘raw‘: False}
			Superuser created successfully.

			D:\\soft\\work\\Python_17\\day21\\form_demo>
		‘‘‘

		更多admin做好的接口参考:http://www.cnblogs.com/wupeiqi/articles/7444717.html
		Django提供的对数据库的操作,admin.py 和 models.py 配合
		‘‘‘
			class Depart(models.Model):
			    """部门表"""
			    title = models.CharField(max_length=32) # 数据库里就是string类型

			    def __str__(self):
			        return self.title

			    class Meta:
			        verbose_name_plural = "部门表"

			class UserInfo(models.Model):
			    """用户表"""
			    name = models.CharField(max_length=32)
			    # email = models.EmailField(max_length=32)
			    email = models.CharField(max_length=32)
			    phone = models.CharField(max_length=32)
			    pwd = models.CharField(max_length=64)
			    dp = models.ForeignKey(to=‘Depart‘,to_field=‘id‘)

			    def __str__(self):
			        return self.name

			    class Meta:
			        verbose_name_plural = "用户表"
		‘‘‘


		在admin.py中只需要将Mode中的某个类注册,即可在Admin中实现增删改查的功能,如:
		‘‘‘
		# admin.py
			from django.contrib import admin
			from app01 import models

			# Register your models here.

			admin.site.register(models.UserInfo)
			admin.site.register(models.Depart)
		‘‘‘

		但是,这种方式比较简单,如果想要进行更多的定制操作,需要利用ModelAdmin进行操作,如:
		‘‘‘
		# admin.py
			from django.contrib import admin
			from app01 import models

			# Register your models here.

			class DepartAdmin(admin.ModelAdmin):
			    list_display = [‘id‘,‘title‘]
			    search_fields = [‘title‘, ]
			admin.site.register(models.Depart,DepartAdmin)


			class UserInfoAdmin(admin.ModelAdmin):
			    list_display = [‘id‘,‘name‘,‘email‘,‘phone‘,‘dp‘]
			    search_fields = [‘name‘, ]
			admin.site.register(models.UserInfo,UserInfoAdmin)
		‘‘‘


	- ModelForm

	- BBS项目练习
		- 前端知识捡一下
		- 各个小功能的设计和实现






用户表
	用户名
	密码

新闻表
	标题
	简介
	点赞个数	点赞时要更新字段,Django的F实现自增1
	评论个数
	新闻类型
	发布者
	新闻图表

新闻类型表
	类型名

点赞记录表

评论记录表

  

 

以上是关于Django基础06-day21的主要内容,如果未能解决你的问题,请参考以下文章

21个常用代码片段

机器学习基础06DAY

django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE的解决办法(转)(代码片段

django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE的解决办法(转)(代码片段

Django学习笔记(下)

Django学习笔记(下)