django

web框架的本质 – socket服务端

  1. socket收发消息

  2. 根据不同的路径返回不同的内容

  3. 动态页面(jinja2)

    http://www.cnblogs.com/maple-shaw/?id=

浏览器上输入地址之后发生的事情

Web框架原理

HTTP协议

HTTP协议

请求的格式:

​ ‘请求方式 URL路径 协议版本\r\n

​ k1:v1\r\n

​ k2:v2\r\n

​ \r\n

​ 请求体’

响应格式:

​ ‘HTTP/1.1 状态码 状态描述\r\n

​ k1:v1\r\n

​ k2:v2\r\n

​ \r\n

​ 响应体(HTML文本)’

状态码 !

​ 1xx

​ 2xx 请求成功 返回正常的响应

​ 3xx 重定向 301 302

​ 4xx 请求错误 404 403

​ 5xx 服务器的错误 500 502

请求头: !

​ content-type

​ cookie set-cookie

​ host

​ user-agent

​ location

MTV MVC

MVC与MTV

MVC M model V view C controller

MTV M model T template V view

路由

Django 路由系统

正则

​ ^ $ \d \w ? + *

分组和命名分组

url的命名和反向解析

include

namespace

视图

Django 视图

FBV CBV

request !

response

​ 三大件

CBV

​ as_view 原理

​ 加装饰器

模板

Django 模板

{{ }} {% %}

变量

​ . KEY 属性 方法 索引

过滤器

​ {{ 变量|filter:参数 }}

​ safe mark_safe from django.utils.safestring import mark_safe

​ default add date : \’Y-m-d H:i:s\’ join first last length

标签 {% %}

{% csrf_token %} csrfmiddlewaretoken 64字符串

{ % with as %}

{% endwith %}

组件

​ 一段HTML代码 nav.html

​ {% include nav.html %}

静态文件

​ {% load static %}

​ {% static ‘相对路径’ %}

母板和继承

{ % extends \’母版的文件名\’ %} # 写到顶部

三个自定义方法: !!!

filter simple_tag inclusion_tag

步骤:

  1. 在APP下创建名为tempaltetags的Python包

  2. 在包内写py文件 my_tags.py

  3. 在py文件中写

    from django import  template
    register = template.Library()
    
    
  4. 写函数+装饰器

    @register.filter
    def addxx(value,arg=None):  # 对变量使用 {}
        return \'xxxxx\'
    
    @register.simple_tag 
    def simple(*args,**kwargs):   # 对标签使用  {% %}
        return \'cccccc\'
    
    @register.inclusion_tag(\'li.html\') # 
    def show_li(*args,**kwargs):
        return {\'k1\':v1}
    
  5. 使用

    {% load my_tags %}
    {{ \'alex\'|addxx:\'sb\' }}
    {% simple \'v1\' \'v2\'  k1=\'v3\' %}
    
    {% show_li  %}
    

ORM

Django ORM

对象关系映射

​ 对应关系

  1. 必知必会13条

    对象列表

    ​ all

    ​ filter # 过滤

    ​ exclude # 过滤反转

    ​ values() # 字典列表

    ​ values_list() # 元组列表

    ​ order_by() # 排序

    ​ reverse() # 反转

    ​ distinct() # 去重,按照整个结果去重,不能按照每个字典去重

    对象

    ​ get

    ​ first()

    ​ last()

    数字

    ​ count()

    布尔值

    ​ exists()

  2. 单表的双下划线

    __gt gte lt lte

    __isnull

    __in =[ ]

    __range=[1,10]

    __contains

    __icontains

  3. 外键

    描述多对一的关系

    publisher book

    class Book:

    ​ pub = Fk(\’Publisher\’,on_delete,related_name=\’books\’) # on_delete 当删时做的操作 SET(value) SET_DEFAULT SET_NULL

    基于对象

    正向查询

    book_obj.pub ——》 出版社对象

    book_obj.pub_id ——》 出版社对象ID

    反向查询

    pub_obj.book_set ——》 管理对象 related_name=\’books pub_obj.books

    pub_obj.book_set.all() ——》 出版社所管理所有的书籍

​ 基于字段

​ Book.objects.filter(publisher__name=\’xxxxx\’)

  1. 多对多

    创建的三种方式
    方式一,让Django自动创建第三张表
    class Author():
        name = 
        books = models.ManyToManyField(\'Book\')
        
        
    方式二,手动创建第三张表, 查询不方便,需要手动跨表
    class Author(models.Model):
        name = models.CharField(max_length=32)
    
    
    class Author_Book(models.Model):
        author = models.ForeignKey(\'Author\')
        book = models.ForeignKey(\'Book\')
        date = models.DateTimeField()
    
    
    方式三,手动创建,查询优化,如同自动创建的
    class Author(models.Model):
        name = models.CharField(max_length=32)
        books = models.ManyToManyField(\'Book\', through=\'Author_Book\')
    
    
    class Author_Book(models.Model):
        author = models.ForeignKey(\'Author\')
        book = models.ForeignKey(\'Book\')
        date = models.DateTimeField() 
    
   
方法:
   
​	author_obj.books   ——》 管理对象
   
​	author_obj.books.all() 
   
​	author_obj.books.set()       设置多对多   【对象,对象】   【id,id】
   
​	add       remove    clear     create  
   
​	author_obj.books.create     book 			
   
​        book_obj.author_set
   
F  和  Q
   
Q 条件 
   
   ```pyton
   Q(name__contains =\'xxxx\')  |  Q(qq__contains=\'111\')
   
   &  与  ~ 非  
   Q((\'name__contains\' ,\'xxxx\'))
   
   q = Q()
   q.connector = \'OR\'
   q.children.append(Q((\'name__contains\' ,\'xxxx\')))
   q.children.append(Q( Q(qq__contains=\'111\')))
   

聚合和分组 TODO 真心不懂

   from crm import models
   
   from django.db.models import Count, Max, Sum, Min, Avg
   
   ret = models.UserProfile.objects.aggregate(Count(\'id\'))
   print(ret)
   ret = models.Campuses.objects.annotate(Count(\'classlist\')).values()
   
   ret = models.ClassList.objects.values(\'campuses\').annotate(Count(\'campuses\'))
   
   print(ret)

事务

   from django.db import transaction
   
   with transaction.atomic():
       # 事务
       pass
   
   

行级锁 !

   from django.db import transaction
   
   with transaction.atomic():
       # 事务
       queryset = models.ClassList.objects.filter(pk__gt=3).select_for_update()
   
       queryset.update()

cookie和session !!

Cookie和Session

解决HTTP协议无状态的问题

cookie 保存在浏览器上一组组键值对

django中的操作

设置

​ response.set_cookie(key, values,max_age=10,) set-cookie

获取

​ request.COOKIES cookie

session

​ 保存在服务器上一组组键值对 必须依赖于cookie

django中操作

​ request.session[]

ajax

data csrfmiddlewaretoken

heard x-csrftoken

中间件 !!!!!

Django 中间件

本质上是一个类,在全局范围内改变django的输入和输出,一个钩子。

5种 4个点

process_request()
process_response()
process_view()
process_exception()       # 视图级别 有错误才执行
process_template_response()   # 返回的response 对象是

执行时间 、 执行顺序、 参数  、不同返回的流程

form modelform modelformset

django-debug-toolbar

Django django-debug-toolbar

缓存

Django 缓存

信号

Django 信号

ORM性能相关

Django ORM性能优化

数据库相关

Django 数据库相关配置

crm

重点

  1. 业务
  2. 代码 自己能写出来
  3. 权限控制
  4. 表结构
  5. 数据结构 session 中
  6. 开发过程中遇到了什么问题?
  • 干什么用的?

    维护客户关系一套系统。 客户、销售增多 。

  • 实现的功能

    • 销售
      • 客户管理
      • 公户 私户
      • 跟进记录管理
      • 报名表
      • 缴费表
    • 班主任
      • 班级管理
      • 课程记录管理
      • 学习记录
  • 公户和私户

    • 避免销售抢单

      3天跟进 15天成单 –> 客户的上限 150 200

  • CRM有现成的系统?为什么要开发?

    自己开发 可定制化程度高 学邦 http://www.xuebangsoft.com/about.html?

  • crm有多少张表?

    • 业务 10 张
    • 权限 6张表(4个model)
  • 权限是如何实现的?

    ​ 大概思路, 不是代码,不是结果

    • url代表的一个权限
    • 表结构
    • 登录 + 中间件
  • 权限中的技术点

    • 视频 153.38

    • 登录

      • 获取权限
        • 跨表
      • 去重
    • 去空

    • 数据结构

      • 权限的结构

        permission_list = [ { url title id pid } ]

        路径导航

          permission_dict   =  {
          
          		权限的id : {  url  title  id  pid   }
        
        	}
        
        

        权限控制到按钮级别

          permission_dict   =  {
          
          		权限的name : {  url  title  id  pid  pname }
        
        	}
        
      • 菜单的结构

        menu_dict = {

        一级菜单的ID: {
        	
        	title:
        	
        	icon:
        	
        	children : [
        	
        		{   title  url  id   }	
        	
        	]
        
        }	
        

        }

    • session

      • json序列表
    • 中间件

      • process_request
      • request.pah_info
      • request.breadcrumb_list = [ { url:index , title:首页 } ]
      • 白名单
      • settings
      • 正则
      • 权限的校验
        • 是有pid
          • 有pid 子权限
            • request.current_menu_id = pid
            • breadcrumb_list.append({ url title }) permission_dict [pid] 父权限 pname
            • breadcrumb_list.append({ url title }) 子权限
          • 没有pid 二级菜单
          • request.current_menu_id = id
          • breadcrumb_list.append({ url title }) 二级菜单
    • 动态菜单

      • inclusion_tag
      • 权限的id == request.current_menu_id
      • 二级菜单 class = active
      • 一级菜单 class= ‘’
  • 路径导航

    • inclusion_tag
    • 权限控制到按钮级别
      • if name in permission_dict
      • filter

简单权限的实现

class Permission(models.Model):
    url = models.CharField(max_length=64)
    title = models.CharField(max_length=32)


class Role(models.Model):
    name = models.CharField(max_length=32)
    permissions = models.ManyToManyField(\'Permission\')


class User(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    roles = models.ManyToManyField(\'Role\')

动态一级菜单

class Permission(models.Model):
    url = models.CharField(max_length=64)
    title = models.CharField(max_length=32)
    is_menu = models.BooleanField(default=False)
    icon = models.CharField(max_length=64)


class Role(models.Model):
    name = models.CharField(max_length=32)
    permissions = models.ManyToManyField(\'Permission\')


class User(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    roles = models.ManyToManyField(\'Role\')

动态二级菜单

class Menu(models.Model):
    title = models.CharField(max_length=64)
    icon = models.CharField(max_length=64)


class Permission(models.Model):
    """
    有menu_id      二级菜单

    有parent_id    子权限
    """
    url = models.CharField(max_length=64)
    title = models.CharField(max_length=32)
    menu = models.ForeignKey(Menu, null=True, blank=True)
    parent = models.ForeignKey(\'self\', null=True, blank=True)


class Role(models.Model):
    name = models.CharField(max_length=32)
    permissions = models.ManyToManyField(\'Permission\')


class User(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    roles = models.ManyToManyField(\'Role\')

权限控制到按钮级别

class Menu(models.Model):
    title = models.CharField(max_length=64)
    icon = models.CharField(max_length=64)


class Permission(models.Model):
    """
    有menu_id      二级菜单

    有parent_id    子权限
    """
    url = models.CharField(max_length=64)
    title = models.CharField(max_length=32)
    name = models.CharField(\'URL别名\', max_length=32, unique=True)
    menu = models.ForeignKey(Menu, null=True, blank=True)
    parent = models.ForeignKey(\'self\', null=True, blank=True)


class Role(models.Model):
    name = models.CharField(max_length=32)
    permissions = models.ManyToManyField(\'Permission\')


class User(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    roles = models.ManyToManyField(\'Role\')

权限如何能不重新登录,就应用新的权限?

  • 用户表加字段 存 session_key

  • 通过session_key 拿到用户的session数据 更新权限

    from django.contrib.sessions.models import Session
    from django.contrib.sessions.backends.db import SessionStore
    
    decode   encode
    
    

权限如何控制到行级别?

加条件表

1554205394307

开发过程中遇到了什么问题?

  • 数字变字符串
  • 表结构的变化
  • 需求的取舍

路飞学城

Vue

要求:了解Vue 能看懂Vue的代码,能够使用elementUI搭建简单的页面

Vue的基础语法

  • 常用指令(小清单的应用 数据驱动视图) –> MVC和MVVM的区别
    • Vue的生命周期钩子函数
  • 组件
    • 组件定义
    • 全局组件
    • 局部组件
    • 组件间传值
    • 插槽(slot)
  • 前端模块化开发
    • node.JS(基于chrome V8引擎的一个服务器版JS) –> 让我们像写后端代码一样写前端代码
    • webpack –>打包工具,把后端开发的JS代码都打包成一个JS文件,放到HTML中
    • VueCLI3 –> vue create 项目名 (项目的目录结构)
  • VueRouter
    • 基本路由定义 router-link路由入口 router-view路由出口
      • $route:当前的这条路由信息
      • $router:当前路由对象
    • 嵌套路由
    • 命名路由
    • 路由的动态匹配(参数:route.params route.query
    • 编程式导航 –> router.push(...)
  • axios (Vue里面推荐使用的发送ajax请求的模块,支持promise)
  • VueX: 一般大型项目才用的 https://vuex.vuejs.org/zh/

Django REST framework

十个组件

序列化(Serializer)

用法类似于form组件

serializer使用

  1. 定义一个serializer类,继承serializers.Serializer/serializers.ModelSerializer
  2. 字段
    1. read_onlywrite_only
    2. source用来指定该字段的具体操作source=get_category_display
    3. serializers.MethodField serializer类中必须定义一个get_开头的方法
    4. 外键关联 depth=1 所有外键关联的数据就变成只读的
    5. serializers.ListField
    6. require=True
  3. 校验 抛出serializers.ValidationError 异常 (对比Django form校验记忆)
    1. 全局validate()
    2. 局部validate_field()
    3. 使用内置的检验规则 正则等

serializers.ModelSerializer

  1. 不用自己挨个定义字段
  2. .save() 直接一键更新或创建
class ArticleWriteSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Article
        fields = "__all__"
        extra_kwargs = {
            "tag": {
                "error_messages": {
                    "does_not_exist": \'"{pk_value}"对应的tag对象不存在。\'
                }
            }
        }

序列化过程:ORM对象–>JSON格式数据

反序列化:JSON格式数据–>ORM对象

视图

对面对对象理解更深刻的一节课。

重难点:类的多继承,mixin混合类

混合类: 不能单独实例化,必须和别的类搭配使用

img

认证、权限、限制(节流)

认证

重写authenticate()方法,返回值是一个元素:第一个元素是用户对象 第二个元素是token

全局配置:所有视图都通用的认证方案

局部视图配置:给单独某个视图配置的认证方案

Token: JWT –> JSON Web Token替代session存储的方案

JWT原理 面试的经常问,要能够说明白!

权限

表示用户有没有权限访问某个接口(API)

重写has_permission()方法

允许访问返回True

不允许访问返回False

全局配置:所有视图都通用的认证方案

局部视图配置:给单独某个视图配置的认证方案

class VipPermission(BasePermission):
    def has_permission(self, request, view):
        # 如果当前的用户是VIP用户就返回True
        if not request.user:
            return False
        if request.user.vip:  # 前提user表里必须要有一个vip字段
            return True
        else:
            return False

限制(节流)

用来限制用户访问API的频率

重写allow_request()方法

一般使用内置的就满足基本需求

from rest_framework.throttling import SimpleRateThrottle


class VisitThrottle(SimpleRateThrottle):

    scope = "xxx"

    def get_cache_key(self, request, view):
        return self.get_ident(request)

在settings.py中要添加配置项

# 在settings.py中设置rest framework相关配置项
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
    # "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
    "DEFAULT_THROTTLE_CLASSES": ["app01.utils.VisitThrottle", ],
    "DEFAULT_THROTTLE_RATES": {
        "xxx": "5/m",
    }
}

知识点:

一分钟最多访问3次,使用while循环

边循环列表边对列表做删除元素的操作。

分页、版本控制、过滤器

分页

分页模式

  1. 基本的page number
  2. limitoffset
  3. 加密分页

使用的模式:

  • 全局配置
  • 局部视图配置
REST_FRAMEWORK = {
    # 指定用什么分页模式
    \'DEFAULT_PAGINATION_CLASS\': \'rest_framework.pagination.LimitOffsetPagination\',
    # 每页显示多少条数据
    \'PAGE_SIZE\': 100
}

版本控制

为了兼容引出来版本的概念,满足新旧版本同时运行的需求。

五种方式:

  1. 域名: luffycity.com/api/v1
  2. URL参数luffycity.com/version=v1
  3. 在请求头中添加 version信息

img

配置:

REST_FRAMEWORK = {
    ...
    \'DEFAULT_VERSIONING_CLASS\': \'rest_framework.versioning.URLPathVersioning\',
    \'DEFAULT_VERSION\': \'v1\',  # 默认的版本
    \'ALLOWED_VERSIONS\': [\'v1\', \'v2\'],  # 有效的版本
    \'VERSION_PARAM\': \'version\',  # 版本的参数名与URL conf中一致
} 

在视图中拿到版本信息:

request.version拿到当前这次请求的版本号

if request.version == "v1":
    ....
elif request.version == "v2":
    ...

过滤器(filter)

对请求的数据按照某个字段做筛选。

视图中通过get_queryset()方法拿到本次请求用到的所有数据

get_queryset中对数据进行过滤。

DRF有个插件:django-filter

安装pip install django-filter

class ProductList(generics.ListAPIView):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    filter_backends = (filters.DjangoFilterBackend,)
    filter_fields = (\'category\', \'in_stock\')  # 通过这个配置项指定支持过滤的字段

解析器、渲染器

解析器:把前端提交过来的数据反序列化成DRF框架中可以使用的数据

渲染器:根据前端请求头里面的信息返回不同格式的数据

POSTman

一个测试接口的工具

路飞业务

首页 elementUI搭建首页

课程列表页

后端用的是ListAPIView

前端Vue用的v-for

支持排序和检索

根据价格排序:order_by("price")

按照课程分类做筛选:filter(category=1)

添加购物车

Redis
  • 五种数据类型:List String Hash Set Zset

  • 基本操作

  • Django中使用redis

    储购物车数据的数据格式:字符串 JSON格式的字符串 –> Python中的字典

结算

数据有效性的校验

  1. 课程信息校验
  2. 价格策略的校验
  3. 优惠券校验
    1. 课程优惠券
    2. 通用优惠券
  4. 支付金额的校验

结算属于中间状态,用redis存储。

支付校验

创建订单(未支付的) –> 返回一个订单号

创建支付宝支付链接需要用到订单号

支付宝支付

加密(为什么要加密?确保通信的安全)

沙箱环境的使用

调用支付宝支付接口的流程:

  1. 创建一个支付宝的支付链接(要有订单号)
  2. 浏览器拿到这个链接跳转到支付宝的二维码页面
  3. 用户扫码
  4. 用户支付成功 –> 支付宝收到钱
  5. 支付宝先会发送一个POST请求到我的网站指定的接口
  6. 对发来的请求用私钥解密信息,判断是否真的支付成功
  7. 给支付宝的POST请求返回一个true 应答
  8. 支付宝会在发送一个GET请求到一个指定的URL

简历

CRM:

​ 客户管理系统

​ 经销商管理

​ 库存管理

​ 内部OA

路飞(5个月):

​ 拼购的网站:类似于电商

​ 小程序:调用微信登录

​ K12: 在线的公开课网站,给小孩子看视频的

​ 经销商培训系统:培训新产品的新特色之类

项目难点:

​ 自己看源码 –> DRF视图 –> 面向对象有了更深刻的理解 多继承和混合类

​ 支付宝支付接口 –> 学会看文档(SDK) –> 要能够把支付流程说清楚

​ 优惠券策略 –> 不同的品类绑定不同的优惠券 –> contenttype

​ 存redis操作 –> 购物车数据结构 –> 大字典

人工智能:

​ 智能蓝牙音箱(小爱同学)

​ 智能玩具

​ 智能客服(爱因互动)

爬虫和数据分析:

git操作

数据结构和算法:

​ 常见算法及时间复杂度空间复杂度必须背会。

​ 手写快排、堆排序、选择排序

​ 归并排序

关于准备面试

  1. 自己提前做好计划,确定好里程碑节点。(简历写(改)完, 刷面试题,投简历,出去面试(录音回来分析))

写简历千万不要像写笔记一样,把知识点与项目背景融合,写的尽量真实点。

简历可以准备多份,根据投的公司不一样使用不同的简历。

本科 3年

简历上如果是子计算机相关专业就写上,不是就不要写了。

简历要下功夫

准备面试永远没有准备好的那一天。

简历上写的项目要做到给你一张纸一根笔能说半个小时。

推荐大家把每个项目要说的东西都写下来。

面试的要不卑不亢,落落大方。

机会是自己努力争取的。

职业生涯代码量:1年6W左右

基础

第一部分

Cpython -> 解释器: 执行代码

解释性编程语言 -> 同声传译
执行效率低
跨平台性比较好

编译型编程语言 -> 笔译
执行效率高
跨平台性不好

IPython: 交互不一样

变量: 保存数据, 程序运行过程中产生的值。 供给后面的程序使用

int: 整数
float:浮点数

二级制

bool: 布尔
str: 字符串

​ ascii

​ unt8

list: 列表 -> 能装对象的对象
增删改查

set: 集合
去重复, 子集, 差集

dict: 字典
以key:value存储数据
key:必须可哈希。不能重复
value: 没有要求

tuple: 元组
不可变 -> 可哈希

long:长整数; py2

open() 打开一个文件 -> 获取到文件句柄

​ a w r

​ open 参数

深浅拷贝

第二部分

函数:
对功能或者动作的封装

def 函数名(形参):
    函数体
    return

函数名(实参)

返回值:
    函数执行的结果

    1. 不写return  没有返回值. None
    2. 只写return  没有返回值. None
    3. return 值, 只有一个返回值.
    4. return 值1, 值2, 值3... 有多个返回值. 外面接收的是一个元组

    return可以终止一个函数的执行

参数:
    形参:
        1. 位置
        2. 默认值参数
        3. 动态传参:
            *args     位置参数
            **kwargs  关键字

            顺序: 位置 > *args > 默认值 > **kwargs
            *, ** 在形参: 聚合成元组
            *, ** 在实参: 打散. 可以把列表(可迭代对象)打散

    实参:
        1. 位置
        2. 关键字
        3. 混合  先位置, 后关键字

函数名: 函数名就是变量名

作用域和名称空间:
    globals()   查看全局中的内容
    locals()    查看当前作用域中的内容

    global     获取到全局变量
    nonlocal   在局部, 内层函数对外层变量的引入.

闭包:
    内层函数对外层函数的变量的使用
    def outer():
        a = 10
        def inner():
            a
     开闭原则:
     	对添加新功能开发
     	对修改源代码封闭

    闭包作用:
        1. 让一个变量常驻内存    
        2. 保护变量不被修改

装饰器:

    from functools import wraps
    def wrapper(fn):
        @wraps(fn)
        def inner(*args, **kwargs){
            \'\'\'在xxx之前\'\'\'
            ret = fn(*args, **kwargs)
            \'\'\'在xxxx之后\'\'\'
            return ret

        return inner

    @wrapper   # target = wrapper(target)
    def target():
        pass

    print(target.__name__)

    给装饰器传参:
        再提一层函数. 专门给装饰器传递参数用的.
        def wrapper_out(flag): # 给装饰器传参, True, False
            def wrapper(fn):
                def inner(*args, **kwargs):
                    if flag:
                        print("问问吴老板, 现在适不适合约. ")
                        ret = fn(*args, **kwargs)
                        print("吴老板骗我.....")
                    else:
                        ret = fn(*args, **kwargs)
                    return ret
                return inner
            return wrapper

        @wrapper_out(True)  先执行后面的括号, 返回一个装饰器再和前面的@拼接.成一个语法糖

    同一个函数被多个装饰器装饰

    迭代器:
        存在的意义: 为了让所有的数据类型拥有相同的遍历方式

        __iter__获取到迭代器
        __next__获取到下一个元素. 获取到最后的时候会报错. StopIteration

        list. dict, range, open(), str, tuple, set

        都可以被迭代. 都可以使用for循环

        特点:
            1. 省内存    ->  生成器
            2. 惰性机制
            3. 只能向前. 不能反复

    生成器:
    	面试题很恶心
    		# 生成器 
			# def add(a, b): # 求和
            #     return a + b
            #
            #
            # def func(): # 生成器函数   0 1 2 3
            #     for i in range(4):
            #         yield i
            #
            # g = func()  # 生成器   0 1 2 3
            #
            #
            # n = 2
            # g = (add(n, i) for i in g)
            #
            # ##############
            # n = 10
            # g = (add(n, i) for i in g)
            #
            # ############
            #
            # # for n in [2,10]:
            # #     g = (add(n, i) for i in g)
            #
            # print(list(g))  #  [g...] 会吧生成器拿空
            # # n = 10
            # # 20 21 22 23

            # 函数闭包
            # def add():
            #     return [lambda x: x * i for i in range(4)]
            #     # lst = []
            #     # for i in range(4):
            #     #     def fn(x):
            #     #         return x * i
             #     # return lst
            #
            # print([m(2) for m in add()])


​ 1. 生成器函数: yield

​ def func():
​ yield

​ func() 创建生成器对象 不会执行函数

​ g.next() 运行到下一个yield. 把yield后的数据返回
​ g.send(123) 给上一个yield位置传值

​ 2. 生成器表达式
​ [结果 for if]
​ {key:value for if}
​ {key for if}

​ (结果 for if) 直接获取到生成器对象

​ 内置函数:
​ map()
​ sorted() 排序
​ filter() 筛选和过滤
​ super()
​ divmod() 计算商和余数
​ len()
​ zip()
​ enumerate() 枚举
​ all() and
​ any() or

​ bin()
​ hex()
​ int()
​ format()
​ max()
​ sum()
​ avg()
​ range()

​ lambda x: xxxxxx

​ 递归函数
​ 函数自己调用自己
​ 优势:简单.
​ 缺点:耗内存. 容易崩溃

    二分法
        掐头结尾取中间
        缺点: 必须有序

第三部分

collections
Counter:
defaultdict
OrderDict
Namedtuple
Iterator
Iterable

time模块
时间
time.time() 系统时间 时间戳 数字. 1970-01-01 00:00:00
time.strftime(“%Y-%m-%d %H:%M:%S”) 格式化时间
time.localtime() 转换成结构化时间

pickle: 序列化.
dumps 没有文件
dump 有文件
loads 没有文件
load 有文件

json:
dumps 没有文件
dump 有文件
loads 没有文件
load 有文件

ensure_ascii = False

True:true
False:false
None: null
数字: 字符串

random
randint() 随机整数

choice() 随机选择一个
sample() 随机选择n个
shuffle() 打乱

os
os.path.join
os.path.abspath
os.path.dirname
os.path.exists 判断是否存在
os.path.getSize()
os.rename
os.remove

sys
sys.path
sys.argv
sys.modules

第四部分

类和对象
class 类名(object):
def init(self, 参数1, 参数2…):

对属性的封装

​ self.属性 = 参数1
​ self.属性 = 参数2
​ self.属性 = 参数3
​ self.属性 = 参数4

    def jump(self):
        pass

obj = 类名()

obj...

封装:
1. 对属性的封装 对象.属性 = 值
2. 对方法的封装 类中定义方法

继承:
子类自动拥有父类中的除了私有内容外的所有内容
多继承
MRO: C3算法来完成

多态:
类的成员:

1. 变量
    1. 实例变量  ->  给对象用的.
    2. 类变量   -> 给类用的.
    2. 方法
    1. 实例方法  -> 对象
    2. 类方法   -> 类  @classmethod
    3. 静态方法  -> 函数  @staticmethod

3. 属性
    @property

4. 私有
    私有 __开头  只能自己用

5. 特殊
    __new__ 创建对象
    __init__
    __call__
    __str__
    __repr__
    __dict__
    __getitem__
    __setitem__
    __eq__
    __iter__
    __next__

hasattr()
getattr()
setattr()
delattr()

type()
issubclass()
isinstance()

约束:
1. raise NotImplementedError
2. 使用抽象类
from abc import ABCMeta, abstractmethod

try:
    xxxx
except Exception as e:
    ....

网络编程

一 CS架构
客户端服务端架构
BS架构
浏览器与服务端

二 网络通信流程
网卡 收发网络电信息
mac地址 网卡的全球唯一标识 广播的通信方式 — 广播风暴 — 造成网络拥堵 信息不安全
ip地址 划分网段 192.168.1.0 — 192.168.1.255 属于同一子网 同一子网内可以进行广播通信 arp协议 通过ip地址获取mac
子网掩码 255.255.255.0 11111111.111111111.11111111.00000000
192.168.1.16 — 192.168.1.0 计算两个ip地址是否为同一网段
DNS服务器 DNS保存着ip地址和域名的一个对应关系, www.baidu.com|波多野结衣| www.baidu.com — 103.235.46.39

网关

交换机 升级版的集线器
路由器 管理内网 联通外网
集线器
广播\单播
广播风暴

三 osi七层协议
应 表 会 传 网 数 物

tcp\id五层
应 传 网 数 物

你好|80|IP地址|mac地址 ---- 电信号  --网线 ---  电信号 -- 你好  

传输层
	tcp\udp
	tcp: 面向连接,消息可靠,面向流,无消息保护边界,相对效率低
		tcp要建立连接:
			三次握手    详情  https://github.com/jawil/blog/issues/14
				
			四次挥手


​ udp: 面向无连接,消息不可靠,面向包的,有消息保护边界,效率高

​ socket在应用层和传输层之间的一个抽象层

​ socket tcp和udp下的写法都要会

​ 粘包

​ 解决粘包
​ struct

并发编程

重看 博客

操作系统, 进程,线程,GIL,协程,IO多路复用

IO多路复用,select、poll、epoll 原理 TODO 有点难理解

算法

希尔排序

def shell_sort(list):
    n = len(list)
    # 初始步長
    gap = n // 2
    while gap > 0:
        for i in range(gap, n):
            # 每个步長進行插入排序
            temp = list[i]
            j = i - gap
            # 插入排序
            while j >= 0 and list[j] > temp:
                list[j + gap] = list[j]
                j -= gap
            list[j + gap] = temp
        # 得到新的步長
        gap = gap // 2
    return list

k数之和 TODO dp版本

SQLAlchemy

SQLAlchemy.md

Flask-SQLAlchemy

Flask-SQLAlchemy.md

Flask-Script

Flask-Script.md

Flask-Migrate

Flask-Migrate.md

Celery

Celery.md

设计模式

Flask

  1. response
  2. request
  3. session
  4. 路由
  5. 初始化配置
  6. config
  7. buleprint
  8. 特殊装饰器
  9. CBV
  10. requestsContent

websocket

​ 原理,封包、解包

数据分析 爬虫

知识点总结

  • 通用爬虫
  • 聚焦爬虫
  • 增量式
  • requests模块 — urllib
    • 爬取数据流程:
      • 指定url
      • 发起请求
      • 获取响应数据
      • 数据解析
      • 持久化存储
    • get,post作用:
    • get,post参数:
      • url
      • headers
      • params/data
      • proxies
    • 处理ajax动态加载的数据:
      • url:必须通过抓包工具捕获
      • get/post发起请求获取响应数据,对响应数据进行解析,持久化存储
    • 模拟登陆:

    • 打码平台使用:
      • 开发者用户:
        • 创建一个软件(id,秘钥)
        • 下载示例代码
    • cookie的处理:
      • 手动处理:
        • 将cookie值封装到headers中
      • 自动处理:
        • session对象. session = requests.Session()
    • 代理ip:
      • proxies参数: requests.get(proxies={\’http://\’:\’ip:port\’})
      • 透明,匿名,高匿
      • 快代理,西祠代理
    • 线程池:
    • 图片懒加载:
      • 伪属性:scr2
  • 数据解析
    • 解析原理:
      • 标签的定位
      • 提取标签中的数据
    • 正则表达式:
    • bs4:
      • soup.tagName
      • find系列函数:
        • find(\’tagName\’,class_=\’xxx\’)
        • find_all(tagName)
      • select:层级选择器(> )
      • text,string,get_text()
      • soup.a[\’href\’]
    • xpath:
      • xpath函数结合着xpath表达式实现标签定位和数据提取
  • selenium
    • 作用:实现浏览器自动化的操作(通过代码定制相关的行为动作,且将该行为动作同步映射到浏览器中)
    • 使用流程:
      • 导包:from selenium import webdriver
      • 实例化一个浏览器对象(驱动程序)
      • 发起请求(get)
      • 关闭浏览器(bro.quit())
    • find系列函数:
      • find_element_by_id
      • 定位标签
    • switch_to.frame函数:
      • qq空间
      • bro.switch_to.frame(\’iframe_id\’)
    • page_source:
    • phantomJs:
      • 浏览器
    • 谷歌无头浏览器:
  • scrapy
    • 项目创建流程:
      • 创建工程
      • cd ProName
      • 创建爬虫文件
        • 父类:Spider
        • name
        • start_urls
        • parse(self,response)
          • response.xpath(\’//a/@href\’):返回值是一个列表.(列表元素:Selector对象),extract/extract_first
    • 持久化存储:
      • 基于终端指令
        • scrapy crawl spiderName -o xxx.csv
      • 基于管道
        • item对象:存储解析到的某一组数据.因为管道文件中的process_item这方法只可以处理和操作item类型的对象.
        • 编码流程:
          • 数据解析
          • 实例化item对象,将解析到的数据封装到item对象中
          • 将item提交给管道
          • 在管道的process_item方法中接收item,将item中存储的数据进行持久化存储
          • 在配置文件中开启管道
        • 如何将同一份数据存储到不同的平台中?
          • 在管道文件中封装多个管道类(负责将数据存储到一个平台)
          • process_item中返回值(return item)的作用:传递给下一个即将被执行的管道类
    • 处理分页数据爬取:
      • 基于全站数据爬取:
        • 手动请求发送+递归解析
        • 手动请求发送:
          • yield scrapy.Request/FormRequest()
    • post请求
      • start_urls:
      • start_requests():
    • cookie处理:
      • 自动处理
    • 日志等级:
      • LOG_LEVEL=\’ERROR\’ LOG_FILE=\’log.txt\’
    • 请求传参(item):
      • 使用场景:当爬取的数据不在同一张页面中.
      • yield scrapy.Request(url=url,callback=self.parse_detail,meta={\’item\’:item})
    • 五大核心组件原理:

    • 下载中间件:
    • UA池和代理池:
      • process_request(self,request,spider):
        • request.headers[\’User-Agent\’] = random.chioose(UAList)
      • process_exception(request):
        • request.url 返回发生异常请求的url
        • request.meta[\’proxy\’] = \’http://ip:port\’
    • selenium在scrapy中的应用:
      • 编码流程:
        • 实例化一个浏览器对象(爬虫文件的构造方法中)
        • 在爬虫文件的closed方法中关闭浏览器对象
        • 在中间件的process_response(response)方法中编写自动化的操作
          • page_source(包含了动态加载的数据)
          • 实例化一个新的响应对象,且将page_source封装到该响应对象中
          • 返回新的响应对象
    • crawlSpider:
      • 全站数据爬取
      • 创建爬虫文件的指令:scrapy genspider -t crawl spiderName xxx.com
      • 爬虫文件的父类:CrawlSpider
      • LinkExtractor:连接提取器,根据指定规则(正则)提取连接(url)
        • Rule:规则解析器,负责将连接提取器提取到的连接发起请求获取对应的页面数据,且对该数据进行指定规则的解析.
      • 一个连接提取器对应一个规则解析器.
      • 深度提取:
  • 分布式
    • scrapy为何不能实现分布式:
      • 管道和调度器无法被所有的分布式机群共享
    • scrapy-redis的作用:
      • 给scrapy提供了可以被共享的管道和调度器(spider)
      • redis_key:
    • 实现分布式的方式:
    • 流程:
  • 增量式爬虫
    • 概念:用来 检测 网站数据的更新情况.
    • 去重
      • 对url去重
      • 爬取的数据去重

案例总结

反爬机制总结

  • robots.txt
  • UA检测
  • 验证码
  • 数据加密
  • cookie
  • 禁IP
  • 动态token
  • 数据动态加载

数据清洗

  • 空值检测删除空值所在的行数据:
    • df.dropna(axis=0)
    • 手动处理:
      • 检测df中存在空值的行(isnull notnull any all)
      • 获取行索引
      • 使用drop删除指定的行(行索引)
        • 将合适的bool值作为行索引
  • 空值检测填充空值:
    • fillna(method=\’ffill/bfill\’,axis=0/1)
  • 异常值检测和过滤:
    • 判断异常值的条件
    • 条件对应的表达式一定是一组bool值(df[\’C\’] <= df[\’C\’].std()*2)
  • 重复行检测和删除:
    • drop_duplicated(keep)

面试题

  • 如何提升爬虫的效率
    • 线程池
    • scrapy配置文件相关配置(禁用cookie,禁止重试,减小下载超时,增加并发,日志等级)
  • scrapy核心组件工作流程
  • scrapy中如何设置代理(两种方法)
    • 中间件
    • 环境变量(os.environ[\’HTTPS_PROXY\’] = \’https:ip:port\’)
  • scrapy如何实现限速
    • DOWNLOAD_DELAY = 1
  • scrapy如何实现暂停爬虫
    • JOBDIR=\’sharejs.com\’
    • control-C
  • pipeline如何丢弃一个item对象
    • yield item 在spider 中判断
    • item.class 在pipeline 中放弃持久化操作
  • scrapy-redis组件作用
  • 实现深度和广度优先:默认为深度优先。
    • DEPTH_PRIORITY = 1
    • SCHEDULER_DISK_QUEUE = \’scrapy.squeues.PickleFifoDiskQueue\’
    • SCHEDULER_MEMORY_QUEUE = \’scrapy.squeues.FifoMemoryQueue\’
    • 广度优先:不全部保留结点,占用空间少;运行速度慢
    • 深度优先:保留全部结点,占用空间大;运行速度快
    • https://www.cnblogs.com/zhaof/p/7092400.html

Git

git的使用生命周期

工作目录(你当前linux操作的目录)  >  暂存区   >  本地仓库 > 远程github

git的命令,就是将文件变化,在这四个区域,来回变动


初始化git版本库的方式,有三个

1.对已经有的代码进行 版本管理
我这台机器 已经有了一个django项目,对它进行管理

	1.对当前已经有的django项目进行git初始化
	git init 
	
	2.查看git状态
	git status  #查看git状态
	
        (gitlearn) [root@lht1 dj220]# git status
        # On branch master		#在master分支上
        #
        # Initial commit
        #
        # Untracked files:		#未标记的文件如下 
        #   (use "git add <file>..." to include in what will be committed)
        #
        #	dj220/
        #	manage.py


    3.git项目的第一次管理,初始化的流程
        1.git init  对django代码初始化
        2.git status 查看git版本库的状态
        3.对django代码,进行跟踪,标记 ,然后提交本地工作区的代码,到暂存区
        git add . 
	4.提交暂存区的代码,到本地版本库
	git commit -m "写入你的提交备注信息"
		# -m 是标记注释的意思
	
	5.查看git提交日志
	git log 
	
	6.git的各种命令,就是对四个区域来回切换,并且只能在git工作区下去敲
	必须得在含有.git文件夹的目录,去敲命令,才可以
	
	7.在git版本库目录下,新创建的文件,都会被标记为  Untracked files,代表未跟踪的文件
	
	8.对新创建的文件,进行跟踪 
	git add .
	
	9.修改django的url.py,写入新功能,也是对文件进行修改标记	modified
	对修改过的代码文件,也必须git add 添加到暂存区
	
	git add .
	
	9.2 commit 新版本  git commit -m "XXXXX"
	
	10.任何的对项目修改的操作,注意都要git status看一下
	
	
	11.查看git提交日志
	git log 
	
	12.git回退历史
	
	语法:	git reset --hard commit的id记录   --hard参数是强制性回退
	
	git reset --hard 954e6df1c0a2a71dd141850727d3eddd580518b3

	再次回到另一个提交版本信息,
	git reset --hard 2444fd8ed876eab2a95a697d039916510b356104
	
	13.git穿梭未来 
	git 回退,前进版本,其实就是是对git的文件指针,来回切换
	文件指针叫做head
	
	git reflog  #查看所有回退历史记录的命令
    然后再使用命令前进,其实就是修改了head指针
    	git reset --hard  
	
	14.撤回git修改的记录
	对已经跟踪的文件app01/views.py进行修改,此时标记为了modified:   app01/views.py
	c
	git add .
	如果你发现代码修改错了,git可以很方便的撤回
	git checkout -- 文件名
	git checkout -- app01/views.py 
	
	
	15.理解git命令
	git init  初始化一个git版本库,会生成一个.git 文件夹,此时这个目录就是git仓库了!!!
	
	16.修改git工作区的文件,重命名,以及删除文件
	
	linux的命令如下
	rm 	删除 
	mv  移动目录,或者重命名
	但是,你对git仓库中的代码,请使用git的命令
	git rm  删除git管理的代码
	git mv  对git管理的代码,改名
	
	17.git临时区的概念
	使用场景:
	git add  作用是?  是把本地工作区的代码,提交到暂存区
	git commit   将暂存区的代码,提交到本地版本仓库中,提交完毕,这件事就结束了 
	
	使用流程,场景,在你开发新功能的时候,突然线上代码有问题,你必须得改线上代码,
	将你目前已经开发好的功能,临时存储起来,
	待你修复bug完毕之后,再把这个临时存储的代码,回退回来即可
		:
		1.git stash  # 将你暂存区提交的代码,放到一个stash临时区中
		2.修复bug完毕
		3.拿回stash的代码
		git stash pop  
		
		4.查看stash是否还有临时代码
		git stash list 
		
		5.注意未标记的,已修改的文件,都得git add 添加到暂存区之后,才可以提交到本地仓库
		git add .
		
		6.如果你想提交这个代码
		git commit -m "提交注释信息"

	18.git分支功能,每个人都有自己的分支,不直接影响本体代码,在自己的分支上,写完代码后,通过管理员吧分支的代码,合并到主干上即可
	git branch  #查看当前所在的分支
	git branch  wupeiqi  #创建吴佩琪分支
	git branch  alex  #创建艾利克斯分支
	
	git checkout wupeiqi  #切换到吴佩琪分支
	
	分支开发使用流程
		1.创建新的分支
			git branch wupeiqi 
		2.切换分支
			git checkout wupeiqi 
		3.在分支下,写自己的代码
			........ add , commit 
		4.切换到主干分支上
			git checkout master 
		5.合并分支的代码,此时吴佩琪开发提交的代码,就被合并到master了
			git merge  wupeiqi 
		
	分支冲突怎么办?手动解决冲突的代码即可
	思路:master分支和wupeiqi分支,同时操作一个文件,对同一行代码进行写入
		
		0. git branch wupeiqi  创建另一个分支
		1.用master主干分支,操作一个文件,并且提交commit
		git branch #当前是主干master
		模拟对一个文件的第二行写入代码
		2.master提交本次修改记录
		git add . 
		git commit -m "提交注释"
		
		
		3.切换分支,也对同一个文件,进行写入代码,且提交
		
		git checkout wupeiqi 
		模拟对同一个文件,写入同一行代码,肯定会和master冲突
		git add .
		git commit -m "分支提交的注释"
		
		4.回到master主分支,合并吴佩琪分支,然后手动解决
		git checkout master 
		
		git merge wupeiqi 
		如果出现了冲突,就手动编辑这个文件,删除git自动添加的冲突注释
		
		5.再次提交
		git add . 
		git commit -m  "master最终合并的注释"
		
		
    6.git分支的命令
        git branch 分支名linux     创建分支linux
        git checkout 分支名linux    切换分支到linux
        git branch    查看当前分支情况,在哪一个就有*符
        git check -- filename 一键还原文件,将git仓库的文件覆盖当前文件,危险命令
        git checkout -b name  创建+切换新的分支
	
		
	
	
	
	
	




2.当前机器没有项目,直接进行git初始化,这个是管理一个空的目录

mkdir 目录名

git init 初始化这个空目录


3. 远程克隆下载一个项目,从github,或者gitlab  ********公司使用方式是他
远程克隆下载一个项目,从github,或者gitlab ,一台新的机器,啥也没有,把公司的代码下载出来,进行开发,以及版本管理








github的使用
1.注册一个github账号
https://github.com
2.登录后,添加创建一个新的github仓库,用于传输本地代码

3.新建github仓库,填写github仓库的名字,描述信息,以及redame文件,以及忽略文件(忽略编程语言的一些缓存文件)


4.添加ssh秘钥,让github和linux机器进行免密登录
	1.linux推送代码到github有2个登录方式 
	一个是账号密码方式
	一个是ssh秘钥方式
	
	2.选择ssh秘钥,安全性更高
	ssh是一个远程安全登录的命令,可以通过ssh-keygen命令生成一对公私钥(其实就是2个秘钥文件),然后把公钥发给github,私钥自己本地保留
	输入如下命令
				
				
			[root@fd dj220]# ssh-keygen   #这个命令生成一对公私钥,一路回车
			Generating public/private rsa key pair.
			Enter file in which to save the key (/root/.ssh/id_rsa): 
			Created directory \'/root/.ssh\'.
			Enter passphrase (empty for no passphrase): 
			Enter same passphrase again: 
			Your identification has been saved in /root/.ssh/id_rsa.
			Your public key has been saved in /root/.ssh/id_rsa.pub.
			The key fingerprint is:
			SHA256:ResKz3ErviC3OjbHe+Hqog2290YrqgCVlsMcpL+JUmg root@fd
			The key\'s randomart image is:
			+---[RSA 2048]----+
			| .o       .      |
			| + +     . .     |
			|. O       o      |
			| = .     o       |
			|oEo   . S o      |
			|oo o  .+.+ .     |
			|+ = .ooo=..      |
			|o. +Bo=+o.       |
			|..+=o@*+o.       |
			+----[SHA256]-----+
			[root@fd dj220]# 
			[root@fd dj220]# 
			[root@fd dj220]# cd ~/.ssh/
			[root@fd .ssh]# ls 
			#公私钥内容如下  id_rsa是秘钥   id_rsa.pub 是公钥 
			id_rsa  id_rsa.pub

	3.把公钥的内容,赋值粘贴发给github
		#查看如下内容,
		[root@fd .ssh]# cat id_rsa.pub 

		#将如下公钥信息,复制
		ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKfEGqHrIf8n6NrawBFt0/slRobTVuI9HoLxBWx0SdhIj+ATKgsEoVryG1S3WXulStNgDqF4dBSTRbNPFO/rrMdyURYRnSceQBKdNe+SmW2ttb/bfxd4JOnsC2ARCBK+DCTB48gtoSx+x4AUx3HGMUkOlgCjhHxk55CaMY8BtrBvdBAuOtUrv2RVOiheTTI+Sr8OJL/7lHEkZWGkW1n+xnx4/Urph4oa6lg8gQgFMWlLA9z5+cN8ZrQUi0MLX4p2e8sYfMnkzra5sSsUKQulqRsATaD8RK4FD+VEDWYwGfbdncCIMgiqol6gEQXKc4OJ/mU/xQMx5RQFwQGXW4hFFX root@fd

	4.此时你的linux 机器和github已经建立ssh通道了
	
	5.获取你的github项目仓库地址
	比如你的项目地址如下:
	git@github.com:examole/example.git
	

	6.在linux机器上配置远程仓库别名
	# git remote add 都是关键字  然后给你的github项目地址添加一个别名叫做origin 
	git remote add origin git@github.com:examole/example.git
    
	
	7.保证你的本地代码,和远程github仓库内容一致,如果不一致,会失败,先pull下载代码,保证一致性
	git pull origin master  #向远程的github origin别名下的master分支下载代码

	
	8.此时可以吧你本地的代码,推送到github仓库了
	#git push 是推送的意思  origin是远程仓库地址的别名  master 推到远程仓库的master分支上
	#得到git管理的版本仓库下敲
	 
	git push origin master 
	 
	9.去github去查看代码
	
	
	
到了公司里,给了你一个新电脑,该干啥???
	
	 1.配置ssh秘钥,方式在笔记上面
	 
	 
	 2.在一个目录,克隆一个新项目代码
	 git clone git@github.com:examole/example.git

	 3.在github仓库下,在浏览器中,新建一个分支,名字是development
	 
	4.下载最新的github代码
	  git pull origin
	5.此时项目,默认只有一个master分支,所以需要新建一个分支去开发,便于维护master的代码
	 #在本地新建一个dev分支,并且和远程的github的dev分支建立关系
	 
	 git branch development  origin/development 
	
	6.在项目中使用development分支去开发
		...开发代码省略...
	7.提交本地开发
	git add .
	git commit -m "分支提交了新的代码"
	
	8.提交分支本地的代码,到github中
	git push origin development 
	
	9.合并分支代码,推送到master主干线中
	git checkout master 
	git merge development #合并分支的代码
	git push origin master  #推送本地master的代码到github中
	
	 
	 
	 
git常用命令
git init 初始化
git status  查看git版本库的状态
git add 指定文件或者 . 
git commit -m "提交的注释"  提交暂存区的内容到本地仓库
git checkout  文件名  #撤回对文件的修改
git checkout 分支名 #切换不同的分支
git log   #查看git提交的日志记录
git reflog  #查看所有提交以及回退的记录
git reset --hard  commitID  #回退到某一个提交的id版本下
git config --global user.name "你的名字"
git config --global user.umail "你的邮件"
git branch   		#查看分支
git branch 分支名  #创建一个新的分支
git branch -d  分支  #删除这个分支
git checkout -b 分支名 #创建并且切换到一个新的分支下
git stash   #将暂存区的记录,临时放到一个区域 ,先git add之后,再git stash
git stash pop  #删除最后一个stash记录,放回暂存区
git rm  #删除git版本库中的文件
git mv  #改名
git remote add 别名 github仓库的地址
用法如下
git remote add origin git@github.com:examole/example.git

git push 别名 分支名  
用法
git push origin master #推送本地git仓库到github仓库了

git pull origin master  #下载github远程仓库到本地来





nginx git  yum  python  mysql redis  都是linux上的软件

gitlab私有仓库的搭建, github共有仓库不安全,虽然现在也有私有仓库的功能了
携程,美团运维开发组都是搭建的gitlab企业私有代码仓库
1.环境配置,至少4G内存的虚拟机

2.通过yum安装gitlab,阿里云的源也没有gitlab这个软件包
	解决方案:1.选择gitlab官网提供的yum仓库地址
	2.还是去找一个第三方,拥有gitlab软件包的yum仓库 
	3.配置清华大学的yum源
	找到yum仓库目录
	/etc/yum.repos.d
	然后手动创建一个 以.repo结尾的文件
	touch  gitlab.repo 
	4.写入如下信息
	cat gitlab.repo 
	[gitlab-ce]
	name=Gitlab CE Repository
	baseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el$releasever/
	gpgcheck=0
	enabled=1
	~              
	5.安装gitlab 
	yum install gitlab-ce 
	

	6.如何启动?
		确保服务器内存足够,可以用如下三个命令,清空buff内存缓存
		[root@DD-Server-9F ~]# echo 1 > /proc/sys/vm/drop_caches
		[root@DD-Server-9F ~]# echo 2 > /proc/sys/vm/drop_caches
		[root@DD-Server-9F ~]# echo 3 > /proc/sys/vm/drop_caches
			
			
		gitlab-ctl reconfigure 初始化gitlab,只能执行一次
		gitlab-ctl status/stop/start    启动gitlab
		gitlab-ctl status  #确保你的gitlab启动了

		
	访问方式:
	直接访问你linux服务器的ip即可,注意关闭linux防火墙(咱们学习阶段的配置)
	
	iptables -F #清空规则 
	systemctl stop firewalld 
	systemctl disable firewalld 
	#临时关闭selinux,也是一个防火墙
	setenforce 0
	#永久关闭selinux,修改/etc/selinux/config 
	修改如下参数
	

	
	
	
		通过浏览器访问页面服务器ip,默认开启了nginx的web端口,设置初始密码,操作类似github
		第一次访问会设置新密码 至少8个字符
		
		默认登录用户root
		密码11111111
		即可看到gitlab 
	
	2.启动了gitlab之后,修改了账号密码
	
	3.配置ssh公钥,发送给gitlab
	
	4.下载私有的gitlab仓库
	git clone git@192.168.15.62:root/s16gitlab.git

	5.进入gitlab下载的代码中,此时就可以pull push代码了
	

	

Linux

linux是操作系统的平台,安装了linux系统的机器,称为服务器

我们本地开发的机器 windows系统,测试开发使用

1.linux服务器,
有centos7发行版,有ubuntu,redhat发行版
手机(linux) 是个名词
redhat,ubuntu(华为,iphone)

2.物理服务器,真实的一台机器

3.阿里云服务器(用的最多的)
服务器的ip地址
服务器的账号
密码

4.如何登陆使用服务器呀
-你可以选择用xshell工具,远程登录linux服务器,去使用服务器的!!!!
-macos自带的 ssh命令
-secureCRT也是远程登录工具

5.用命令登录
ssh 用户名(linux服务器的那个用户,基本是运维给你创建的)

ssh root@服务器的ip

6.vmware workstation (虚拟化操作系统工具)
-下载你想要的操作系统,你可以去阿里云镜像站去下载
https://opsx.alibaba.com/mirror
-获取操作系统地址后,下载即可

LInux复习题

答案linux考试题

  1. 在登录Linux时,一个具有唯一进程ID号的shell将被调用,这个ID是什么(b)
    A.NID B.PID C.UID C.CID
    答:
    w命令查看用户tty终端信息
    ps -ef|grep pts/0
  2. 下面那个用户存放用户密码信息(b)
    A./boot B./etc C./var D./dev
  3. 用于自动补全功能时,输入命令或文件的前1个或后几个字母按什么键(b)
    A.ctrl B.tab C.alt D.esc
  4. vim退出不保存的命令是(d)
    A.:q B.q C.:wq D.:q!
  5. 文件权限读、写、执行三种符号的标志依次是(a)
    A.rwx B.xrw C.rdx D.rws
  6. 某文件的组外成员的权限是只读、属主是全部权限、组内权限是可读可写、该文件权限为(d)
    A.467 B.674 C.476 D.764
  7. 改变文件的属主的命令是(c)
    A.chmod B.touch C.chown D.cat
  8. 解压缩文件mydjango.tar.gz,我们可以用(a)
    A.tar -zxvf mydjango.tar.gz
    B.tar -xvz mydjango.tar.gz
    C.tar -czf mydjango.tar.gz
    D.tar – xvf mydjango.tar.gz
  9. 检查linux是否安装了,可用哪些命令(b) #注意rpm -qi只能查询用yum安装的软件,编译的查不到
    A.rpm -ivh nginx
    B.rpm -q nginx
    C.rpm -U nginx
    D.rpm -x nginx
  10. Linux配置文件一般放在什么目录(a)
    A.etc B.bin C.lib D.dev
  11. linux中查看内存,交换内存的情况命令是(c) #free -m
    A.top(任务管理器) B.last(用户最后登录信息) c.free() D.lastcomm
  12. 观察系统动态进程的命令是(b)
    A.free B.top C.lastcomm D.df
  13. 如果执行命令,chmod 746 file.txt ,那么该文件的权限是(a)
    A.rwxr—rw-
    B.rw-r—r—
    C.—xr—rwx
    D.rwxr—r—
  14. 找出当前目录以及其子目录所有扩展名为”.txt”的文件,那么命令是(d)
    A.ls .txt
    B.find /opt -name “.txt”
    C.ls -d .txt
    d.find -name “.txt”
  15. 什么命令常用于检测网络主机是否可达? c
    A.ssh(远程登录) B.netstat(查看Linux端口信息) C.ping D.exit(退出会话)
  16. 退出交互式shell,应该输入什么? d
    A:q! B.quit C.; D.exit
  17. 创建文件时父目录不存在,添加的参数是? d
    A.-P B.-d C.-f D.-p
  18. 下列文件中,包含了主机名到IP地址映射关系的文件是? b
    A./etc/hostname 主机名
    B./etc/hosts 强制写入域名解析记录
    C./etc/resolv.conf 存放dns服务器的文件
    D./etc/networks

    1. 查看网站的web服务器种类 curl -I 域名/ip
  19. 请问你使用的linux发行版是什么?如何查看linux发行版信息?
    centos7
    cat /etc/os-release
  20. 请问你公司的服务器环境是物理机还是虚拟化?
    500人企:
    26台dell power r720服务器,托管在世纪互联
    通过vmware esxi虚拟化的280+linux服务器,有100+centos 100+redhat
    分为三个环境
    测试服务器、预生产服务器、生产服务器
    技术栈:
    svn 、java、apache、tomcat、oracle、nagios、redhat、centos、weblogic
    初创企业:
    5台阿里云
  21. vim有几种工作模式
    命令模式
    编辑模式
    底线命令模式
  22. nginx的主配置文件是?如何实现多虚拟主机?nginx反向代理参数是?
    nginx.conf
    多个server{}
    proxy_pass http://ip
  23. 如何解压缩后缀是.gz文件?
    gipz -d *.gz
  24. 如何解压缩后缀是.tar文件?
    tar -xf .tar
  25. 如何解压缩后缀是.xz文件?
    xz -d .xz
  26. www服务在internet最为广泛,采用的结构是?
    Browser/Server
  27. 如何给linux添加dns服务器记录?
    /etc/resolv.conf
    添加2条主备dns记录
    nameserver dns服务器ip
  28. 每月的5,15,25的晚上5点50重启nginx
    ctontab -e 详情
    50 17 5,15,25 /usr/bin/systemctl restart nginx
    50 17 5,15,25 /opt/nginx112/sbin/nginx -s reload
  29. 每分钟清空/tmp/内容

/usr/bin/rm -rf /tmp/*

  1. 每天早上6.30清空/tmp/的内容
    30 6 /usr/bin/rm -rf /tmp/
  2. 每个星期三的下午6点和8点的第5到15分钟之间备份mysql数据到/opt/
    * * * * * 命令
    分 时 日 月 周 命令(绝对路径)
    5-15 18,20 3 /usr/bin/cp -r /var/lib/mysql /opt/
  3. 某文件权限是drw-r—rw-,请解读该权限?
    d:目录文件
    rw- 属主:可读可写
    r— 属组:可读
    rw- other:可读可写
  4. centos版本系统服务管理命令是?
    centos6 service
    centos7 systemctl
  5. 如何远程登录阿里云123.206.16.61?
    ssh root@123.206.16.61
  6. 备份mariadb的命令是?
    mysqldump -uroot -p
  7. 简述特殊符号的含义?
# root用户的身份提示符 或 注释符
$ 普通用户身份的提示符
. 当前目录
.. 上一级目录
- 上一次工作目录
$PATH  取值环境变量的值

> 重定向覆盖写
>> 重定向追加写


  1. 如果你发现在公司无法使用rm,使用提示’禁止你使用rm’,是为什么?
    别名alias 或者 配置了权限
  2. 如何修改test.py属组为alex?
    chgrp alex test.py
  3. 如何在windows和linux传输文件?有哪些方法?
    xftp (建立ssh)、lrzsz(拖动发送,rz,sz)、 scp(linux 之间)
  4. 如何杀死mariad进程?
杀死一个进程
ps -ef | grep mariadb
kill pid

杀死一组进程
pkill mariadb
killall mariadb
  1. 简述dns解析流程?访问www.pythonav.cn的解析流程
    自上而下的顺序
    1.优先查找本地dns缓存
    2.查找本地/etc/hosts文件,是否有强制解析
    3.如果没有去/etc/resolv.conf指定的dns服务器中查找记录(需联网
    4.在dns服务器中找到解析记录后,在本地dns中添加缓存
    5.完成一次dns解析
  2. linux如何安装软件?有几种方式?
    yum 自动解决依赖关系,只需要配置好yum仓库,适合安装各种小工具,并且不需要自定义的软件
    rpm 舍弃
    源码包 可以自由定制软件
  3. 出于安全角度,简述如何安装启动redis服务端?
    更改端口
    开启protomode yes安全模式
    设置redis密码
    redis-server redis.conf
  4. 如何保证本地测试环境和线上开发环境一致性?思路?
    1.docker打包镜像
    2.手动解决环境问题 pip3 freeze导出依赖
  5. virtualenv是什么?简述如何使用
在开发Python应用程序的时候,系统安装的Python3只有一个版本:3.4。所有第三方的包都会被pip安装到Python3的site-packages目录下。

如果我们要同时开发多个应用程序,那这些应用程序都会共用一个Python,就是安装在系统的Python 3。如果应用A需要jinja 2.7,而应用B需要jinja 2.6怎么办?

这种情况下,每个应用可能需要各自拥有一套“独立”的Python运行环境。
virtualenv就是用来为一个应用创建一套“隔离”的Python运行环境。

1.安装 pip3 install virtualenv
2.创建虚拟环境 virtualenv —no-site-packages —python=python3 env1
3.激活虚拟环境 sourcce /opt/MyVirtualenv/venvDjango1/bin/activate
4.测试 python3 或者 pip3 list

46.virtulevnwrapper是什么?简述使用

解决python解释器模块依赖问题的,可以在一台机器上,虚拟化出N多个解释器,解决环境隔离问题 

virtualenv 的一个最大的缺点就是,每次开启虚拟环境之前要去虚拟环境所在目录下的 bin 目录下 source 一下 activate,这就需要我们记住每个虚拟环境所在的目录。



Virtaulenvwrapper是virtualenv的扩展包,用于更方便管理虚拟环
1.安装虚拟环境 pip3 install virtualenvwrapper
2.创建并进入虚拟环境 mkvirtualenv env1
3.切换虚拟环境 workon 虚拟环境名


redis是什么?

Redis是一个开源的基于内存的,key-value数据结构的缓存数据库,支持数据持久化,m-s复制,
常用数据类型有string set hash list,

最佳应用场景:适用于数据变化的应用程序。
例如:股票价格、数据分析、实时数据搜集、实时通讯。
Redis只能使用单线程,性能受限于CPU性能,故单实例CPU最高才可能达到5-6wQPS每秒
(取决于数据结构,数据大小以及服务器硬件性能,日常环境中QPS高峰大约在1-2w左右)

redis持久化机制
rdb 
aof 

redis 相关  https://www.cnblogs.com/pyyu/tag/redis/

其他nosql数据库?

QPS每秒查询速度
Memcached可以利用多核优势,单实例吞吐量极高,可以达到几十万QPS(取决于key、value的字节大小以及服务器硬件性能,日常环境中QPS高峰大约在4-6w左右)

php + memcache开发的抢红包后台 

。适用于最大程度扛量。
只支持简单的key/value数据结构,不像Redis可以支持丰富的数据类型。
无法进行持久化,数据不能备份,只能用于缓存使用,且重启后数据全部丢失。

MongoDB   
更高的写负载,MongoDB拥有更高的插入速度,支持高可用性,支持索引高速查询,占用磁盘空间较大,支持持久化



redis主从复制

思路
1.通过redis.conf 支持多实例的数据库功能
2.在配置文件中添加
slaveof 127.0.0.1  端口 
即可配置主从关系

如果主从复制架构故障,master宕机,背景,一主两从,主6380,从6378、6381
解决思路

1.2个从库功能都还尚好,数据也在,第一步应该数据持久化,防止数据丢失

2. 6379  6381两个从库还活着,登录某一个数据,进行持久化,建立6379是主库,6381是新的从库
   redis-cli -p 6379 

    先save保存数据
    然后 slaveof no one

3.登录6381数据库,更改主从身份
	slaveof  127.0.0.1  6379 

手动切换故障如上

自动切换 redis哨兵功能

1.环境准备,三个redis哨兵(保安)配置文件 ,3个redis数据库配置文件  
-rw-r--r-- 1 root root 28 Apr 20 19:52 redis-6379.conf   三个redis数据库之间是端口的区分,和slaveof参数的区分 
-rw-r--r-- 1 root root 50 Apr 20 19:53 redis-6380.conf
-rw-r--r-- 1 root root 51 Apr 20 19:54 redis-6381.conf

三个哨兵配置一模一样,仅仅是端口的区分 
-rw-r--r-- 1 root root  0 Apr 20 19:51 redis-sentinel-26379.conf
-rw-r--r-- 1 root root  0 Apr 20 19:51 redis-sentinel-26380.conf
-rw-r--r-- 1 root root  0 Apr 20 19:51 redis-sentinel-26381.conf

4.分别启动三个redis哨兵,三个redis主从架构



5.启动正确,即,redis哨兵,能够自动切换主从故障

TODO  如果不懂可以在237视频最后一部分看到

  1. redis哨兵是什么?作用是
    Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案
    redis哨兵是监控redis主从服务,不存储数据的,作用是用于自动切换reidis服务主从关系,即当主库服务停止后,会将其中一个从库变为主库

  2. redis-cluster是什么?
    即使使用哨兵,redis每个实例也是全量数据存储,每个redis存储的内容都是完整的数据。
    为了最大化利用内存,可以采用cluster群集,就是分布式存储。即每台redis存储不同的内容。
    采用redis-cluster架构正是满足这种分布式存储要求的集群的一种体现。redis-cluster架构中,被设计成共有16384个hash slot。每个master分得一部分slot,其算法为:hash_slot = crc16(key) mod 16384 ,这就找到对应slot。采用hash slot的算法,实际上是解决了redis-cluster架构下,有多个master节点的时候,数据如何分布到这些节点上去。key是可用key,如果有{}则取{}内的作为可用key,否则整个可以是可用key。群集至少需要3主3从,且每个实例使用不同的配置文件。

​ redis-cluster搭建 详情 redis-cluster配置

  1. 什么是静态资源,什么是动态资源?
    静态资源指定的是网站的CSS/JS/HTML文件
    动态资源一般指的是数据,即后端给前端提供的数据
  2. 配置linux软连接的命令?
ln -s 目标文件名 软连接名

ln -s /root/大爷来玩呀   /tmp/hehe.txt

  1. 如何永久添加/opt/python36/的环境变量?
    vim /etc/profile 每次登陆都会加载这个全局文件
    添加PATH = /opt/python36/bin:
    source /etc/profile

52.给如下代码添加注释

server{ # 一个虚拟主机
	listen 80; # 监听的端口,访问的端口80
	server_name 192.168.11.11; # 访问的域名192.168.11.11
	location / { # 访问的路径 /  当你请求url是  192.168.11.11:80/
		root html; # 指定页面的目录,访问/会找到html目录
		index index.html # 指定网页,访问/就是访问index.html
	}
}





server{ #虚拟主机
	listen 8080; #nginx监听端口
	server_name 192.168.11.11; #nginx访问域名
	location / { #location匹配url
		include uwsgi_params; #将uwsgi参数添加进nginx
		uwsgi_pass 0.0.0.0:8000; #反向代理转发请求给uwsgi
	}
}

  1. supervisor是什么?如何使用? 后台管理进程任务的
你本来自己手动敲的命令,现在交给supervisor去管理 

使用:
1.安装 easy_install supervisor
2.生成配置文件 echo_supervisord_conf > /etc/supervisor.conf
3.写入自定义的配置
[program:crm] ; 项目名称
command=/root/Envs/knight/bin/uwsgi —ini /opt/knight/uwsgi.ini ;启动项目的命令
stopasgroup=true ;默认为false,进程被杀死时,是否向这个进程组发送stop信号,包括子进程
killasgroup=true ;默认为false,向进程组发送kill信号,包括子进程
4.启动supervisor服务
supervisord -c /etc/supervisor.conf
5.启动所有项目
supervisorctl -c /etc/supervisor.conf start all

54.简述项目部署流程?如何部署路飞,uwsgi+nginx+supervisor+nginx

部署路飞:
1.安装python3 环境
2.安装 mysql,redis,nginx
3.部署前端
    1.安装node.js的环境
    2.安装依赖包 npm instlal 
    3.修改axios的发送的端口接口  axios.get("后台接口的地址 ")
    4.打包
4.部署后端
    1.安装virtualenv
    2.创建虚拟环境
    3.安装django和uwsgi,以及项目的依赖包
    4.修改uwsgi的配置文件
	5.通过uwsgi -ini 配置文件启动django项目

5.配置nginx
    1.创建两个虚拟主机,分别监听80和8000端口
    2.访问80端口是访问呢vue
    3.访问8000端口是vue发起的8000端口请求,反向代理到9000的uwsgi
    6.启动nginx,mysql,redis
    7.通过supervisor来管理



  1. docker是什么?简述docker优势
    linux容器软件
    docker应用于快速构建应用,解决环境部署依赖的麻烦问题

  2. 你常用的docker常用命令有哪些?操作镜像、容器、仓库的命令

docker images # 查看本地镜像
docker serach 镜像 # 通过docker hub搜索镜像
docker rmi 镜像 # 删除镜像
docker save 镜像 > 路径 # 导出镜像
docker load < 路径 # 导入镜像
docker build -t . # 打包生成镜像,打包dockerfile生成docker镜像

docker的生命周期

开发写好 dockerfile ,docker build 生成镜像
镜像文件 就可以生成docker容器了,应用跑在docker容器当中

镜像文件,通过docker hub同一管理

镜像
容器
仓库

操作容器命令:
docker run -d 镜像 解释器 # 根据镜像生成容器,后台允许
docker run -it 镜像 解释器 # 根据镜像生成并进入容器
docker start/stop 容器id # 启动/停止容器
docker ps # 查看当前运行的容器
docker rm 容器id # 删除容器
docker exec 容器id # 进入当前正在运行的容器
docker commit 容器id 镜像名 # 将容器提交为镜像
docker contain ls # 查看当前运行的容器
操作仓库的命令:
docker pull 镜像 # 下载镜像
docker push 镜像 # 推送镜像

  1. 哪个命令无法查看linux文件内容? d
    A.tac B.more C.head D.man
  2. 使用rm -i 系统会提示什么信息? b
    A.命令所有参数
    B.是否真的删除
    C.是否有写的权限
    D.文件的路径
  3. 为何说rm -rf 慎用? -r递归删除 -f强制删除

60 .python操作linux的模块是? os,subprocess ,sys

  1. 如果端口8080被占用,如何查看是什么进程? netstat -tunlp | grep 8080

  2. redis是如何做持久化的?
    RDB AOF

rdb
定期执行save指令
Redis会定期保存数据快照至一个rdb文件中,并在启动时自动加载rdb文件,恢复之前保存的数据,通过save指令触发持久化,redis单独开启一个子进程进行数据持久化。
rdb缺点,定期执行,可能会丢失数据,并且数据量特别大时候,如果服务器cpu性能较低,rdb开启子进程持久化性能影响很大,影响redis对外提供服务的能力。

2U
4G内存

3G的数据 需要持久化

aof
Redis会把每一个写请求都记录在一个日志文件里。
在Redis重启时,会把AOF文件中记录的所有写操作顺序执行一遍,确保数据恢复到最新。
随着AOF不断地记录写操作日志,因为所有的操作都会记录,所以必定会出现一些无用的日志。大量无用的日志会让AOF文件过大,也会让数据恢复的时间过长。
优先:数据安全,不怕数据损坏,如断电等问题,还可以用redis-check-aof修复数据,AOF文件人为可读
缺点:占磁盘,性能损耗高,数据恢复慢

jemmory

怎么用rdb和aof
如果既配置了RDB,又配置了AOF,则在进行数据持久化的时候,都会进行,但是在根据文件恢复数据的时候,以AOF文件为准,RDB文件作废

  1. 简述mysql主从复制原理?
    (1) master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);
    (2) slave将master的binary log events拷贝到它的中继日志(relay log);
    (3) slave重做中继日志中的事件,将改变反映它自己的数据。

  2. 创建mysql用户alex,并且授予权限select权限,命令是什么?

useradd  创建linux用户 

create user alex@"%"  identified by  "alexdsb";

grant select on *.* to alex@’%’;


  1. nginx如何实现负载均衡?负载均衡的目录? 请求分流,解决单点机器的压力 ,压力平摊
123.206.16.61    access.log 检测用户来源ip  

upstream mydjango {
    server xxx   
    server  xxx 
    server xxx  
    ip_hash;  
}

uwsgi_pass mydjango   

  1. nginx的负载均衡调度算法有几种?是什么?

调度算法    概述
轮询     按时间顺序逐一分配到不同的后端服务器(默认)
weight    加权轮询,weight值越大,分配到的访问几率越高
ip_hash    每个请求按访问IP的hash结果分配,这样来自同一IP的固定访问一个后端服务器
url_hash   按照访问URL的hash结果来分配请求,是每个URL定向到同一个后端服务器
least_conn 最少链接数,那个机器链接数少就分发

  1. linux下载软件包的方法有?

wget

curl

yum

  1. windows和linux常用远程连接工具有哪些?

xshell

putty

securecrt

macos 自带 ssh

  1. 如何给与一个脚本可执行权限
    chmod u+x file

  2. 过滤出settings.py中所有的空白和注释行
    grep -v “^#” file |grep -v “^$”

  3. 过滤出file1中以abc结尾的行
    grep “abc$” file1

  4. 容器退出后,通过docker ps查看不到,数据会丢吗?

docker ps #查看的是正在运行的docker容器
docker ps -a #查看所有运行过的容器记录 ,这个容器挂了,但是没被删除

不会,因为docker ps -a 还能查到容器记录,数据存放在这个容器记录中

如果docker ps -a 也看不到或者被 docker rm 容器id 删除后,数据即丢失

  1. 如何批量清理后台停止的容器

docker rm docker ps -aq

docker ps -aq #取出所有的容器id号

docker ps -aq #代表保存这个命令的值

  1. 如何查看容器日志?

比如你的crm跑在docker容器中

docker logs -f 容器id ,查看容器正在运行的日志信息

tail -f

  1. wsgi是什么?
    WSGI是Web服务器网关接口。它是一个协议,描述了Web服务器(nginx,uWSGI)如何与Web应用程序(web框架 django flask )通信。

  2. Django中使用的是?
    wsgiref 是个单击socket模块,性能很低,用于测试django代码正常运行的

uwsgi 替代wsgiref
uwsgi –ini uwsgi.ini

uwsgi支持多进线程,让你的django,并发性更好
用nginx结合uwsgi,nginx处理静态文件,uwsgi处理动态请求,实现网站的高并发

答:Django中实现wsgi的是:wsgiref和uwsgi,wsgiref是开发测试用的,uwsgi是线上用的。
Flask中实现wsgi的是:werkzurg

Tornado中实现wsgi的是:tornado和gevent

greenlet

asyncio

  1. 消息队列的作用? 实现消息队列的软件,市面主流的有 kafka,rabbitmq,nsq,等等等….

1)程序解耦

2)数据冗余,例如rabbitmq的ack机制,消息确认机制
rabbitmq支持数据持久化,消息持久化

3)削峰能力
假设我本来业务,路飞本来只有 8个服务器,支撑业务正常运转
路飞突然有一天要做一个秒杀活动

4)可恢复性,就算系统中部分组件挂掉,消息在队列也不丢失,待组件恢复后继续处理消息。

5)异步通信,如发红包,短信等流程丢入队列,可以优先级很低的去处理。

git常用命令

本地工作区 git add
暂存区 git commit -m “注释”
本地代码仓库 git push
公网代码仓库 github

1:git init—————————初始化 ,这个文件夹就是一个git工作区了
2:git add .————————-从工作区,添加到版本库
3:git commit -m”xxx”————从暂存区,添加到分支
4:git status————————查看状态
5:git log —————————查看版本库的日志
6:git reflog————————查看所有日志,用于回退历史版本记录的
7:git reset —head 提交id号 —-切换
8:git stash————————-将暂存区中的数据,放到一个临时区
9:git stash————————-将第一个记录从“某个地方”重新拿到工作区(可能有冲突)
git stash list——————————————————————————查看“某个地方”存储的所有记录
git stash clear—————————————————————————-清空“某个地方”
git stash pop——————————————————————————-将第一个记录从“某个地方”重新拿到工作区(可能有冲突)
git stash apply —————————————————————————编号,将指定编号记录从“某个地方”重新拿到工作区(可能有冲突)
git stash drop —————————————————————————编号 ,删除指定编号的记录
10:git branch dev—————创建分支

11:git branch -d dev———-删除分支
12:git checkout dev————切换分支
13:git merge dev—————-合并分支 ,先切换到master分支,然后合并dev分支
14:git branch———————查看所有分支
15:git clone https:xxx——-克隆 ,在一个新的机器上,如果没有代码,可以从github克隆一个
16:git add origin https:xxx-起个别名
17:git push origin dev ——添加到dev分支
18:git pull origin master—拉代码
19:git fetch origin master-去仓库获取
20:git merge origin/master-和网上下的master分支合并
协同开发:
默认线上diamante是master分支——————————master
开发的分支—————————————dev
做代码review————————————review(代码审计的分支 )

程序员自己的分支——————————…….
1:每个员工创建自己的分支
2:将自己的代码提交的到自己的分支—————xxx,sss,wwww…….
3:由组长或老大做代码的review,——————-代码提交的review分支
4:再提交到dev.
5: 再合并到master分支

熟悉 Linux常用操作。
1:man rm———————————————查看命令帮助
2:mkdir———————————————-创建目录
3:touch———————————————-创建文件
4:cd—————————————————切换。
5:ls—————————————————查看目录
6:ls -lh————————————————查看目录详细
7:pwd————————————————-查看当前目录
8:vim————————————————-添加内容
9:echo————————————————追加内容
10:cat————————————————查看文件内容
11:mv————————————————-移动
12:cp————————————————-拷贝
13:mv————————————————重命名
15:find———————————————-搜索
16:rm————————————————-删除数据
17:ping———————————————-查看能不能上网
19:tar cf ————————————————打压缩
20:tar xf——————————————-解压缩
安装:
yum install
rpm包安装
编译安装
快捷键:
1:Tab键—————————————-自动补全命令或路劲。
2:ctrl+l—————————————清屏
3: ctrl+c—————————————取消当前操作
4:vi/vim 快捷键:
复制当前行 ——————————yy
粘贴—————————————-p
剪切—————————————-dd
撤销—————————————-u
恢复—————————————-ctrl + r

路飞项目

项目介绍

2012年 -> 卖视频 1000RMB

2014年 -> 和51CTO合作, 老师直播答疑, 3000RMB ~ 5000RMB

2015底, -> 一对一导师服务, 6到7K

2017年7月 做路飞

通过一些技术的手段, 让学员在线上也可以学的更好.

项目架构

  • 主站(供广大用户访问, 在上学习)
    • luffiyadmin root123456
  • 管理后台(运营维护网站站点)
  • 导师后台(供导师使用的)

组织结构

  • CEO (架构师, 把控项目的进度, ) 1
  • 产品(提需求, ) 产出 -> 原型图, 产品需求文档 1
  • UI 根据原型图 产出 -> 设计图 1
  • 开发(前端1, 后端各一个, 1写管理后台) -> 概要设计文档 –> 评审 ——》开发
  • 测试 (测试) 产出 -> 测试用例, 测试
  • 运维 (上限) 部署项目架构, 项目上线
  • 运营

技术栈

  • nginx
    • web服务器, 动静分离, 负载均衡, 反向代理
    • 提高网站的并发性
  • uwsgi
    • 网关接口, 用来连接 django服务和nginx服务的桥梁
  • django+drf
    • 实现业务逻辑
  • vue
    • 前端的页面渲染
  • mysql 重点
    • 提供数据服务
    • 索引, 事务,
  • redis 重点
    • 提供缓存服务
    • 为什么要用redis(减小数据库的压力, 读取效率高, )
    • redis的数据类型你都有哪些业务场景,
  • jwt
    • 用户认证系统
  • jenkins
    • 自动化部署的工具
    • CI 持续集成
  • sentry
    • 错误日志的收集管理工具, 提供了一个web页面让你的错误信息可视化
    • logging除了可以做错误日志信息的收集, 还可以做用户日志分析.
  • celery
    • 异步和定时任务
      • 发送邮件
      • 超过24小时订单关闭
      • 导师超过24小时未跟进惩罚
  • 第三方的服务
    • 微信和支付宝的支付, 通知消息
    • 视频服务
    • 短信服务
    • 滑动验证

项目周期

  • 第一版本(2017-07 ~~ 2017-11, 一直处于一个维护的阶段至新年)
    • 课程
      • 课程的展示, 专题课和学位课
    • 用户
      • 登录注册/短信登录
      • 滑动验证码
    • 支付
      • 从课程页面点击立即购买, 跳转到确认订单页面
      • 触发确认订单的接口, 用户的购买信息(课程ID, 有效期ID), 后台校验并验证, 课程, 返回课程信息, 返回可用的课程优惠券, 通用优惠券, 可用的虚拟货币, 让用户选择最优支付方案, 进行支付, 校验通过, 生成订单, 根据用户选择的支付方式, 生成支付链接, 跳转, 让用户进行支付, 支付成功之后, 修改订单状态, 创建用户报名的课程.
      • 策略模式,支付,课程优惠券,通用优惠券,贝利,
      • 存储,临时数据,操作频繁
    • 购物车
      • 缓存数据结构
    • 奖惩体系
      • 导师超过24小时未跟进扣导师费
      • 未批改作业扣费
    • 视频服务
      • 自己做 不安全
      • 保利威视频服务
    • 资讯
      • 类似于博客
  • 第二版本(2018-03 ~~ 2018-07, 题库)
    • 爬虫, 人为出题
    • 进行用户的行为埋点, 比如说 用户观看的视频数, 某个视频次数, 观看视频的时长, 错题情况, , 多个系列的维度, 可以给它推荐题.
  • 第三版本(2018-08 ~~ 2018-12, )
    • 问答系统(学员提问题, 导师回答)
    • 评价系统(评价作业, 评价跟进信息, 评价回答信息)
    • 网站改版, 业务逻辑并没有多大变化,(维护你的项目)

项目中遇到的问题

  • 产生重复订单的问题 (网络不好,前端页面没反应,用户多次下单)
    • 前端
    • 后端
  • 用户支付成功, 服务宕机了, 如何解决
    • 1, 第三方支付平台, 每隔2分钟, 4分钟, 8分钟, 在没有响应正确的字符串的情况下, 24个小时
    • 2, 定时任务, 每隔一段时间, 查询未支付成功的订单, 根据订单号根据支付方式, 去第三方平台查询是否支付成功
  • 在服务器上跑, 经常会抛出内存错误,
    • uwsgi + django 观察, 把问题规模不断地进行缩小,
    • 结果,调整的uwsgi的配置参数, workers, 调优, 服务器的横向扩展
  • 遇到不会写的情况
    • 画流程图
    • 伪代码

项目的亮点

  • 项目优化做的特别好
    • 项目文档设施很完善(开发说明文档)
    • 代码格式很规范, 遵守PEP8规范,
    • git协作开发
  • 抽离出很多公共的代码, 让它复用性很强, 不要重复造轮子
    • 支付, 短信, 业务层面
  • 项目架构很好
    • 扩展性好等等

扩展

  • redis
    • 为什么要用redis? (缓存数据库, 非关系型数据库)
      • 读写速度快, 丰富的数据类型, 支持持久化
    • 数据类型的业务应用
      • 购物车, redis, 哈希, 字符串, 比如说 哈希 {“SHOP_CART”: “UID”: “json数据结构”}
      • 字符串结构自增, 学习人数, 点赞
    • 做好宕机的准备
      • 集群, 哨兵监控
      • 持久化(AOF, RDB)
  • mysql数据库是怎么设计的, 数据库优化
    • 数据库引擎选型,
    • 建索引,
    • explan 分析sql语句, 用索引
    • 慢日志查询
    • 为什么要用读写分离, 好处: ….

学习链接

第三方服务

sentry

日志

ck-editor

富文本编辑框

说明: https://www.jianshu.com/p/65d2a748634b

读写分离

email

视频配置

  • 保利威服务

logging配置

last day

今日内容

  1. 模拟面试(回顾和补充)
  2. 简历的撰写
  3. 就业标准(工作)
  4. 复习计划 ( 执行力 )

模拟面试


    • python怎么学的? 有运维经验.
    • 组织架构.
      • git合并时间.
      • 代码review
      • git知识补充:
        • git是做版本管理的 ( SVN & VSS)
        • git + github / 码云 / gitlab
        • 分支
          • master
          • release,发布版本
          • dev , 开发版本
            • 张扬
            • 张阳
            • 张杨
          • 合并(小的功能2左右)
          • 代码review , 组长.
        • git 命令 , 笔试题.
          • git add .
          • git commit -m \’xx\’
          • git push origin master
          • git pull origin master
          • git stash
          • git branch
          • git reset …
          • git merge
          • git rebase
        • 你想要给开源的项目贡献代码:
          • fork
          • 在自己仓库进行修改
          • pull request 提交给作者
        • 先进行pull再进行push提交.
        • 敏捷开发(看板) 任务管理工具
          • 禅道
          • tower
          • 蒲公英
        • 软件:compare
        • 其他:
          程序员入职之后会有几个账号: 钉钉 / 邮箱(周报/日报) / git 账号 / 禅道 / VPN .
    • 运维项目(*)
    • 爬虫
      • 用什么做的?
        • requests
        • selenuim
        • scrapy
        • 分布式爬虫
      • 爬虫面试:
        • 案例
          • 滑动验证码
          • 数据量级 一天爬多少数据
          • 神箭手 第三方爬虫
        • 数据结构 + 消息队列
        • 给问题让你解决

    • 函數有什麽坑?

      def func(a,b=[]):
          pass
      
      
    • 装饰器的应用场景?

      • flask路由系统.
      • filter
      • inclustion_tag
      • simple_tag
      • 用户认证(不推荐)
      • csrf_token
    • 手写装饰器:不带参数和带参数

      • 不带

        def wrapper(func):
            @funtools.wrap(func)
            def inner(*args,**kwargs):
                return func(*args,**kwargs)
            return inner 
        
        
      • 带参数

        # 写装饰器实现让被装饰的函数执行N次
        def x(count):
            def wrapper(func):
                @funtools.wrap(func)
                def inner(*args,**kwargs):
                    for i in range(count):
                        data = func(*args,**kwargs)
                    return data
                return inner 
            return wrapper
        
        
        @x(5)
        def func():
            pass
        
        
    • 面向对象中的双下滑方法.

    • 单例模式

      # 错误示例
      class Person:
          _obj = None
          def __new__(cls):
              if cls._obj is None:
                  cls._obj = super().__new__(cls)
               return cls._obj
      
      
      import threading
      
      class Singleton(object):
          _instance = None
          _lock = threading.RLock()
      
          def __new__(cls, *args, **kwargs):
              if cls._instance:
                  return cls._instance
              
              with cls._lock:
                  if not cls._instance:
                      cls._instance = super().__new__(cls, *args, **kwargs)
                  return cls._instance
      
      
      
      class Foo(object):
      
          def __setitem__(self, key, value):
              pass
      
          def __getitem__(self, item):
              pass
      
      
          def __delitem__(self, key):
              pass
      
      obj = Foo()
      
      obj[\'k1\'] = \'alex\'
      obj[\'k1\']
      del obj[\'k1\']
      
      
      
      class Foo(object):
      
          def __enter__(self):
              print(\'进入\')
              return 123
      
          def __exit__(self, exc_type, exc_val, exc_tb):
              print(\'退出\')
      
      obj = Foo()
      with obj as f:
          print(f)
      
      
      class Foo(object):
      
          def __call__(self, *args, **kwargs):
              pass
      
      
      Foo()()
      # flask源码入口
      
      
    • 手写栈

      class Stack(object):
          
          def __init__(self):
              self.data = []
          
          def push(self,value):
              self.data.append(value)
          
          def pop(self):
              return self.data.pop()
          
      obj = Stack()
      obj.push(\'alex\')
      obj.push(\'eric\')
      val = obj.pop()
      print(val)
      
      
    • 你如何理解面型对象的三大特性?

      • 封装

      • 继承,哪里用过继承.( drf的视图 )

      • 多态(什么是鸭子模型)

        class Foo(object):
            def xxxxx(self):
                pass
            
        class Base(object):
            def xxxxx(self):
                pass
            
        def func(arg):
            arg.xxxxx()
            
        obj1 = Foo()
        obj2 = Base()
        
        func(obj1)
        func(obj2)
        
        

      • 什么是反射?
        通过字符串形式去一个对象找到指定的属性.

      • 反射应用场景:

        • crm, 公户和私户的处理(下拉框action)

        • cbv

           def dispatch(self, request, *args, **kwargs):
                  # Try to dispatch to the right method; if a method doesn\'t exist,
                  # defer to the error handler. Also defer to the error handler if the
                  # request method isn\'t on the approved list.
                  if request.method.lower() in self.http_method_names:
                      handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
                  else:
                      handler = self.http_method_not_allowed
                  return handler(request, *args, **kwargs)
          
          
        • django配置文件(中间件)

        • restful api

      • TCP三次握手和四次挥手

      • osi 模型

      • c/s 和 b/s

      • 简述http和 https协议.

        • http协议:

          • 连接状态:一次请求一次响应然后断开连接.

          • 数据传输格式:

            client = socket.socket()
            client.connect((...))
            client.sendall(b\'GET /s?wd=alex HTTP1/1\r\n.....\r\n\r\n\')
            client.sendall(b\'POST /s?wd=alex HTTP1/1\r\n.....\r\n\r\nname=alex&age=19\')
            
            
          • 常见问题:

            • 状态码
            • 常见请求头
            • 常见请求方式
        • https: ca证书 + SSL

        • websocket: 双工 / 魔法字符串 magic string

      • 进程线程协程的区别?

      • IO多路复用:select / poll / epoll 的区别.

      • GIL锁

第一章 知识点串讲

1.1 Python基础

  1. 解释型语言和编译型语言的区别?

  2. 你除了python以外还会哪些编程语言?

  3. 你为什么选择python?

    - 语法简洁
    - 从诞生之初,类库丰富,不用重复造轮子.
    - 大势所趋:
        - 底层算法/api
        - 应用开发
    
    购买现成的解决方案.
    
    
  4. 列举你常用数据类型及其中的方法.

  5. 深浅拷贝 ?

    # 针对可变类型: list,dict,set
    # 浅拷贝:拷贝第一层
    # 深拷贝:所有层的可变类型都会被拷贝.
    
    
  6. is 和 == 的区别?

    is是内存
    ==值
    
    
  7. 看代码写结果

    v = 1 or 2
    v = 0 or 6
    v = 1 and 2 
    v = 0 and 2 
    
    
  8. 给你一个大文件,如何查看所有内容?

    # for 文件对象
    
    # tell 和 seek
    
    
  9. 列举常用的内置函数?

    len
    range
    open
    help
    type
    id 
    bin/hex/oct/int
    filter/map/zip
    enumrate
    divmod
    
    
  10. filter/map/reduce 的作用?

  11. 比较两个值

    v = (1)
    v = (1,)
    
    
  12. 列表推导式

    v = [i for i in range(10)]
    
    v = [lambda:i for i in range(10)]
    print(v[0]())
    print(v[9]())
    
    
    def func():
        return [lambda:i for i in range(5)]
    v = [m() for m in func()] # [4,4,4,4,4]
    
    
  13. (i for i in range(10)) 和 [i for i in range(10)] 的区别?

  14. def func(a,b=[]):pass 有什么陷阱?

  15. 看代码

    def func(a,b=[]):
        b.append(a)
        return b
    
    l1 = func(1)
    l2 = func(2,[11,22])
    l3 = func(9)
    print(l1,l2,l3) # [1,9]   [11,22,2]    [1,9]
    
    
  16. 装饰器: 不带参数 和 带参数(手写)

  17. IP地址转换

  18. 常用内置模块?

    os/json/time/re/datetime/sys
    
    
    
  19. 你了解的第三方模块

  20. re中match和search的区别?

  21. 正则中什么是贪婪匹配?

  22. 如果获取一个目录中的所有文件?

    import os
    
    # os.listdir,只能获取一级目录.
    # for path in os.listdir(\'src\'):
    #     print(path)
    
    # os.walk,获取目录中所有文件.
    for path,folder,files in os.walk(\'src\'):
        for file in files:
            file_path = os.path.join(path,file)
            print(file_path)
    
    
  23. 列举你了解的双下划线方法?

  24. __call__方法的作用?

  25. __new__方法的作用?

  26. 手写栈

  27. 单例模式(加锁)

  28. 面向对象中的上下文管理指的是什么?

    class Foo:
        pass
    
    with Foo() as f:
        pass
    
    
  29. 都在哪里用过继承? drf时都继承哪些类?

  30. 写输出

    class Parent(object):
        x = 1
        
    class Child1(Parent):
        pass
    
    class Child2(Parent):
        pass
    
    
    print(Parent.x, Child1.x, Child2.x) # 1 1 1
    Child2.x = 2
    print(Parent.x, Child1.x, Child2.x) # 1 1 2
    Parent.x = 3
    print(Parent.x, Child1.x, Child2.x) # 3 3 2
    
    
  31. @classmethod和@staticmethod有什么区别?

    类方法: 类直接调用; 至少有一个cls参数.
    静态方法:类直接调用;可以有任意个参数.
    
    
  32. Python垃圾回收机制?

1.2 网络并发编程

  1. cs和bs架构?

  2. osi 7层模型/5层/4层

  3. TCP三次握手四次挥手

  4. 什么是粘包?

  5. http协议

  6. 常见http请求头/常见请求方式/常见状态码

  7. https协议(非常重要)

  8. websocket协议

    • 意义: 实现服务端向客户端主动推送消息(双工通信)
    • 实现原理:
      • 握手: 随机字符串+magic string (必须)
      • 数据加密: 127/126/125
  9. 进程/线程/协程的区别?

  10. 什么是GIL锁?

    一个进程中同一时刻只有一个线程被cpu调度.
    # 无法保证数据安全
    
    
  11. IO多路复用,select/poll/epoll区别?

    • 作用: 监听多个socket是否发生变化(新连接/新数据到来).
    • 区别:
      • select, 最多监听1024个; 轮训 (水平触发).
      • poll, 最多监听无数个; 轮训 (水平触发). .
      • epoll, 最多监听无数个; 回调.(边缘触发)
  12. 进程之间如何实现数据共享?

    queue
    manager
    pipe
    第三方: redis/rabbitMQ/socket
    
    

1.3 MySQL

  1. 数据的引擎以及区别?

    • innodb
      • 支持事务
      • 支持行锁/表锁
    • myisam
      • 不支持事务
      • 表锁
  2. char和varchar的区别?

  3. char(50) 中的50是什么意思?

  4. left jon 和inner join的区别?
    部门表 depart

    id title
    1 运营
    2 销售
    3 技术

    用户表 user

    id name depart_id
    1 铁帅 1
    2 耀中 1
    3 张阳 2
    select * from user left join depart on user.depart_id = depart.id  # 3条数据
    
    select * from depart left join user on user.depart_id = depart.id  # 4条数据
    
    select * from depart inner join user on user.depart_id = depart.id  # 3条数据
    
    
    
  5. 联合索引: (a,b,c) [最左前缀]

    • a,b
    • b,c 无法命中
    • a,c
    • a,b,c
  6. 函数和like都是无法命中索引.

    select * from user where name like \'%ex\'
    
    select * from user where 函数(name) like \'%ex\'
    
    
  7. 存储过程/触发器/视图

  8. 数据库优化方案

    • 建索引 + 命中索引
    • 固定长度在前面
    • 特定数据放内存,不要创建表来进行存储(避免连表操作)
    • 允许数据冗余,不建额外表(少了连表操作).
    • 读写分离
    • redis做缓存
    • 分库分表
  9. 数据库设计 ( 重要 )

    • fk
    • m2m
  10. SQL语句 (最重要)

1.4 前端

  1. 什么是响应式布局?

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/css/bootstrap.css" rel="stylesheet">
        <style>
            .bg{
                background-color: red;
            }
            @media (min-width: 768px) {
                .bg{
                    background-color: green;
                }
            }
        </style>
    </head>
    <body>
        <!--<div class="row">-->
            <!--<div class="col-md-6">坐标</div>-->
            <!--<div class="col-md-6">右边</div>-->
        <!--</div>-->
        <div class="bg">asdf</div>
    </body>
    </html>
    
    
  2. js作用域

    <script>
        
    var name = \'oldboy\';
    
    function f1(){
        console.log(name);
    }
    
    f1()
    
    </script>
    
    
    <script>
        
    var name = \'oldboy\';
    
    function f1(){
        console.log(this.name); // window
    }
    
    window.f1()
    
    </script>
    
    
    <script>
        function f1(){
            console.log(213);
        }
        f1()
        
        (function(arg){
            console.log(arg);
            console.log(this)
        })(123)
    </script>
    
    
    info = {
        user:\'alex\',
        func:function(){
            console.log(this); //info
        }
    }
    
    info.func()
    
    
    name = \'alex\'
    info = {
        name:\'eric\',
        func:function(){
            console.log(this.name); // eric
            
            function f1(){
                console.log(this.name); // alex
            }
            f1()
        }
    }
    
    info.func()
    
    
    name = \'alex\'
    info = {
        name:\'eric\',
        func:function(){
            console.log(this.name); // eric
            var that = this;
            function f1(){
                console.log(that.name); // eric
            }
            f1()
        }
    }
    
    info.func()
    
    
  3. 跨域

    • jsonp (面试)
    • cors
  4. bootstrap常用的样式.

1.5 django框架

  1. django和flask的区别?
  2. django 路由中的别名 / include 路由分发
  3. FBV和CBV
  4. request对象中都用过哪些方法?响应时都返回过哪些对象?
  5. ORM ( 练习题 ) 重点中的重点 , 请补充.
  6. django中如何执行原生SQL ?
    • raw
    • extra
    • connections (最原生)
  7. django如何实现数据库读写分离?
  8. 模板拔高:
    • filter
    • simple_tag
    • inlusion_tag
  9. 中间件
    • 执行流程
    • 应用场景: 权限 / 用户认证 / 白名单 / csrf
  10. Form和ModelForm
  11. django的缓存如何实现?
  12. django中信号的作用?

1.6 爬虫 & 数据分析

1.7 Linux架构

  1. redis有哪些数据类型?
  2. redis中中RDB和AOF的区别?
  3. redis中如何实现读写分离?
  4. redis中的有多少哈西槽?
  5. redis分布式锁是什么?
  6. rabbitMQ和kafka的区别?
  7. 什么时rpc?
  8. git如何做协同开发?
  9. git常见命令?
  10. 如何做代码review?
  11. git 如何给开源项目贡献代码?

1.8 项目:CRM

1.9 项目:路飞学城

1.10 项目:智能玩具 & Flask

1.11 项目:代码发布

第二章 简历示例

2.1 个人技能

  • 熟悉 Python、了解Golang
  • 熟悉 Django、Flask、Tornado等Web框架
  • 熟练 HTML、CSS、JavaScript、jQuery等
  • 熟练 VUE、Ajax、JSONP、CORS、BootStrap、跨域等前端技术
  • 熟悉MySQL、存储过程、触发器器、索引
  • 熟悉 Redis、主从、分布式cluster
  • 熟悉 celery、RabbitMQ 消息队列的使用
  • 熟悉 Python⽹网络编程、IO多路路复⽤用
  • 熟悉 多线程、多进程、协程、异步非阻塞等
  • 熟悉 Scrapy框架和分布式爬⾍虫框架redis-scrapy组件
  • 熟悉 爬⾍虫相关Requests和BeautifulSoup模块使⽤用
  • 熟悉 常⽤用算法如冒泡、快排、堆排、希尔等;
  • 熟悉 Git
  • 熟悉 WebSocket
  • 熟悉 Linux、ansible、saltsack、docker

2.2 项目经验

2.2.1 CRM

  • 其他名称:SPATA系统/SELL系统(推荐)

  • 项目介绍
    随着公司日益发展以及市场和销售人员日益扩展,完成销售流程的规范化以及标准化并在SELL系统对员工进行行监管,项目主要用于为公司销售⼈员、运营、售后等⼈员提供公共的处理平台,在公司发展的过程中以便便实现信息的管理, 实现公司的信息化流程。为销售人员工提供客户关系的管理,对于新客户信息的录入和等级。定期对客户进行回访和跟进,从而增加用户粘性,便便于之后的转化。运营和渠道通过关系以及人脉获取有效客户,可以进⾏行录⼊和分配。

  • 项目功能
    SELL主要⽤用于为销售、渠道人员以及管理理者实现⼀个规范化的平台,为了防止销售之间存在的”恶意”或”非恶意”竞争,避免有人进⾏抢单导致部门不和谐因素

    实⾏公户和私户管理理,公户主要存放未指定销售的客户信息,公户可有两种⽅式进⾏分配到私户,第⼀种是销售⾃己申请,第⼆种是主管进⾏行行主动分配.

    私户主要存放⾃己的客户,在申请客户时基于数据库事务/锁保证数据安全,从⽽安全将客户申请到⾃己的账户.批量量操作时候action… / 模糊搜索等操作。

    项⽬中继承了⼀个独立的权限组件,权限组件主要⽤于为让各种⻆色的客户仅能访问⾃己拥有的功能,⽆无权越级访问,权限基本使用流程涵盖了了一下知识点,如:⽤户认证,将权限和菜单信息放⼊session/用户访问,在中间件中进行权限校验(⽩名单)/动态菜单,使⽤用inclusion_tag定制菜单的显示.

  • 项目相关问题

    • CRM系统是什么?里面都有哪些功能(业务)?
    • 什么是公户?什么是私户?为什么要做这个区分?
    • 请列举出CRM系统中的表。
    • 对数据库的数据做展示时,不同字段类型有不同的展示方法,分别是什么?
    • 请详细说说你们公司销售是如何使用CRM的。
    • 详细说说班主任是如何使用CRM的。
    • CRM中有哪些技术点,用于做什么(至少写出5个)?
    • 为什么不用现成的crm而是自己去开发?
    • 权限有多少张表?每张表中有哪些字段?(5分)
    • 请简述实现权限控制的流程。(10分)
    • 初始化权限时,定义了两个字典,分别是什么数据结构?为什么要把他们存在session中?
    • 权限校验的中间中都做了什么事情?
    • 如何实现二级菜单默认展开并且是选中状态的?
    • 权限控制到按钮级别是如何实现的?
    • 权限批量操作时,哪些权限是需要新增的?哪些是需要删除的?哪些是可更新的?
    • 开发过程中遇到问题,一般都是怎么解决的?请说一下你印象比较深刻的一个问题。
    • 请简述下管理权限信息的流程(管理、分配权限是如何操作的)?
    • rbac组件中有哪些技术点,用于做什么(至少写出5个)?

2.2.2 路飞学城

  • 其他名称:智慧树、猿辅导等

  • 项目介绍
    路⻜学城是⼀个基于Python和Django开发的平台,平台的⽬标致力于提升在线学习的完课率,目前在线教育领域都是在线看视频的方式,路飞学城从开创最新“一对⼀”模式辅导,实现导师每天跟进并定期考核制度,除次之外执行学、练、改、管、测五位⼀体的教学⽅法以及奖惩措施,以此促进完成学成率。

  • 项目功能
    路飞学城共包含三⼤大部分,即:导师平台、管理理平台、在线平台(APP),导师后台主要对导师进⾏行行跟进和考核监管,对导师采⽤用扣“奖金”措施来督促导师跟进率。管理后台主要⽤用于运操作管理,可以对于深科技和咨询信息的录⼊和编辑,除此之外还可以对课程上传管理以及学⽣休学和提现管理。

    在线平台部分主要为vue和app提供接口功能,接口基于django rest framewok框架的基础搭建,利用其内置组件和⾃定义扩展实现⽤户认证和访问频率限制,根据依赖django-redis组件实现对缓存的操作,将⽤户访问记录放⼊入redis实现认证操作。

    在线业务主线主要将课程分为“学位课”和“专题课”,基于django contenttype组件实现课程多价格策略,为了减轻数据库压力将临时购买信息放⼊redis以便便操作,购物流程包含 ⻉里、优惠券、⽀付宝联合支付。在线通知使⽤用阿⾥短信接⼝和“微信服务号”模板消息对购买、提交作业、咨询等信息的提醒。最后整合第三⽅美洽、CC视频、保利威视在线咨询以及在线视频播放的功能。

  • 项目相关问题:

    • 简述rest ful 规范.
    • drf提供了哪些组件?
    • drf时都继承过哪些视图类.
    • jwt的原理?
    • 路飞学城有跨域吗?如何解决的?
    • 购物车用redis做的时候,其结构长什么样子?
    • 支付宝用的什么加密:?
    • 视频是如何实现加密的?
    • 支付寶支付完成时,服务器宕机怎么办 ?
    • 如果避免点击按钮生成重复订单 ?
    • 公司的组织架构?
    • 如何做的协同开发?

2.2.3 智能玩具

  • 介绍
    关爱留守儿童, 让玩具成为父母间沟通的媒介, 建立沟通的桥梁,让玩具成为孩子的玩伴,实现无屏社交,依靠孩子的语音指令做出响应,例如我要和爸爸聊天,玩具会提示可以和爸爸聊天了并打开与app通讯的链接,我要听世上只有妈妈好,玩具就会依照指令播放相应的内容

  • 功能

    • 基于Websocket实现语音IM通讯
    • 基于MUI实现app移动端应用布局
    • 基于HTML5PLUS实现移动操作系统的硬件驱动调用及系统调用
    • 基于MongoDB实现数据存储
    • 基于Redis实现离线消息存储
    • 基于BaiduAI开放技术实现语音合成和语音识别
    • 基于gensim LSIModel 语言模型实现词语训练
    • 基于gensim 稀疏矩阵相似度实现文本相似度匹配
    • 基于jieba 实现语音指令分词
    • 基于pypinyin 实现中文同音字识别
  • 相关问题

    • 说说你智能玩具的项目?
      目的:关爱留守儿童, 让玩具成为父母间沟通的媒介, 建立沟通的桥梁,让玩具成为孩子的玩伴,实现无屏社交,依靠孩子的语音指令做出响应,例如我要和爸爸聊天,玩具会提示可以和爸爸聊天了并打开与app通讯的链接,我要听世上只有妈妈好,玩具就会依照指令播放相应的内容。

    • 说说智能玩具有什么功能?
      玩具可以语音点播朗诵诗歌,播放音乐,做游戏-成语接龙,与智能机器人聊天与手机app 的im通讯 ,手机app可以为玩具点播歌曲,玩具与玩具之间的通讯。

    • 智能部分使用了什么算法:
      两种回答:

      • 使用百度ai中的语音合成和语音识别,点播功能是使用Gensim库进行训练的,聊天做游戏是用的图灵机器人+百度语音合成
      • 使用百度ai中的语音合成和语音识别 NLP自然语言处理 点播功能基于百度NLP,聊天做游戏是用的图灵机器人+百度语音合成
    • 语音IM通讯是怎么实现的:
      通过http传输音频文件,将音频文件保存在服务器中,并将聊天信息存储在服务器中,再通过Websocket进行实时通讯,收到消息之后第一时间去服务器中查询聊天信息

    • 手机app是怎么做的(使用什么方式)?
      使用MUI 前端布局,使用HTML5PLUS 完成系统硬件驱动调用 (摄像头,麦克风等) 。

    • 谈谈你对人工智能的理解(说出人工智能技术的关键字至少5个):
      语音类 : 语音识别 语音合成
      图像类 : 图像识别 文字识别 人脸识别 视频审核
      语言类 : 自然语言处理 机器翻译 词法分析 依存句法分析 文本纠错 对话情绪识别 词向量表示 短文本相似度
      词义相似度 情感倾向分析

    • mongodb相关:

      1.修改器: $push $set $pull $inc $pop
      2.说说你对 $ 的理解 : $ 我的理解就是代指符号,代指所查询到的数据或索引位置
      3.Mongodb中的数据类型 : ObjectID String Boolean Integer Double Arrays Object(Dict) Null Timestamp Date
      4.mongodb的比较符 : $lt $gt $lte $gte  ":"
      
      
    • 公司组织架构:
      1.综合人力财务行政:1个小姐姐
      2.营销部:**
      3.产品部:** + UI小姐姐
      4.软件部:** + 前端小姐姐 + 你
      5.硬件部:**

    • 项目不做底层,只使用三方的原因:
      制作底层大量占用人力,公司资金不足以支撑底层研发,将大量成本投入到硬件研发中。

    • 百度AI是网络请求,那如果出现延迟,怎么处理:
      百度响应默认超时2秒,返回给用户语音识别失败

    • 关于用户体验问题:
      非极端情况下,用户会在3秒内得到响应的结果

版权声明:本文为whj233原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/whj233/articles/11629018.html