跳转至

2-Django使用示例

官方文档

websocket支持

过程笔记

1
2
3
4
5
6
7
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns = [
    path('admin/', admin.site.urls),
    re_path('', include('usermodectl.urls'))
]

urlpatterns += staticfiles_urlpatterns()
或者
from django.conf import settings
from django.contrib import admin

from django.urls import path, re_path, include
from django.views.static import serve

from usermodectl.views import *

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r"^static/(?P<path>.*)$", serve, {"document_root": settings.STATIC_ROOT}, name='static'),
    re_path('', include('usermodectl.urls'))
]

STATIC_ROOT = os.path.join(BASE_DIR, "static")

用Uvicorn来启动ASGI组件
pip install uvicorn
启动:
uvicorn djangoProject.asgi:application
协程

1
2
3
4
5
6
7
8
# 异步视图
async def index(request):
    return HttpResponse("Hello, Django!")

async def async_view(request):
    loop = asyncio.get_event_loop()
    loop.create_task(async_task())
    return HttpResponse("Hello, async Django!")

bug_sum.objects.values_list(“teamname”,flat=True).distinct() # : bug_sum.objects.values_list(“teamname”).distinct() # :

定义在了命名空间字典 namespace 中。然后,使用 exec() 执行代码,并通过命名空间字典获取执行后的结果。

1
2
3
4
namespace = {}
exec(svnaddr, namespace)
logging.error(namespace.get("components_list_rootfs"))
logging.error(namespace.get("components_list"))

这里有一个坑,如果要


则必须要保证指定了 app_name app_name = ‘fun’ urlpatterns = [ re_path(‘login_mysite’, login_mysite, name=’login_mysite’), re_path(‘’, index), ]

1
2
3
4
5
由于x-frame-options设置了deny属性,导致了iframe失效,x-frame-options响应头是用来给浏览器设置允许一个页面可否在<frame>、<iframe>中展现的标记,有三个属性

deny:页面不允许在iframe中展现,相同域名嵌套也不允许
sameorigin:允许在相同域名嵌套展示
allow-from uri:允许指定源的iframe展示,即白名单

一下是 setting.py 中需要添加的配置

1
2
3
4
5
6
AUTHENTICATION_BACKENDS = [
    # 'django_auth_ldap.backend.LDAPBackend',
    'hoaofun.backend.SettingsBackend',
    'django.contrib.auth.backends.ModelBackend'
]
LDAP_CONFIG = {"HOST": "ldap://192.168.1.1:389"}

依赖 pip install python-ldap

参考资料 ldap.py
https://www.python-ldap.org/en/latest/installing.html
https://www.lfd.uci.edu/~gohlke/pythonlibs/#ecos

特殊操作

通过字典更新

from myapp.models import MyModel

# 假设您有要更新的模型实例的ID和要更新的数据字典
instance_id = 1
data = {
    'field1': 'New Value 1',
    'field2': 'New Value 2',
}

# 使用update()方法更新模型实例
MyModel.objects.filter(id=instance_id).update(**data)

创建模型,注册管理

1
2
3
4
5
6
7
8
9
models.py 
from django.contrib.auth.models import AbstractUser
class CACA(AbstractUser):
    phone = models.IntegerField("手机号",null=True,blank=True)
    def __str__(self):
        return self.username

admin.py 
admin.site.register(CACA,myusers)
在setting.py 中添加
AUTH_USER_MODEL = "syslog.CACA" 注意:
1、尽可能在开始创建
2、项目开发中途操作可能出现错误
3、出错可以尝试删除auth 和 django 开头的表;并删除app下的全部 migrations

Django直接执行django的程序,Debug

1
2
3
4
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tech.settings')
django.setup()

特性配置

静态配置目录

1
2
3
4
5
6
settings.py 文件中添加
STATIC_ROOT = os.path.join(BASE_DIR,"static")


urls.py 文件中添加
re_path(r"^static/(?P<path>.*)$", serve, {"document_root": settings.STATIC_ROOT}, name='static'),
模板配置
settings.py 文件 变量 TEMPLATES 修改dirs

'DIRS': [BASE_DIR / 'templates', ],# 即模板文件存放在 BASE_DIR/templates
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}
LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

USE_TZ = False

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    BASE_DIR / 'static',
]

1
2
3
4
5
6
7
8
from django.urls import re_path

from aboutpbc.views import *
app_name = 'aboutpbc'

urlpatterns = [
    re_path("",index,name="index")
]
urlpatterns = [
    re_path('^$', index_page),# 一般首页的写法
    re_path('model_info', model_info),

    # 正则匹配 其中 name可以在模板网页中使用 <a href="{% url "queryproduct" per_model.1 %}"
    re_path("query/(?P<product_name>.*)", product_list,name="queryproduct"),

    path('contol/', admin.site.urls),# 修改默认的管理地址
    re_path("",include("cneos.urls")),# 走到某个app
]

1
2
3
4
5
6
7
{% for key,value in dicts.items %}  
  <tr class="{% cycle 'altrow' '' %}">              
    <td>{{ forloop.counter }}</td>            
    <td>{{ key }}</td>            
    <td>{{ value }}</td>            
  </tr>           
{% endfor %}
下面两种也是,循环k - v
{% for row in user_dict.keys %}
{% for row in user_dict.values %}

要修改 Django 后台管理左上角的 “Django 管理” 为 “公共服务”,你需要覆盖 Django 的默认 admin 模板。下面是具体步骤:

  1. 在你的 Django 项目的主目录下(与 manage.py 文件在同一级别),创建一个名为 templates 的文件夹。

  2. templates 文件夹下,创建一个名为 admin 的文件夹。这是为了覆盖 Django admin 的默认模板。

  3. admin 文件夹下,创建一个名为 base_site.html 的文件。Django admin 会首先搜索这个文件,如果找到,就会使用它替代默认的模板。

  4. base_site.html 文件中,你需要继承 admin/base.html,并覆盖 branding 块,如下所示:

{% extends "admin/base.html" %}
{% load i18n %}

{% block title %}{{ title }} | {% trans "公共服务" %}{% endblock %}

{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">{% trans "公共服务" %}</a></h1>
{% endblock %}

{% block nav-global %}{% endblock %}
  1. 确保你的 Django 项目知道这个新的 templates 文件夹的位置。在你的 settings.py 文件中,你应该有一个名为 TEMPLATES 的设置。在这个设置中,你需要添加你刚刚创建的 templates 文件夹的路径,如下所示:
1
2
3
4
5
6
7
TEMPLATES = [
    {
        ...
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        ...
    },
]

这样,当你再次打开 Django admin 页面时,你应该会看到左上角的 “Django 管理” 已经被改为 “公共服务”。

1、具体的app里面 新建middle 文件夹
2、创建中间件代码,具体参考下方代码
3、在setting的MIDDLERWARE 中注册中间件

from django.utils.deprecation import MiddlewareMixin


class letdo(MiddlewareMixin):
    # 它应该返回 None 或 HttpResponse 对象。如果它返回 None ,Django 将继续处理这个请求
    ''' 顺序
    调用 self.process_request(request) (如果被定义过)。
    调用 self.get_response(request) 来从后续的中间件和视图得到响应。
    调用 self.process_response(request, response) (如果被定义过)。
    返回响应。
    '''
    def __call__(self, request):
        '''

        :param request:是中间件的主要入口点。当请求到达时,Django将调用中间件的__call__方法,传递request对象作为参数。
        中间件可以在这个方法中执行任何预处理或处理请求的操作,例如记录请求信息、检查用户身份、设置一些请求标志等。
        :return:
        '''
        ...
    def process_view(self, request, view_func, view_args, view_kwargs):

        '''  只在 Django 调用视图前被调用;这个方法在请求被路由到视图函数之前被调用
        request 是一个 HttpRequest 对象。
        view_func 是一个 Django 将要使用的 Python 函数。(这是一个真实的函数对象,不是函数的名称);
        view_args 是一个用来传递给视图的位置参数列表,;
        view_kwargs 是一个用来传递给视图的关键字参数字典。
        view_args 和 view_kwargs 都不包含第一个视图参数 ( request )。
        '''
        ...
    def process_exception(self,request, exception):
        '''
        当视图引发异常时,Django 会调用
        :param request:
        :param exception:
        :return:
        '''
        ...
    def process_template_response(self,request, response):
        '''
        在视图被完全执行后调用;它必须返回一个实现了 render 方法的响应对象
        当视图函数返回一个模板响应时,这个方法会被调用。中间件可以在这里对模板响应进行处理,例如添加额外的上下文变量或修改响应内容。
        :param request:
        :param response:
        :return:
        '''
        ...
    def process_request(self,request):
        '''
        这个方法在__call__方法之前调用。它允许中间件在请求处理之前进行一些操作
        '''

        ...
    def process_response(self,request,response):
        # 这个方法在视图函数处理请求并生成响应后调用
        ...

数据相关

语法 效果
~Q(jira_key__istartswith=”ARC”) 不以ARC开头的任务
__exact 精确等于 like ‘111’
__iexact 精确等于 忽略大小写 ilike ‘111’
__contains 包含 like ‘%111%’
__icontains 包含 忽略大小写 ilike ‘%111%’,
__gt 大于
__gte 大于等于
__lt 小于
__lte 小于等于
__in 存在于一个list范围内
__startswith 以…开头
__istartswith 以…开头 忽略大小写
__endswith 以…结尾
__iendswith 以…结尾,忽略大小写
__range 在…范围内
__year 日期字段的年份
__month 日期字段的月份
__day 日期字段的日
__isnull=True/False

Django自定义过滤器

第一步: 在app目录下创建包 templatetags

在templatetags下创建py文件,文件名随意

自定义过滤器函数filter

from django.template import Library
import datetime


register = Library()

def show_time(v):
    # 首页返回底部时间的过滤器
    return datetime.datetime.now().date()


register.filter('show_time',show_time)

第二步,html引用

在文件开头导入

{% load my_page %}

使用

重启服务器!!!!!!

Django过滤器 过滤器 描述
upper 以大写方式输出 {{ user.name | upper }}
add 给value加上一个数值 {{ user.age | add:”5” }}
addslashes 单引号加上转义号
capfirst 第一个字母大写 {{ ‘good’| capfirst }} 返回”Good”
center 输出指定长度的字符串,把变量居中 {{ “abcd”| center:”50” }}
cut 删除指定字符串 {{ “You are not a Englishman” | cut:”not” }}
date 格式化日期 {{ 时间|date:”Y-m-d” }}
default 如果值不存在,则使用默认值代替 {{ value | default:”(N/A)” }}
default_if_none 如果值为None, 则使用默认值代替
dictsort 按某字段排序,变量必须是一个dictionary {% for moment in moments | dictsort:”id” %}
dictsortreversed 按某字段倒序排序,变量必须是dictionary
divisibleby 判断是否可以被数字整除 {{ 224 | divisibleby:2 }} 返回 True
escape 按HTML转义,比如将”;”转换为”&lt”
filesizeformat 增加数字的可读性,转换结果为13KB,89MB,3Bytes等 {{ 1024 | filesizeformat }} 返回 1.0KB
first 返回列表的第1个元素,变量必须是一个列表
floatformat 转换为指定精度的小数,默认保留1位小数 {{ 3.1415926 | floatformat:3 }} 返回 3.142 四舍五入
get_digit 从个位数开始截取指定位置的数字 {{ 123456 | get_digit:’1’}}
join 用指定分隔符连接列表 {{ [‘abc’,’45’] | join:’*’ }} 返回 abc*45
length 返回列表中元素的个数或字符串长度
length_is 检查列表,字符串长度是否符合指定的值 {{ ‘hello’| length_is:’3’ }}
linebreaks 用;p;或;br;标签包裹变量 {{ “Hi\n\nDavid”|linebreaks }} 返回;p;Hi;/p;;p;David;/p;
linebreaksbr 用;br/;标签代替换行符
linenumbers 为变量中的每一行加上行号
ljust 输出指定长度的字符串,变量左对齐 {{‘ab’|ljust:5}}返回 ‘ab ’
lower 字符串变小写
make_list 将字符串转换为列表
pluralize 根据数字确定是否输出英文复数符号
random 返回列表的随机一项
removetags 删除字符串中指定的HTML标记 {{value | removetags: “h1 h2”}}
rjust 输出指定长度的字符串,变量右对齐
slice 切片操作, 返回列表 {{[3,9,1] | slice:’:2’}} 返回 [3,9]{{ ‘asdikfjhihgie’ | slice:’:5’ }} 返回 ‘asdik’
slugify 在字符串中留下减号和下划线,其它符号删除,空格用减号替换 {{ ‘5-2=3and5 2=3’ | slugify }} 返回 5-23and5-23
stringformat 字符串格式化,语法同python
time 返回日期的时间部分
timesince 以“到现在为止过了多长时间”显示时间变量 结果可能为 45days, 3 hours
timeuntil 以“从现在开始到时间变量”还有多长时间显示时间变量
title 每个单词首字母大写
truncatewords 将字符串转换为省略表达方式 {{ ‘This is a pen’ | truncatewords:2 }}返回This is …
truncatewords_html 同上,但保留其中的HTML标签 {{ ‘;p;This is a pen;/p;’ | truncatewords:2 }}返回;p;This is …;/p;
urlencode 将字符串中的特殊字符转换为url兼容表达方式 {{ ‘http://www.aaa.com/foo?a=b&b=c’ | urlencode}}
urlize 将变量字符串中的url由纯文本变为链接
wordcount 返回变量字符串中的单词数
yesno 将布尔变量转换为字符串yes, no 或maybe {{ True | yesno }}{{ False | yesno }}{{ None | yesno }} 返回 yesno maybe
1
2
3
4
5
6
7
# 应用导出
python manage.py dumpdata [appname] > appname_data.json
# 应用导出的某一张表
python manage.py dumpdata [appname.table] > appname_data.json

# 导入
python manage.py loaddata blog_dump.json blog_dump2.json blog_dump3.json

django集成redis

环境准备

apt install redis
pip install django-redis

setting 中添加配置

1
2
3
4
5
6
7
8
9
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

django集成 celery flower

celery详细说明

Celery之前的版本需要一个单独的库才能与Django一起使用,但是自3.1之后就不再是这种情况了。 Django现在是开箱使用的,

pip install Celery "celery[redis,auth,msgpack]"

前提条件 已有 redis

setting 中添加配置

1
2
3
4
5
6
7
8
CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/1'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = "Asia/Shanghai"
CELERY_MAX_TASKS_PER_CHILD = 100
CELERY_LOG_FILE = os.path.join(BASE_DIR,'celery.log')
CELERYBEAT_LOG_FILE = os.path.join(BASE_DIR,'celery.log.beta')

在app 下创建 celery.py

import os

from celery import Celery

# Set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Assetinventory.settings') # 注意自己的 setting

app = Celery('tech') # 注意替换app 

# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
#   should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')

# Load task modules from all registered Django apps.
app.autodiscover_tasks() # 自动遍历目录下的tasks.py


@app.task(bind=True, ignore_result=True)
def debug_task(self):
    print(f'Request: {self.request!r}')

新建tasks.py

1
2
3
4
5
6
7
from celery import shared_task
from .about_qiwei import wxsendmsg

@shared_task
def shared_task_demo(username,txt):
    print('shared_task_demo')
    wxsendmsg(username,txt)

在正常代码中的调用方式 delay

shared_task_demo.delay(c.userinfo_obj.username,txt=f"{request.user.first_name}申请使用你在用的设备")

启动:

1
2
3
4
5
celery -A tasks flower --broker=redis://@loaclhost:6379/0

celery --app tasks worker --loglevel=info

DJANGO_SETTING_MODULE=setting.loacl  celery --app tasks worker --loglevel=info

定时任务

>> 方法如下
@shared_task
def check_our_dev():
    check_devalive()


>> setting使用下面的

CELERY_BEAT_SCHEDULE = {
    'run-every-minute': {
        'task': 'tech.tasks.check_our_dev',
        'schedule': 60.0,  # 每分钟执行一次
    },
}

异步任务无法保存数据库

  • 事务 是将一系列数据库操作作为原子操作执行的机制,要么全部成功提交,要么全部回滚。

在Django中,默认情况下,每个同步请求都会自动启动一个数据库事务,并在请求结束时进行提交。

  • 但是,在异步任务中,默认情况下不会自动启动事务,因此需要手动管理事务。
  • django.db.transaction模块提供了在Django中进行数据库事务处理的功能
from django.db import transaction

# 使用上下文管理器
def your_task_function():
    with transaction.atomic():
        # 执行数据库操作
        # 如果发生异常,事务将回滚

# 或者装饰器
@transaction.atomic
def your_task_function():
    # 执行数据库操作
    # 如果发生异常,事务将回滚
  • 使用事务处理后,重启celery服务,即可生效