python -m pip install \
Django==2.0 \
django-cors-headers==2.4.0 \
django-recaptcha==1.5.0 \ \
django-admin-view-permission==1.9 \
django-crontab==0.7.1 \
django-redis==4.11.0 \
-i https://pypi.douban.com/simple
django-admin startproject pro1
mkdir pro1/apps
cd pro1/apps
python ../manage.py startapp user
在pro1/settings.py中,将对应的app模块添加进去
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'apps.users', #用户模块
]
使用命名空间定义路由
from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include
urlpatterns = [
path('admin/', admin.site.urls),
#使用users命名空间定义users路由
url(r'^api/v1/users/',include(('apps.users.urls','users'),namespace='users')),
]
命名空间表示,凡是users.urls中定义的路由,均属于namespace指明的users名下。
命名空间的作用:避免不同应用中的路由使用相同的名称发生冲突,使用命名空间区分开
cat >> apps/users/urls.py << EOF
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django.conf.urls import url
from apps.users import views
urlpatterns = [
url(r'^hello/$',views.hello,name='hello'),
]
EOF
在apps/users/views.py中添加下面内容
from django import http
# Create your views here.
def hello(request):
# 返回相应
return http.JsonResponse({'name':'hello'})
python manage.py runserver 0.0.0.0:8080
0.0.0.0:设置外部可以访问
# Redis缓存库配置
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/0",
"OPTIONS": {
"PASSWORD": "123456",#redis密码
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"COMPRESSOR": "django_redis.compressors.zlib.ZlibCompressor",
"CONNECTION_POOL_KWARGS": {"max_connections": 512},
"IGNORE_EXCEPTIONS": True,
"SOCKET_CONNECT_TIMEOUT": 5, # in seconds
"SOCKET_TIMEOUT": 5, # in seconds
}
},
"authority": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"PASSWORD": "123456",#redis密码
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"COMPRESSOR": "django_redis.compressors.zlib.ZlibCompressor",
"CONNECTION_POOL_KWARGS": {"max_connections": 512},
"IGNORE_EXCEPTIONS": True,
"SOCKET_CONNECT_TIMEOUT": 5, # in seconds
"SOCKET_TIMEOUT": 5, # in seconds
}
},
"feedflow": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/2",
"OPTIONS": {
"PASSWORD": "123456",#redis密码
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"COMPRESSOR": "django_redis.compressors.zlib.ZlibCompressor",
"CONNECTION_POOL_KWARGS": {"max_connections": 512},
"IGNORE_EXCEPTIONS": True,
"SOCKET_CONNECT_TIMEOUT": 5, # in seconds
"SOCKET_TIMEOUT": 5, # in seconds
}
},
}
"""
全局管理缓存的调用,封装django自带的cache
主要用于小数据量的调用
"""
import json
import re
import redis
from contextlib import contextmanager
from functools import reduce
from django.core import signals
from django.core.cache import _create_cache
from django_redis import get_redis_connection
def query_cache(dbname):
"""
redis 扩展redis 原生 功能用此连接方式
"""
conn_redis = get_redis_connection(dbname)
return conn_redis
def get_cache(backend, **kwargs):
"""django-redis 自带方法请用这个"""
cache = _create_cache(backend, **kwargs)
signals.request_finished.connect(cache.close)
return cache
class CacheAdpter():
@classmethod
def hset(cls, cache_name, mainkey, subkey, values, second=None):
"""
单个添加 redis hash 值
:param cache_name: db
:param mainkey: 主key
:param subkey: 子key
:param second: 不建议设置过期时间,此过期时间针对mainkey设置,对subkey无效
:return
CacheAdpter.hmset('authority', CacheKey.AUTHY_CUSTOMER_ROLE, 20, key_1='values_11', key_2='values_662')
"""
use_cache = query_cache(cache_name)
use_cache.hset(mainkey, subkey, values)
if second:
use_cache.expire(mainkey, second)
@classmethod
def hmset(cls, cache_name, mainkey, second=None, **kwargs):
"""
批量添加 redis hash 值
:param cache_name: db
:param mainkey: 主key
:param **kwargs: 批量subkey
:param second: 不建议设置过期时间,此过期时间针对mainkey设置,对subkey无效
:return
CacheAdpter.hmset('authority', CacheKey.AUTHY_CUSTOMER_ROLE, 20, key_1='values_11', key_2='values_662')
"""
use_cache = query_cache(cache_name)
use_cache.hmset(mainkey, kwargs)
if second:
use_cache.expire(mainkey, second)
@classmethod
def hdel(cls, cache_name, mainkey, key):
"""
删除 redis hash 数据
:param cache_name: db
:param mainkey: 主key
:param subkey: 子key
:return:
"""
use_cache = query_cache(cache_name)
use_cache.hdel(mainkey, key)
@classmethod
def hget(cls, cache_name, mainkey, subkey, type=False):
"""
获取 redis hash 数据 扩展redis hash hget 调用
:param cache_name: db
:param mainkey: 主key
:param subkey: 子key
:return:
"""
use_cache = query_cache(cache_name)
result = use_cache.hget(mainkey, subkey)
# bytes 转 str
if type:
return None if result is None else str(result, encoding='utf-8')
else:
result = json.loads(result) if result else None
return result
@classmethod
def hkeys(cls, cache_name, mainkey, default=None):
"""
获取主key中所有子key的列表
:param cache_name: 缓存库
:param mainkey: 主key
:return: 返回列表
"""
default = default if default else []
use_cache = query_cache(cache_name)
keys_list = use_cache.hkeys(mainkey)
if not keys_list:
return default
return keys_list
@classmethod
def get_time_out(cls, cache, timeout):
"""
设置db 过期时间
:param cache: db
:param timeout: 过期时间
:return:
"""
if not timeout:
timeout = cache.default_timeout
return timeout
@classmethod
def get(cls, cache_name, key, default=None):
"""
获取 redis 数据
:param cache_name: db
:param key: 主key
:return:
"""
use_cache = get_cache(cache_name)
value = use_cache.get(key)
if value is None:
return default
return value
@classmethod
def set(cls, cache_name, key, value, timeout=0):
"""
存储 redis 数据
:param cache_name :db
:param key: key
:param value: values
:param timeout:设置过期时间 单位秒
:return:
"""
use_cache = get_cache(cache_name)
use_cache.set(key, value, cls.get_time_out(use_cache, timeout))
@classmethod
def get_many(cls, cache_name, keys, default=None):
"""
批量获取 redis 数据
:param cache_name :db
:param keys: key list []
:return:
"""
default = default if default else {}
use_cache = get_cache(cache_name)
value_dict = use_cache.get_many(keys)
if value_dict is None:
return default
return value_dict
@classmethod
def set_many(cls, cache_name, keys, timeout=0):
"""
批量设置 redis 过期数据
:param cache_name :db
:param keys: key list []
:param timeout 60*24
:return:
"""
use_cache = get_cache(cache_name)
use_cache.set_many(keys, cls.get_time_out(use_cache, timeout))
@classmethod
def delete(cls, cache_name, key):
"""
删除 redis set 数据
:param cache_name :db
:param key: key
:return:
"""
use_cache = get_cache(cache_name)
use_cache.delete(key)
@classmethod
def delete_many(cls, cache_name, keys):
use_cache = get_cache(cache_name)
for key in keys:
use_cache.delete(key)
@classmethod
def get_large_list(cls, cache_name, key):
use_cache = get_cache(cache_name)
value_list = []
grp_num = use_cache.get(key)
if grp_num is None:
return value_list
keys = [key + '_' + str(i) for i in range(grp_num)]
value_dict = use_cache.get_many(keys)
if not value_dict:
return value_list
else:
return reduce(list.__add__, value_dict.values())
@classmethod
def sadd(cls, cache_name, key, values):
"""
添加元素到redis集合中,添加多个元素需要封装为可迭代类型
:param key: 键
:param values: 值
:param cache_name: 缓存库
:return:
"""
use_cache = query_cache(cache_name)
if isinstance(values, str or int):
return use_cache.sadd(key, values)
return use_cache.sadd(key, *values)
@classmethod
def smembers(cls, cache_name, key):
"""
获取缓存中集合的所有元素
:param key: 键
:param cache_name: 缓存库
:return: 以列表返回所有结果
"""
use_cache = query_cache(cache_name)
value = use_cache.smembers(key)
if value:
return sorted([i.decode() for i in value])
return None
@classmethod
def delete_set_key(cls, cache_name, key):
"""
由于django自带的redis无法删除set(集合)中的键,所以调用此方法
:param key: 键
:param cache_name: 缓存库
:return:
"""
use_cache = query_cache(cache_name)
return use_cache.delete(key)
@classmethod
def incr(cls, cache_name, key, count, timeout=0):
use_cache = query_cache(cache_name)
use_cache.incr(key, count)
if timeout:
use_cache.expire(key, timeout)
@classmethod
def get_8origin(cls, cache_name, key, default=None):
"""
获取 redis 数据, 通过get_redis_connection原生连接获取数据
:param cache_name: db
:param key: 主key
:return:
"""
use_cache = query_cache(cache_name)
value = use_cache.get(key)
result = json.loads(value) if value else default
return result
@classmethod
def add(cls, cache_name, key, value, timeout=None):
"""
当缓存中键不存在时向缓存中写入键值,可以设置有效期
:param key: 键
:param value: 值
:param cache_name: 缓存库
:param timeout: 有效期时间
:return:
"""
use_cache = get_cache(cache_name)
if isinstance(timeout, int):
return use_cache.add(key, value, timeout)
else:
return use_cache.add(key, value, timeout=cls.get_time_out(use_cache, None))
python manage.py shell
开启shell模式,接下来就可以直接对表模型直接进行操作
执行代码
from django_redis import get_redis_connection
conn_redis = get_redis_connection("default")
conn_redis.set("test","test")
显示结果
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 数据库引擎
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306, # 数据库端口
'USER': 'root', # 数据库用户名
'PASSWORD': '123456', # 数据库用户密码
'NAME': 'test' # 数据库名字
},
'slave': {
'ENGINE': 'django.db.backends.mysql', # 数据库引擎
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306, # 数据库端口
'USER': 'root', # 数据库用户名
'PASSWORD': '123456', # 数据库用户密码
'NAME': 'test' # 数据库名字
}
}
在utils中创建db_router.py
class MasterSlaveDBRouter(object):
"""数据库主从读写分离路由"""
def db_for_read(self, model, **hints):
"""读数据库"""
return "slave"
def db_for_write(self, model, **hints):
"""写数据库"""
return "default"
def allow_relation(self, obj1, obj2, **hints):
"""是否运行关联操作"""
return True
在settings.py文件中增加
# 配置读写分离
DATABASE_ROUTERS = ['utils.db_router.MasterSlaveDBRouter']
在pro1/init.py文件中增加
import pymysql
pymysql.install_as_MySQLdb() #使用pymysql代替mysqldb连接数据库
python manage.py shell
开启shell模式,接下来就可以直接对表模型直接进行操作
执行代码
from django.db import connection, transaction
cursor = connection.cursor()
cursor.execute("show tables")
print(cursor.fetchone())
import pymysql
conn = pymysql.connect(
host='127.0.0.1', # ip
port=3306, # 端口
user='root', # mysql客户端登陆用户名
passwd='123456', # mysql客户端登陆用密码
charset='utf8', # 千万不要加-
# 指定要操作哪个库
database='meiduo_mall_42'
) # 链接数据库
# 产生一个游标对象(类似在cmd中登陆mysql客户端后的哪个等待你输命令的闪烁的短下划线)
"""
将查询的结果以字典的形式返回
"""
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("show tables")
print(cursor.fetchone())
具体的错误提示为:
File "" , line 1030, in _gcd_import
File "" , line 1007, in _find_and_load
File "" , line 986, in _find_and_load_unlocked
File "" , line 680, in _load_unlocked
File "" , line 850, in exec_module
File "" , line 228, in _call_with_frames_removed
File "/home/test/Desktop/works/demos/django-pro/pro1/pro1/urls.py", line 25, in <module>
url(r'^',include('apps.users.urls',namespace='users')),
File "/home/test/anaconda3/lib/python3.9/site-packages/django/urls/conf.py", line 38, in include
raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: Specifying a namespace in include() without providing an app_name is not supported. Set the app_name attribute in the included module, or pass a 2-tuple containing the list of patterns and app_name instead.
错误示例:
url(r'^',include('apps.users.urls',namespace='users')),
修改为:
url(r'^',include(('apps.users.urls','users'),namespace='users')),
具体的错误提示为:
Exception Value:
Invalid HTTP_HOST header: '192.168.3.171:8080'. You may need to add '192.168.3.171' to ALLOWED_HOSTS.
settings.py中的
ALLOWED_HOSTS = []
改为
ALLOWED_HOSTS = ['192.168.3.171']
ALLOWED_HOSTS的作用 ALLOWED_HOSTS是用来设置允许哪些主机访问我们的django后台站点
self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
File "/home/test/anaconda3/lib/python3.9/site-packages/django/db/__init__.py", line 33, in __getattr__
return getattr(connections[DEFAULT_DB_ALIAS], item)
File "/home/test/anaconda3/lib/python3.9/site-packages/django/db/utils.py", line 202, in __getitem__
backend = load_backend(db['ENGINE'])
File "/home/test/anaconda3/lib/python3.9/site-packages/django/db/utils.py", line 110, in load_backend
return import_module('%s.base' % backend_name)
File "/home/test/anaconda3/lib/python3.9/importlib/__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "/home/test/anaconda3/lib/python3.9/site-packages/django/db/backends/mysql/base.py", line 17, in <module>
raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.
Did you install mysqlclient?
解决方案,使用pymysql代替mysqldb连接数据库
在pro1/init.py文件中增加
import pymysql
pymysql.install_as_MySQLdb() #使用pymysql代替mysqldb连接数据库