zoukankan      html  css  js  c++  java
  • 视图层

    1. 昨日回顾

    查询数据
    	get()
    	filter()
    	all() 
    创建数据
    	create()
    	
    	user_obj = models.Userinfo(**kwargs)
    	user_obj.save()
    		
    数据的编辑与删除
    	后端如何获取前端用户想要编辑的数据对象
        1.利用get请求url后面可以携带参数的方式 将数据的主键值传递给后端
    	编辑功能的思路:获取用户想要编辑的数据对象 展示到前端页面 用户修改之后点击修改 再去修改数据库中对应的数据
    		1.方式1
            modeles.Userinfo.objects.filter(**kwargs).update()  # 批量更新
    		2.方式2  (不推荐使用 效率极低 会将每一个字段对应的值全部重写一遍)
            edit_obj = models.Userinfo.objects.filter(pk=edit_id).first()  # pk会自动帮你查找当前表的主键字段
            edit_obj.username = username
            edit_obj.password = password
            edit_obj.save()  
            
    删除
    	models.Userinfo.objects.filter(pk=delete_id).delete()
    	"""真正的数据是不会被删除的 通常都是给数据设置一个是否删除的标志位"""
    
    图书管理系统表设计(orm如何创建表与表之间的关系)
    一对多:一对多外键字段应该建在多的那一方
    	models.ForeignKey(to='关联的表名')  # 自动建关系 默认就是跟关联表的主键字段
    """ForeginKey字段在创建的时候 orm会自动在字段后面加_id"""
                
    多对多
    	ManyToManyField(to='关联的表名')  # 并不会创建一个实际字段 仅仅是用来告诉django orm自动创建第三张表
                
    一对一
    	OneToOneField(to='关联的表名')
    	"""OneToOneField字段在创建的时候 orm会自动在字段后面加_id"""
    
    django请求生命周期流程图
            
    路由层
    	路由匹配: url第一个参数是正则
    	无名分组: url(r'^index/(d+)/',views.index)
        	在调用视图函数index的时候 会将d+匹配到的内容 当做位置参数传递给index
    	有名分组: url(r'^index/(?P<year>d+)/',views.index)
            在调用视图函数index的时候 会将d+匹配到的内容 当做关键字参数(year='')传递给index
    	"""注意 无名有名不能混合使用 但是可以单独使用 单独使用的时候支持多个"""
    	反向解析
    		本质:根据某一个东西得出一个结果  该结果可以直接访问到对应的url
                
    	没有正则表达式的反向解析
    		url(r'^index/',views.index,name='xxx')  # 起别名 别名一定不要重复
          	前端反向解析: {% url 'xxx' %}
          	后端反向解析: 
          	from django.shortcuts import reverse
    			url = reverse('xxx')
    	
    	无名和有名分组的反向解析: url(r'^index/(d+)/',views.index,name='xxx')
    		前端反向解析: {% url 'xxx' 123 %}
            后端反向解析: 
            	from django.shortcuts import reverse
    				url = reverse('xxx',args=(123,))
            """个人建议:在处理容器类型数据的时候 无论有几个值 你最后都加一个逗号"""
                        
         url(r'^index/(?P<year>d+)/',views.index,name='xxx')
    		前端反向解析: {% url 'xxx' 123 %}
                        {% url 'xxx' year=123 %}  # 了解
            后端反向解析: 
    			from django.shortcuts import reverse
                    url = reverse('xxx',args=(123,))
                    url = reverse('xxx',kwargs={'year':123})  # 了解
    		"""个人建议:在处理容器类型数据的时候 无论有几个值 你最后都加一个逗号"""
                    
    	路由分发
            django中的每一个app都可以有自己独立的static文件夹,templates文件夹,urls.py等
            正是由于上述的特点 你基于django开发项目 就真正可以做到分组分功能分模块独立的去开发
            当应用特别多的时候 总路由中的代码过于冗长 不好维护
            # 1.在应用下自己手动创建urls.py
            # 2.在路由中导入 
            	# 1
                from app01 import urls as app01_urls
                from app02 import urls as app02_urls
                    
                url(r'^app01/',include(app01_urls)),
                url(r'^app02/',include(app02_urls))
                # 2
                url(r'^app01/',include('app01.urls')),
                url(r'^app02/',include('app02.urls'))  
                
    	名称空间
    	url(r'^app01/',include('app01.urls',namespace='app01')),
                    url(r'^app02/',include('app02.urls',namespace='app02')) 
         
         # app01 urls.py
         url(r'^index/',views.index,name='index')
         # app02 urls.py
         url(r'^index/',views.index,name='index')
                    
         url = reverse('app01:index')
         url = reverse('app02:index')
         {% url 'app01:index' %}
         {% url 'app02:index' %}
                    
          # app01 urls.py
    		url(r'^index/',views.index,name='app01_index')
          # app02 urls.py
            url(r'^index/',views.index,name='app02_index')
                    
    		
    伪静态
    	url看起来像是一个静态页面(.html结尾)
            
    虚拟环境
        不同的项目应该有各自独立的解释器环境 最大化节省资源
        实际功能中针对不同的项目 会有一个叫requestsments.txt文件
        该文件中列出来是一个个该项目需要用的到模块名和版本号
        eg:
    		django = 1.11.11
            nginx = 1.21
    	后期通过命令直接会去下载该文件内所有的模块及对应版本
            
    	虚拟环境 就类似于是个python解释器环境 每创建一个就类似于重新下载了一个纯净的python解释器环境
         
    django版本区别
    	url和path
            path第一个参数不支持正则 写什么就匹配什么 精准匹配
            re_path跟url是一模一样的用法   
        提供五个默认的转换器  
        还支持用户自定义转换器
    

    2. 视图层

    # 1.HttpResponse  # 返回字符串
                
    # 2.render  # 返回一个html页面 还可以给模板传递
    # render的内部原理
    from django.template import Template,Context
    
    def index(request):
    	res = Template("<h1> {{ user }} </h1>")
    	con = Context({'user':{'username':'jason','pwd':'123'}})
    	ret = res.render(con)
    	print(ret)
    	return HttpResponse(ret)
    # 3.redirect  # 重定向
    

    3. JsonResponse

    # JsonResponse: 返回json格式数据的
    '''
    为什么要给前端返回json格式字符串
    前后端分离  就是基于json格式传输数据
    后端就专门写接口 前端调用你这个接口 就能够拿到一个
    json格式的字符串
    然后前端利用序列化反序列转换成前端对应的数据类型
    
    js常用数据类型: 数值类型、字符类型、数组 []、自定义对象 {}、undefined与null、布尔值 true false、symbol(新加的)
    
    JSON.stringify 序列化   >>>   json.dumps
    JSON.parse     反序列   >>>   json.loads
    '''
    def index(request):
        # user = {'username': 'aa哈哈哈', 'pwd': '123'}
        # json_str = json.dumps(user, ensure_ascii=False)
        # return HttpResponse(json_str)
        # return JsonResponse(user,json_dumps_params={'ensure_ascii':False})
    
        l = [1,2,3,4,5,6]
        return JsonResponse(l, safe=False)
        # JsonResponse默认只支持序列化字典 如果你想序列化其他类型(json能够支持的类型) 你需要将safe参数由默认的True改成False
    
    

    4. form表单上传文件

    '''
    注意事项:
    	1.提交方式必须是post
    	2.enctype参数必须有默认的urlencoded变成formdata
    	
    FBV与CBV 即CBV源码分析
    	FBV(Function Based View) 基于函数的视图
        CBV(Class Based View) 基于类的视图
        
    思考:你在类中写了两个方法 一个叫get一个叫post
         为什么前端get请求来就会触发get方法
         post请求来就会触发post方法  如何实现的???
    '''
    
    # 上传文件
    def up(request):
        if request.method == 'POST':
            # 获取文件对象
            file_obj = request.FILES.get('myfile')
            with open(file_obj.name,'wb') as f:   # file_obj.name 获取文件名
                for chunk in file_obj.chunks():
                    f.write(chunk)
        return render(request,'up.html')
    
    
    # CBV路由
    url(r'^reg/',views.MyReg.as_view())
            
    @classonlymethod
    def as_view(cls, **initkwargs):
    def view(request, *args, **kwargs):
    	self = cls(**initkwargs)  # cls就是我们自己的写的MyReg类
        if hasattr(self, 'get') and not hasattr(self, 'head'):
        	self.head = self.get
        self.request = request
        self.args = args
        self.kwargs = kwargs
        # 上面的一通操作 就是给我们自己写的类的对象赋值
        return self.dispatch(request, *args, **kwargs)
        # 对象在查找属性或方法的时候 顺序是什么?  先从自己找 再从产生对象的类中找  再去类的父类中找...
        """也就意味着你在看源码的时候 你一定要牢记上面的话"""
    return view
            
    # views.py 
    from django.views import View
    
    
    class MyReg(View):
    	def get(self,request):
    		return render(request,'reg.html')
    
    	def post(self,request):
            return HttpResponse("我是MyReg类中post方法")
            
    """CBV最精髓的部分"""
    def dispatch(self, request, *args, **kwargs):
    	if request.method.lower() in self.http_method_names:  # 判断当前请求方式在不在默认的八个请求方式中
    		handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
            # handler = getattr(自己写的类产生的对象,'小写的请求方法(getpost)','获取不到对应的方法就报错')
            # handler就是我们自己定义的跟请求方法相对应的方法的函数内存地址
    	else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)  # 在调用获取到的方法
    

    5. django settings源码分析及实际应用

    '''
    django的配置文件有两个
    一个是暴露给用户可以自定义配置的
    一个是默认的全局配置文件
    用户指定了就用用户的
    用户没有指定就用默认的
    '''
    from django.conf import settings
    
    settings = LazySettings()
            
    class LazySettings(LazyObject):
                
    def _setup(self, name=None):
    	# os.environ你可以把它看成是一个全局的大字典
        settings_module = os.environ.get(ENVIRONMENT_VARIABLE)  # 从大字典中取值
    	# settings_module = 'day59.settings'
    	self._wrapped = Settings(settings_module)  # Settings('day59.settings')
            
    class Settings(object):
    	def __init__(self, settings_module):  # settings_module = 'day59.settings'
    		for setting in dir(global_settings):  # 循环获取global_settings文件中所有的名字
    			if setting.isupper():  # 在判断名字是否是大写
    				# 如果是大写 利用反射 获取到大写的名字所对应的值  不停地添加到对象中
    				setattr(self, setting, getattr(global_settings, setting))
    		# store the settings module in case someone later cares
            self.SETTINGS_MODULE = settings_module
            mod = importlib.import_module(self.SETTINGS_MODULE)  # 'day59.settings'
            # from day59 import settings
            # mod 指代的就是暴露给用户的配置文件模块名
                   
            for setting in dir(mod):  # 循环获取暴露给用户配置文件中所有的名字
    			if setting.isupper():  # 判断是否是大写
                setting_value = getattr(mod, setting)  # 如果是大写 获取大写的变量名所对应的值
                setattr(self, setting, setting_value)  # 不停的给对象设置值
            
    

    6. 模板传值

    # 如果传递给前端一个函数名,会直接加括号调用,将函数的返回值展示到前端,django的模板语法不支持给函数传参
    <p>{{ func }}</p>
    
    # 方法都不能传参
    <p>{{ obj }}</p>
    <p>{{ obj.get_cls }}</p>
    <p>{{ obj.get_func }}</p>
    <p>{{ obj.get_self }}</p>
    
    # django模板语法在获取容器类型内部元素的值的时候 统一只采用 句点符(.)
    # 模板语法取值
    <p>{{ l.1 }}</p>
    <p>{{ l.3 }}</p>
    <p>{{ d.username }}</p>
    <p>{{ d.password }}</p>
    <p>{{ d.password.1 }}</p>
    

    7. 过滤器与标签

    '''
    1.过滤器(|)
    (前端代码并不一定非要在前端写  你也可以在后端写好 传递给前端页面)
        前后端取消转义
            前端 
                |safe
            后端
                from django.utils.safestring import mark_safe
                sss2 = "<a href='http://www.xiaohuar.com'>下午上课 需要激情</a>"
                res = mark_safe(sss2)
    
        模板语法的符号就两种
            {{}}  变量相关
            {%%}  逻辑相关
    '''
    {#过滤器 有点类似于小的方法  #}
    {#特点 会将|左边的当做过滤器的第一个参数  |右边的当前过滤器第二个参数#}
    <p>{{ n|add:100 }}</p>
    <p>{{ n|add:'abc' }}</p>   {# 返回空 #}
    <p>{{ s|add:'abc' }}</p>
    <p>{{ l|length }}</p>
    <p>{{ d|length }}</p>
    
    <p>{{ file_size|filesizeformat }}</p>
    
    <p>截取10个字符 三个点也算{{ w|truncatechars:10 }}</p>
    <p>截取10个字符 三个点也算{{ w1|truncatechars:10 }}</p>
    <p>安装空格截取单词 三个点不算{{ w|truncatewords:6 }}</p>
    <p>安装空格截取单词 三个点不算{{ w1|truncatewords:6 }}</p>
    <p>安装空格截取单词 三个点不算{{ w2|truncatewords:6 }}</p>
    
    <p>{{ l|slice:'0:5' }}</p>
    <p>{{ l|slice:'0:5:2' }}</p>
    
    <p>{{ ctime|date:'Y-m-d' }}</p>
    <p>{{ ctime|date:'Y年m月d日' }}</p>
    
    <p>{{ sss|safe }}</p>
    <p>{{ sss1|safe }}</p>
    <p>{{ res }}</p>
    
    <p>{{ xo|default:'' }}</p>
    {#有值就拿值 没值就用后面默认的#}
    
        
    # 2.标签
    	# if判断
    	# for循环
    {% for foo in l %}
        {% if forloop.first %}
            <p>第一次</p>
        {% elif forloop.last %}
            <p>最后一次</p>
        {% else %}
            <p>嗨起来</p>
        {% endif %}
    {% endfor %}
    	
    # 3.自定义过滤器、标签的步骤
    	# 1.在应用名下面新建一个templatetags文件夹(必须叫这个名字)
    	# 2.在该文件夹下新建一个任意名称的py文件
    	# 3.在该pa文件内固定写两行代码
        	from django.template import Library
            register = Library()
    	
    # 4.自定义的过滤器
    	@register.filter(name='myfilter')
        def index(a,b):
            return a + b
    		
    # 5.自定义的标签
    	@register.simple_tag(name='myst')
        def login(a,b,c,d):
            return f'{a}{b}{c}{d}'
        
    # 6.区别 标签不能再if中使用
    # 可以用
    {% if 0|myfilter:123 %}
        <p>有值</p>
    {% endif %}
    
    # 不能用
    {#{% if myst 1 2 3 4 5 %}#} 
    {#    <p>有值</p>#}
    {#{% endif %}#}
    

    8. 模板的继承

    # 事先需要再模板中 通过block划定区域
        {% block 区域名字 %}
    
        {% endblock %}
    
    # 子板中如何使用
        {% extends '模板的名字'%}
    
        {% block 区域名字 %}
        <h1>登录页面</h1>
        {% endblock %}
    
    # 一个页面上 block块越多 页面的扩展性越高
    # 通常情况下 都应该有三片区域
        {% block css %}
        {% endblock %}
    
        {% block content %}
        {% endblock %}
    
        {% block js %}
        {% endblock %}
    
    # 子板中还可以通过 {{ block.super }} 来继续使用母版的内容
    

    9. 模板的导入

    # 当你写了一个特别好看的form表单 你想再多个页面上都使用这个form表单,你就可以将你写的form表单当作模块的形式导入 导入过来之后 就可以直接展示
    	{% include 'good_page.html' %}
    
  • 相关阅读:
    Android:日常学习笔记(7)———探究UI开发(1)
    Android:日常学习笔记(6)——探究活动(4)
    JavaScript:基础扩展(1)——JSON
    JavaScript:学习笔记(3)——正则表达式的应用
    正则表达式:快速入门
    LeetCode_Easy_471:Number Complement
    Java实现——字符串分割以及复制目录下的所有文件
    DOM、SAX、JDOM、DOM4J以及PULL在XML文件解析中的工作原理以及优缺点对比
    一个简单电商网站开发过程中的业务资料整理
    大道至简,不简则死
  • 原文地址:https://www.cnblogs.com/yushan1/p/11729162.html
Copyright © 2011-2022 走看看