Django项目

Django

在这里插入图片描述

Django

Django2.2.12

  1. 创建项目:django-admin startproject <projectname>
  2. 创建应用:django-admin startapp <appname>
    python manage.py startapp <appname>
  3. app注册:在INSTALLED_APPS里添加
  4. templates路径注册:settings.py中,在TEMPLATES中的DIRS添加路径os.path.join(BASE_DIR,'templates')
  5. static路径注册:settings.py中,STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'), ]
  6. views.py:视图函数,接受浏览器请求,给用户响应
  7. 配置urls.py:path函数
  8. 前端渲染和后端渲染
    • 前端渲染:在浏览器中完成渲染操作,前端通过Ajax请求获得后端提供的数据,通过JavaScript代码用数据渲染页面
    • 后端渲染:在服务器端用Python程序完成, 把前端提供的静态页改造成模板页,把动态内容换成占位符,通过Python程序把动态内容填入模板页
  9. 连接数据库:
    DATABASES = {
        'default' : {
            'ENGINE' : 'django.db.backends.mysql',
            'USER' : '',
            'NAME' : '',
            'HOST' : '',
            'PORT' : 3306,
            'PASSWORD' : '',
            'CHARSET' : 'utf8',
            'TIME-ZONE' : 'Asia/Shanghai',
        }
    }
    

创建Django超级用户

  1. 创建超级用户:python manage.py createsuperuser
  2. 在admin.py中注册数据库
    • class SubjectAdmin(admin.ModleAdmin):
      <详细内容>
    • admin.site.register(Subject,SubjectAdmin)

模型

模型创建表(正向工程)

  1. 生成迁移文件: python manage.py makemigrations
  2. 生成表:python manage.py migrate
  3. 在pycharm进入交互式环境中操作表:python manage.py shell

表创建模型(逆向工程)

  1. python manage.py inpectdb > <指定文件>:将数据库中的表,生成模型

元属性

1.abstract = True:抽象类不能创建对象,专门用于继承
2. verbose_name:一个更可读的名字
3. verbose_name_plural:一个更可读的名字的复数形式
4. db_table:表的名字

base64编码

  1. 前端页面中:
    • 编码:btoa('')
    • 解码:atob('')
  2. 在后端中:
    • 编码:base64.encode(b'')
    • 解码:base64.decode()

Django自带的用户管理界面

  1. 注册:
    • 创建超级用户:python manage.py createsuperuser
    • 注册模型(admin.py):
      • 设置需要的样式:class SubjectAdmin(admin.ModelAdmin):
      • 添加SubjectAdmin:admin.site.register(Subject,SubjectAdmin)

数据库查询

  1. Django自带的查询功能遇到关联查询时较为繁琐所以在查询两个有外键关联的表时,可以设置:
    • 多对一或一对一关联时可以使用select_related方法解决"1+N查询问题"
    • 多对多关联可以使用prefetch_related方法解决"1+N查询问题"
    • 可以使用QuerySet对象的order_by方法对查询结果按照哪个字段进行排序
  2. filter多条件查询:
    • subject = Subject.objects.filter(条件).filter(条件)..
    • subject = Subject.objects.filter(Q(条件) | (条件))..

中间件(拦截过滤器)日志记录

  1. 作用:
    • 拦截异常
    • Django中间件与之前学过的装饰器在写法和用途上都非常接近,
      通过Django项目配置文件的MIDDLEWARE可以配置使用中间件
  2. 使用:
    • 中间件
    from django.shortcuts import render
    
    # 通过Python标准库logging模块的getLogger获取日志记录器
        logger = logging.getLogger('django.request')
    
    
    def exception_handler_middleware(view_func):
    
        def wrapper(request, *args, **kwargs):
            # 拦截用户请求做出相应的处理
            resp = view_func(request, *args, **kwargs)
            # 拦截服务器给用户的响应做出相应的处理
            # 检测响应状态码是不是5xx ---> 服务器程序出问题
            # 2xx ---> 请求成功
            # 3xx ---> 重定向(给浏览器发送一个新的URL,让浏览器重新请求新的URL)
            # 4xx ---> 请求有问题
            #   ~ 404 ---> Not Found
            #   ~ 401 ---> Unauthorized
            #   ~ 403 ---> Forbidden
            #   ~ 405 ---> 请求方法不支持
            #   ~ 400 ---> 请求数据格式不对
            # 5xx ---> 服务器程序有问题
            if str(resp.status_code).startswith('5'):
                # 生成一条日志记录这个错误以便通过追踪日志定位错误解决问题
                # 写日志的时候需要根据日志的级别调用不同的方法
                # debug --- 调试信息
                # info --- 普通(正常)信息
                # warning --- 警告信息
                # error --- 错误信息
                # critical --- 致命错误信息
                logger.error(f'{request.method} {request.path} ---> {resp.status_code}')
                # 渲染专门定制的优雅的错误页给用户
                return render(request, 'error.html')
            return resp
    
    return wrapper
    
    • 在setting.py中注册中间件
    MIDDLEWARE = [    
    'search.middlewares.exception_handler_middleware',
    ]
    
    • 配置日志(官网复制())
    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        # 日志格式化器
        'formatters': {
            'verbose': {
                'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
                'style': '{',
            },
            'simple': {
                'format': '{levelname} {message}',
                'style': '{',
            },
        },
        # 配置日志处理器
        'handlers': {
            'file': {
                'level': 'WARNING',
                'class': 'logging.FileHandler',
                'filename': os.path.join(BASE_DIR, 'error.log'),
                'formatter': 'verbose',
            },
            'console': {
                'class': 'logging.StreamHandler',
                'formatter': 'simple',
            },
        },
        # 配置日志记录器
        'loggers': {
            'django.db': {
                'handlers': ['file', 'console'],
                'level': 'DEBUG',
                'propagate': True,
            },
        },
    }
    

读写EXcel

    • Office 2010 —> Excel 2010 —> openpyxl
    • Office 2003 —> Excel 2003 —> xlwt / xlrd
  1. wb = Workbook()
    sheet = wb.active
    col_names = ('H1', 'H2', 'H3', 'H4', 'H5', 'H6')
    for index, col in enumerate('ABCDEF'):
        sheet[f'{col}1'] = col_names[index]
    row = 2
    for record in queryset:
        sheet[f'A{row}'] = record.h1
        sheet[f'B{row}'] = record.h2
        sheet[f'C{row}'] = record.h3
        sheet[f'D{row}'] = record.h4
        sheet[f'E{row}'] = record.h5
        sheet[f'F{row}'] = record.h6
        row += 1
    buffer = BytesIO()
    wb.save(buffer)
    resp = HttpResponse(buffer.getvalue())
    # 设置响应头指定MIME类型(告诉浏览器服务器返回的内容类型)
    resp['content-type'] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    filename = quote('<NAME>.xlsx')
    # 设置响应头指定内容处置方式(inline-内联打开;attachment-下载)
    # 如果要设置中文文件名,需要将中文处理成百分号编码,否则不能写到响应头
    resp['content-disposition'] = f'attachment; filename*=utf-8\'\'{filename}'
    return resp
    

制作统计图表

  1. 在官网(https://echarts.apache.org/zh/index.html)调用echarts
    前端接入通过JavaScript实现图表效果渲染
  2. 后端提供JSON数据 —> JsonResponse

使用原SQL语句查询

  1. 得到数据库连接:conn = get_connection()
  2. 获取游标:cursor = conn.cursor()
  3. 输入SQL语句:cursor.execute('')
  4. 得到查询结果: cursor.fetchone() / fetchmany() / fetchall()

redis储存数据

  1. 安装Django-redis:
    pip install djang-redis

  2. 配置redis:

    # 配置缓存服务器
    CACHES = {
        "default" : {
            "BACKEND" : "django_redis.cache.RedisCache",
            "LOCATION" : "redis://ip地址/数据库",
            "OPTIONS" : {
                "CLIENT_CLASS" : "django_redis.client.DefaultClient",
                'PASSWORD' : '密码'
            }
        }
    }
    # 配置将session放到缓存中
    SESSION_ENGINE = "django.contrib.sessions.backends.cache"
    SESSION_CACHE_ALIAS = "default"
    
    # 关闭浏览器清除缓存
    SESSION_EXPIPRE_ATBROWSER_CLOSE = True
    
    # 保存时间
    SESSION_COOKIE_AGE = 86400
    
  3. 什么时候使用redis储存数据

    • 数据:体量不大,访问频率极高,不怎么变化 —> 热数据
    • 如果关系型数据某张表更新特别频繁,那么可以把表直接放到Redis
  4. 使用

    • 缓存页面,加装饰器(只能用于函数):@cache_page(timeout='<保存时间>',cache='<缓存位置>')
    • 缓存类:```@method_decorator(decorator=cache_page(timeout=’<保存时间>’,cache=’<缓存位置>’),name=’<装饰的名字>’)

django-rest-framework

辅助写出rest风格的数据接口

模型:

class Subject(models.Model):
    """学科"""
    no = models.AutoField(primary_key=True, verbose_name='编号')
    name = models.CharField(max_length=50, verbose_name='名称')
    intro = models.CharField(max_length=2000, verbose_name='介绍')
    is_hot = models.BooleanField(default=False, verbose_name='是否热门')
    create_date = models.DateField(null=True, verbose_name='成立日期')

    def __str__(self):
        return f'{self.no}: {self.name}'

    class Meta:
        db_table = 'tb_subject'
        verbose_name = '学科'
        verbose_name_plural = '学科'


class Teacher(models.Model):
    """老师"""
    no = models.AutoField(primary_key=True, verbose_name='编号')
    name = models.CharField(max_length=20, verbose_name='姓名')
    sex = models.BooleanField(default=True, choices=((True, '男'), (False, '女')), verbose_name='性别')
    birth = models.DateField(verbose_name='出生日期', help_text='出生日期的格式:yyyy/MM/dd')
    intro = models.CharField(max_length=2000, verbose_name='介绍')
    photo = models.CharField(max_length=512, verbose_name='照片')
    good_count = models.IntegerField(default=0, db_column='gcount', verbose_name='好评数')
    bad_count = models.IntegerField(default=0, db_column='bcount', verbose_name='差评数')
    subject = models.ForeignKey(to=Subject, on_delete=models.PROTECT, db_column='sno', verbose_name='所属学科')

    class Meta:
        db_table = 'tb_teacher'
        verbose_name = '老师'
        verbose_name_plural = '老师'

方法一:FBV

  1. 创建一个serializers.py文件
  2. 在serializers.py中设置相关类
    class SubjectSimpleSerializer(serializers.ModelSerializer) :
        class Meta :
            model = Subject
            fields = ('no', 'name')
    
  3. 在views.py中
        def subject(request):
            queryset = subject.objects.all()
            serialize = SubjectSimpleSerializer(queryset,many=True)
            return Response(serializer.data)
    

方法二:CBV

  1. 创建一个serializers.py文件
  2. 在serializers.py中设置相关类
        class SubjectSimpleSerializer(serializers.ModelSerializer) :
            class Meta :
                model = Subject
                fields = ('no', 'name')
    
  3. 在view.py中
        class SubjectViewSet(ModelViewSet):
            queryset = subject.objects.all()
            serializer_class = SubjectSimplerializer
    
  4. 在setting注册
        INSTALLED_APPS=[
                        'rest_framework',
                        ]
    
  5. 在urls中设置路径
        router = DefaultRouter()
        router.register('subject', SubjectViewSet)
        urlpatterns += router.urls
    

获取外键的值

  • 如Teacher要获得关联外键的subject的属性
    重复上面方法一或方法二的操作
    在serializers.py中设置:
class SubjectSimpleSerializer(serializers.ModelSerializer) :
        subject_id=serializers.CharField(source='subject.mane')


        class Meta :
			model = Subject
            fields = ('no', 'name','subject_id')

source=’<外联表名>.<相关属性>’

(后面补充)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值