django-admin startproject empmanager
django-admin startapp candidates
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
python manage.py inspectdb
python manage.py inspectdb>candidates/models.py
from django.db import models
from django.contrib.auth.models import User
class Candidate(models.Model):
userid = models.IntegerField(unique=True, blank=True, null=True)
username = models.CharField(max_length=135)
city = models.CharField(max_length=135)
phone = models.CharField(max_length=135)
email = models.CharField(max_length=135)
apply_position = models.CharField(max_length=135)
born_address = models.CharField(max_length=135)
gender = models.CharField(max_length=135)
candidate_remark = models.CharField(max_length=135)
bachelor_school = models.CharField(max_length=135)
master_school = models.CharField(max_length=135)
doctor_school = models.CharField(max_length=135)
major = models.CharField(max_length=135)
degree = models.CharField(max_length=135)
test_score_of_general_ability = models.DecimalField(max_digits=10, decimal_places=5, blank=True, null=True) # max_digits and decimal_places have been guessed, as this database handles decimal fields as float
paper_score = models.DecimalField(max_digits=10, decimal_places=5, blank=True, null=True) # max_digits and decimal_places have been guessed, as this database handles decimal fields as float
first_score = models.DecimalField(max_digits=10, decimal_places=5, blank=True, null=True) # max_digits and decimal_places have been guessed, as this database handles decimal fields as float
first_learning_ability = models.DecimalField(max_digits=10, decimal_places=5, blank=True, null=True) # max_digits and decimal_places have been guessed, as this database handles decimal fields as float
first_professional_competency = models.DecimalField(max_digits=10, decimal_places=5, blank=True, null=True) # max_digits and decimal_places have been guessed, as this database handles decimal fields as float
first_advantage = models.TextField()
first_disadvantage = models.TextField()
first_result = models.CharField(max_length=256)
first_recommend_position = models.CharField(max_length=256)
first_remark = models.CharField(max_length=135)
second_score = models.DecimalField(max_digits=10, decimal_places=5, blank=True, null=True) # max_digits and decimal_places have been guessed, as this database handles decimal fields as float
second_learning_ability = models.DecimalField(max_digits=10, decimal_places=5, blank=True, null=True) # max_digits and decimal_places have been guessed, as this database handles decimal fields as float
second_professional_competency = models.DecimalField(max_digits=10, decimal_places=5, blank=True, null=True) # max_digits and decimal_places have been guessed, as this database handles decimal fields as float
second_pursue_of_excellence = models.DecimalField(max_digits=10, decimal_places=5, blank=True, null=True) # max_digits and decimal_places have been guessed, as this database handles decimal fields as float
second_communication_ability = models.DecimalField(max_digits=10, decimal_places=5, blank=True, null=True) # max_digits and decimal_places have been guessed, as this database handles decimal fields as float
second_pressure_score = models.DecimalField(max_digits=10, decimal_places=5, blank=True, null=True) # max_digits and decimal_places have been guessed, as this database handles decimal fields as float
second_advantage = models.TextField()
second_disadvantage = models.TextField()
second_result = models.CharField(max_length=256)
second_recommend_position = models.CharField(max_length=256)
second_remark = models.CharField(max_length=135)
hr_score = models.CharField(max_length=10)
hr_responsibility = models.CharField(max_length=10)
hr_communication_ability = models.CharField(max_length=10)
hr_logic_ability = models.CharField(max_length=10)
hr_potential = models.CharField(max_length=10)
hr_stability = models.CharField(max_length=10)
hr_advantage = models.TextField()
hr_disadvantage = models.TextField()
hr_result = models.CharField(max_length=256)
hr_remark = models.CharField(max_length=256)
creator = models.CharField(max_length=256)
created_date = models.DateTimeField()
modified_date = models.DateTimeField(blank=True, null=True)
last_editor = models.CharField(max_length=256)
first_interviewer_user = models.ForeignKey(User, models.DO_NOTHING, related_name='first_interviewer_user',blank=True, null=True)
hr_interviewer_user = models.ForeignKey(User, models.DO_NOTHING, related_name='hr_interviewer_user',blank=True, null=True)
second_interviewer_user = models.ForeignKey(User, models.DO_NOTHING, related_name='second_interviewer_user',blank=True, null=True)
class Meta:
managed = False
db_table = 'candidate'
class JobsJob(models.Model):
job_type = models.SmallIntegerField()
job_name = models.CharField(max_length=250)
job_city = models.SmallIntegerField()
job_responsibility = models.TextField()
job_requirement = models.TextField()
created_date = models.DateTimeField()
modified_date = models.DateTimeField()
creator = models.ForeignKey(User, models.DO_NOTHING, blank=True, null=True)
class Meta:
managed = False
db_table = 'jobs_job'
class JobsResume(models.Model):
username = models.CharField(max_length=135)
city = models.CharField(max_length=135)
phone = models.CharField(max_length=135)
email = models.CharField(max_length=135)
apply_position = models.CharField(max_length=135)
born_address = models.CharField(max_length=135)
gender = models.CharField(max_length=135)
picture = models.CharField(max_length=100)
attachment = models.CharField(max_length=100)
bachelor_school = models.CharField(max_length=135)
master_school = models.CharField(max_length=135)
doctor_school = models.CharField(max_length=135)
major = models.CharField(max_length=135)
degree = models.CharField(max_length=135)
created_date = models.DateTimeField()
modified_date = models.DateTimeField()
candidate_introduction = models.TextField()
work_experience = models.TextField()
project_experience = models.TextField()
applicant = models.ForeignKey(User, models.DO_NOTHING, blank=True, null=True)
class Meta:
managed = False
db_table = 'jobs_resume'
from django.contrib import admin
# Register your models here.
from .models import JobsJob,JobsResume,Candidate
admin.site.register(JobsJob)
admin.site.register(JobsResume)
admin.site.register(Candidate)
import time
import logging
logger = logging.getLogger(__name__)
def performance_logger_middleware(get_response):
def middleware(request):
start_time = time.time()
response = get_response(request)
duration = time.time() - start_time
response["X-Page-Duration-ms"] = int(duration * 1000)
logger.info("%s %s %s", duration, request.path, request.GET.dict() )
return response
return middleware
MIDDLEWARE = [
'interview.performance.performance_logger_middleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'simple': { # exact format is not important, this is the minimum information
'format': '%(asctime)s %(name)-12s %(lineno)d %(levelname)-8s %(message)s',
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'simple',
},
'mail_admins': { # Add Handler for mail_admins for `warning` and above
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
},
'file': {
#'level': 'INFO',
'class': 'logging.FileHandler',
'formatter': 'simple',
'filename': os.path.join(LOG_DIR, 'recruitment.admin.log'),
},
'performance': {
#'level': 'INFO',
'class': 'logging.FileHandler',
'formatter': 'simple',
'filename': os.path.join(LOG_DIR, 'recruitment.performance.log'),
},
},
'root': {
'handlers': ['console', 'file'],
'level': 'INFO',
},
'loggers': {
"django_python3_ldap": {
"handlers": ["console", "file"],
"level": "DEBUG",
},
"interview.performance": {
"handlers": ["console", "performance"],
"level": "INFO",
"propagate": False,
},
'django': {
"handlers": ["console","file"],
"level": "INFO",
'propagate': True,
},
},
}
from django.utils.translation import gettext_lazy as _
from django.db import models
from django.contrib.auth.models import User
from datetime import datetime
from django.utils.translation import gettext_lazy as _
# Create your models here.
# 候选人学历
DEGREE_TYPE = ((u'本科', u'本科'), (u'硕士', u'硕士'), (u'博士', u'博士'))
JobTypes = [
(0,"技术类"),
(1,"产品类"),
(2,"运营类"),
(3,"设计类"),
(4,"市场营销类")
]
Cities = [
(0,"北京"),
(1,"上海"),
(2,"深圳"),
(3,"杭州"),
(4,"广州")
]
class Job(models.Model):
# Translators: 职位实体的翻译
job_type = models.SmallIntegerField(blank=False, choices=JobTypes, verbose_name=_("职位类别"))
job_name = models.CharField(max_length=250, blank=False, verbose_name=_("职位名称"))
job_city = models.SmallIntegerField(choices=Cities, blank=False, verbose_name=_("工作地点"))
job_responsibility = models.TextField(max_length=1024, verbose_name=_("职位职责"))
job_requirement = models.TextField(max_length=1024, blank=False, verbose_name=_("职位要求"))
creator = models.ForeignKey(User, verbose_name=_("创建人"), null=True, on_delete=models.SET_NULL)
created_date = models.DateTimeField(verbose_name=_("创建日期"), auto_now_add=True)
modified_date = models.DateTimeField(verbose_name=_("修改日期"), auto_now=True)
class Meta:
verbose_name = _('职位')
verbose_name_plural = _('职位列表')
def __str__(self):
return self.job_name
class Resume(models.Model):
# Translators: 简历实体的翻译
username = models.CharField(max_length=135, verbose_name=_('姓名'))
applicant = models.ForeignKey(User, verbose_name=_("申请人"), null=True, on_delete=models.SET_NULL)
city = models.CharField(max_length=135, verbose_name=_('城市'))
phone = models.CharField(max_length=135, verbose_name=_('手机号码'))
email = models.EmailField(max_length=135, blank=True, verbose_name=_('邮箱'))
apply_position = models.CharField(max_length=135, blank=True, verbose_name=_('应聘职位'))
born_address = models.CharField(max_length=135, blank=True, verbose_name=_('生源地'))
gender = models.CharField(max_length=135, blank=True, verbose_name=_('性别'))
picture = models.ImageField(upload_to='images/', blank=True, verbose_name=_('个人照片'))
attachment = models.FileField(upload_to='file/', blank=True, verbose_name=_('简历附件'))
# 学校与学历信息
bachelor_school = models.CharField(max_length=135, blank=True, verbose_name=_('本科学校'))
master_school = models.CharField(max_length=135, blank=True, verbose_name=_('研究生学校'))
doctor_school = models.CharField(max_length=135, blank=True, verbose_name=u'博士生学校')
major = models.CharField(max_length=135, blank=True, verbose_name=_('专业'))
degree = models.CharField(max_length=135, choices=DEGREE_TYPE, blank=True, verbose_name=_('学历'))
created_date = models.DateTimeField(verbose_name="创建日期", default=datetime.now)
modified_date = models.DateTimeField(verbose_name="修改日期", auto_now=True)
# 候选人自我介绍,工作经历,项目经历
candidate_introduction = models.TextField(max_length=1024, blank=True, verbose_name=u'自我介绍')
work_experience = models.TextField(max_length=1024, blank=True, verbose_name=u'工作经历')
project_experience = models.TextField(max_length=1024, blank=True, verbose_name=u'项目经历')
class Meta:
verbose_name = _('简历')
verbose_name_plural = _('简历列表')
def __str__(self):
return self.username
使用{% translate “匠果科技开放职位” %}和{% blocktranslate with user_name=user.username %}
{# Load the tag library #}
{% load bootstrap4 %}
{% load i18n %}
{# Load CSS and JavaScript #}
{% bootstrap_css %}
{% bootstrap_javascript jquery='full' %}
{# Display django.contrib.messages as Bootstrap alerts #}
{% bootstrap_messages %}
<h1 style="margin:auto;width:50%">{% translate "匠果科技开放职位" %}h1>
<p>p>
{% block header %}
<a href="/" style="text-decoration: none; color:#007bff">{% translate "Homepage" %}a>
<a href="/joblist" style="text-decoration: none; color:#007bff">{% translate job_list" %}a>
{% if user.is_authenticated %}
<a href="/accounts/logout" style="text-decoration: none; color:#007bff">{% translate Logout" %}a>
{% else %}
<a href="/accounts/login" style="text-decoration: none; color:#007bff">{% translate Login" %}a>
{% endif %}
{% if user.is_authenticated %}
<p>{% blocktranslate with user_name=user.username %} 终于等到你 {{ user_name }}, 期待加入我们,用技术去探索一个新世界{% endblocktranslate %}p>
{% else %}
<br>{% translate "欢迎你,期待加入我们,登陆后可以提交简历."%}<br>
{% endif %}
{% endblock %}
{% block content %}
{% endblock %}
mkdir locale
django-admin makemessages -l zh_HANS -l en
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR , YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-12-02 06:55+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. Translators: 职位实体的翻译
#: .\jobs\models.py:29
msgid "职位类别"
msgstr "Position category"
#: .\jobs\models.py:30
msgid "职位名称"
msgstr "Job title"
#: .\jobs\models.py:31
msgid "工作地点"
msgstr "working place"
#: .\jobs\models.py:32
msgid "职位职责"
msgstr "responsibilities"
#: .\jobs\models.py:33
msgid "职位要求"
msgstr "Job Requirements"
#: .\jobs\models.py:34
msgid "创建人"
msgstr "Creator"
#: .\jobs\models.py:35
msgid "Creation date"
msgstr ""
#: .\jobs\models.py:36
msgid "modification date"
msgstr ""
#: .\jobs\models.py:39
msgid "职位"
msgstr "position"
#: .\jobs\models.py:40
msgid "职位列表"
msgstr "Position list"
#. Translators: 简历实体的翻译
#: .\jobs\models.py:50
msgid "姓名"
msgstr "full name"
#: .\jobs\models.py:51
msgid "申请人"
msgstr "applicant"
#: .\jobs\models.py:52
msgid "城市"
msgstr "city"
#: .\jobs\models.py:53
msgid "手机号码"
msgstr "phone number"
#: .\jobs\models.py:54
msgid "邮箱"
msgstr "mailbox"
#: .\jobs\models.py:55
msgid "应聘职位"
msgstr "Position Applied"
#: .\jobs\models.py:56
msgid "生源地"
msgstr "Place of origin"
#: .\jobs\models.py:57
msgid "性别"
msgstr "Gender"
#: .\jobs\models.py:58
msgid "个人照片"
msgstr "Personal photos"
#: .\jobs\models.py:59
msgid "简历附件"
msgstr "Resume attachment"
#: .\jobs\models.py:62
msgid "本科学校"
msgstr "Undergraduate school"
#: .\jobs\models.py:63
msgid "研究生学校"
msgstr "post-graduate schools"
#: .\jobs\models.py:65
msgid "专业"
msgstr "major"
#: .\jobs\models.py:66
msgid "学历"
msgstr "education"
#: .\jobs\models.py:76
msgid "简历"
msgstr "resume"
#: .\jobs\models.py:77
msgid "简历列表"
msgstr "Resume list"
#: .\jobs\templates\base.html:18
msgid "匠果科技开放职位"
msgstr "Open position of Jianguo Technology"
#: .\jobs\templates\base.html:23
msgid "Homepage"
msgstr ""
#: .\jobs\templates\base.html:24
msgid "job_list"
msgstr ""
#: .\jobs\templates\base.html:26
msgid "Logout"
msgstr ""
#: .\jobs\templates\base.html:28
msgid "Login"
msgstr ""
#: .\jobs\templates\base.html:31
#, python-format
msgid " 终于等到你 %(user_name)s, 期待加入我们,用技术去探索一个新世界"
msgstr "Finally, you %(user_name)s are looking forward to joining us and exploring a new world with technology"
#: .\jobs\templates\base.html:33
msgid "欢迎你,期待加入我们,登陆后可以提交简历."
msgstr "Welcome and look forward to joining us. You can submit your resume after logging in."
#: .\jobs\templates\base.html:51
msgid "Switch"
msgstr ""
#: .\recruitment\urls.py:30
msgid "招聘管理系统"
msgstr "Recruitment management system"
#: .\settings\base.py:115
msgid "Chinese"
msgstr ""
#: .\settings\base.py:116
msgid "English"
msgstr ""
django-admin compilemessages
MIDDLEWARE = [
...
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',### 多语言中间件
'django.middleware.common.CommonMiddleware',
...
]
# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/
LANGUAGES = [
('zh-hans', _('Chinese')),
('en', _('English')),
]
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = True
LOCALE_PATHS = (
os.path.join(BASE_DIR, 'locale'),
)
<div style="flex: 1; align-content:right;">
<form action="{% url 'set_language' %}" method="post" style="margin-block-end: 0em;">{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}">
<select name="language">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
path('i18n/', include('django.conf.urls.i18n')),
参考文章https://blog.csdn.net/weixin_30836759/article/details/99920251
https://blog.csdn.net/yangjianrong1985/article/details/106913358
https://gitee.com/fqzhang/onpremise
class PerformanceAndExceptionLoggerMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
start_time = time.time()
response = self.get_response(request)
duration = time.time() - start_time
response["X-Page-Duration-ms"] = int(duration * 1000)
logger.info("duration:%s url:%s parameters:%s", duration, request.path, request.GET.dict() )
# Code to be executed for each request/response after
# the view is called.
return response
def process_exception(self, request, exception):
if exception:
message = "url:{url} ** msg:{error} ````{tb}````".format(
url = request.build_absolute_uri(),
error = repr(exception),
tb = traceback.format_exc()
)
logger.warning(message)
# send dingtalk message
dingtalk.send(message)
# capture exception to sentry:
capture_exception(exception)
return HttpResponse("Error processing the request, please contact the system administrator.", status=500)
简单来说,使用render就可以避免XSS跨站JS脚本攻击。
简单来说,template使用CSRF令牌避免CSRF跨站请求伪造,数据查询不要在使用原始SQL查询时还使用参数就可以避免SQL注入攻击(使用ORM查询数据最安全)。
https://www.django-rest-framework.org/
pip install djangorestframework
pip install markdown # Markdown support for the browsable API.
pip install django-filter # Filtering support
INSTALLED_APPS = [
...
'rest_framework',
]
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
}
from django.contrib.auth.models import User
from rest_framework import routers, serializers, viewsets
from jobs.models import Job
#### rest_framework
# Serializers define the API representation.
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ['url', 'username', 'email', 'is_staff']
# ViewSets define the view behavior.
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
class JobSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Job
fields = '__all__'
class JobViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows groups to be viewed or edited.
"""
queryset = Job.objects.all()
serializer_class = JobSerializer
# Routers provide an easy way of automatically determining the URL conf.
router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'jobs', JobViewSet)
urlpatterns = [
...
# django rest api & api auth (login/logout)
path('api/', include(router.urls)),
path('api-auth/', include('rest_framework.urls')),
]
https://django-redis-chs.readthedocs.io/zh_CN/latest/
链接
定位到redis解压缩后的文件夹中, 打开命令提示符对话框输入"cmd"。然后在命令窗口输入“redis-server.exe redis.windows.conf”出现如下界面即成功启动。
双击redis-server.exe可启动redis服务
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple django_redis
MIDDLEWARE = [
'interview.performance.performance_logger_middleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.cache.UpdateCacheMiddleware',#redis中间件
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',#redis中间件
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
#"PASSWORD":"mysecret",
"SOCKET_CONNECT_TIMEOUT": 5, # in seconds
"SOCKET_TIMEOUT": 5, # r/w timeout in seconds
}
}
}
1.默认缓存10分钟,我还不知道在哪改。
2.目前换用户登录后,后一个用户可以访问到前一个用户的访问信息。需要redis清空缓存,请见下方做法。
https://blog.csdn.net/lthahaha/article/details/118926226
celery文档
中文非官方文档
run_task.py脚本是用来运行task.py脚本。
#!coding=utf-8
from celery import Celery
# 第一个参数 是当前脚本的名称,第二个参数 是 broker 服务地址
app = Celery('tasks', backend='redis://127.0.0.1', broker='redis://127.0.0.1')
@app.task
def add(x, y):
return x + y
#coding=utf-8
from tasks import add
result = add.delay(4, 4)
print('Is task ready: %s' % result.ready())
run_result = result.get(timeout=1)
print('task result: %s' % run_result)
C:\Users\Season\Desktop\4.python网页前后端\Django基础教程\workspace4-recruiting\recruitment【40】Django与Celery 集成:Celery的使用\recruitment\celery>celery -A tasks worker --loglevel=INFO
C:\Users\Season\Desktop\4.python网页前后端\Django基础教程\workspace4-recruiting\recruitment【40】Django与Celery 集成:Celery的使用\recruitment\celery>python run_task.py
C:\Users\Season\Desktop\4.python网页前后端\Django基础教程\workspace4-recruiting\recruitment【40】Django与Celery 集成:Celery的使用\recruitment\celery>celery -A tasks worker --loglevel=INFO -P eventlet
C:\Users\Season\Desktop\4.python网页前后端\Django基础教程\workspace4-recruiting\recruitment【40】Django与Celery 集成:Celery的使用\recruitment\celery>python run_task.py
https://blog.csdn.net/qq_30242609/article/details/79047660
参考链接
Celery提供了一个工具flower,将各个任务的执行情况、各个worker的健康状态进行监控并以可视化的方式展现。
1.安装flower:
pip install flower
2.启动flower
例如启动项目工程下面celery_tasks目录的main.py 异步任务启动函数
flower -A celery_tasks.main --port=5555
我的启动如下
celery -A tasks flower --broker=redis://localhost:6379/0
3.进入http://localhost:5555即可查看。
4.可以查看发送的任务详情信息
https://docs.celeryproject.org/en/master/django/first-steps-with-django.html#using-celery-with-django
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings.base')
app = Celery('recruitment')
# 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 app configs.
app.autodiscover_tasks()
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
from __future__ import absolute_import, unicode_literals
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app
__all__ = ('celery_app',)
CELERY_BROKER_URL = 'redis://redis:6379/0'
CELERY_RESULT_BACKEND = 'redis://redis:6379/1'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERYD_MAX_TASKS_PER_CHILD = 10
CELERYD_LOG_FILE = os.path.join(BASE_DIR, "logs", "celery_work.log")
CELERYBEAT_LOG_FILE = os.path.join(BASE_DIR, "logs", "celery_beat.log")
from __future__ import absolute_import, unicode_literals
from celery import shared_task
from .dingtalk import send
@shared_task
def send_dingtalk_message(message):
send(message)
from .tasks import send_dingtalk_message
# 通知一面面试官面试
def notify_interviewer(modeladmin, request, queryset):
candidates = ""
interviewers = ""
for obj in queryset:
candidates = obj.username + ";" + candidates
interviewers = obj.first_interviewer_user.username + ";" + interviewers
# 这里的消息发送到钉钉, 或者通过 Celery 异步发送到钉钉
#dingtalk.send ("候选人 %s 进入面试环节,亲爱的面试官,请准备好面试: %s" % (candidates, interviewers) )
send_dingtalk_message.delay("候选人 %s 进入面试环节,亲爱的面试官,请准备好面试: %s" % (candidates, interviewers) )
messages.add_message(request, messages.INFO, '已经成功发送面试通知')
redis缓存服务(双击redis-server.exe)
celery异步服务(有bug未启动完成)
celery -A proj worker -l INFO
我的项目https://blog.csdn.net/m0_46629123/article/details/126495062
pip install django-celery-beat
INSTALLED_APPS = [
'simpleui',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'GAGA_meeting',
'django_celery_beat',
]
python manage.py makemigrations
python manage.py migrate
celery -A GAGA beat --scheduler django_celery_beat.schedulers:DatabaseScheduler
https://blog.csdn.net/m0_46629123/article/details/126495062
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
## 媒体文件夹路由:读取"/static/"的数据
re_path('media/(?P.*)' , serve, {'document_root':settings.MEDIA_ROOT},name='media'),
picture = models.ImageField(upload_to='images/', blank=True, verbose_name=_('个人照片'))
attachment = models.FileField(upload_to='file/', blank=True, verbose_name=_('简历附件'))
class reward(models.Model):
# 奖品
id = models.AutoField(primary_key=True)
reward_name = models.CharField(max_length=135, blank=True, null=True, verbose_name=u'奖品名称')
reward_image = models.ImageField(max_length=135, blank=True, null=True, verbose_name=u'奖品照片',upload_to='static\images')
reward_score = models.IntegerField(blank=True, null=True,verbose_name=u'奖品积分')
reward_inventory_total = models.IntegerField(blank=True, null=True, verbose_name=u'奖品入库总量')
reward_inventory_used = models.IntegerField(blank=True, null=True, verbose_name=u'奖品使用量')
reward_inventory_left = models.IntegerField(blank=True, null=True, verbose_name=u'奖品剩余量')
class Meta:
db_table = u'reward'
verbose_name = u'奖品'
verbose_name_plural = u'奖品'
def __str__(self):
return self.reward_name
## 列表页显示图片
def image_img(self):
if not self.reward_image:
return '无'
return format_html(
"""""",
self.reward_image.url)
image_img.short_description = '图片'
## 列表页显示图片
def image_img(self):
if not self.reward_image:
return '无'
return format_html(
"""""",
self.reward_image.url)
image_img.short_description = '图片'
# 生成全部表
python manage.py inspectdb --database==running
# 生成指定表
python manage.py inspectdb --database==running area city >models.py
INSTALLED_APPS = [
...
'running',
...
]
from django.contrib import admin
# Register your models here.
from .models import JobsJob,JobsResume,Candidate
admin.site.register(JobsJob)
admin.site.register(JobsResume)
admin.site.register(Candidate)
DATABASE_ROUTERS = ['settings.router.DatabaseRouter']
# settings/router.py
# database router to multiple database by app label
class DatabaseRouter:
route_app_labels = {'running'}
def db_for_read(self, model, **hints):
if model._meta.app_label in self.route_app_labels:
return 'running'
return 'default'
def db_for_write(self, model, **hints):
if model._meta.app_label in self.route_app_labels:
return 'running'
return 'default'
def allow_relation(self, obj1, obj2, **hints):
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
遗留数据库中的表不允许迁移
"""
if app_label in self.route_app_labels:
return False
return True
class City(models.Model):
cityid = models.AutoField(primary_key=True)
countryid = models.ForeignKey(Country, db_column='countryid', null=True, on_delete=models.SET_NULL)
areaid = models.PositiveIntegerField(blank=True, null=True)
provinceid = models.ForeignKey(Province, db_column='provinceid', null=True, on_delete=models.SET_NULL)
chn_name = models.CharField(max_length=64)
eng_name = models.CharField(max_length=64, blank=True, null=True)
sort = models.PositiveIntegerField()
class Meta:
managed = False
db_table = 'city'
def __str__(self):
return self.chn_name if self.chn_name else self.eng_name if self.eng_name else ""
@admin.register(City)
class CityAdmin(ReadOnlyAdmin):
autocomplete_fields = ['provinceid','countryid',]
class ReadOnlyAdmin(admin.ModelAdmin):
readonly_fields = []
def get_list_display(self, request):
return [field.name for field in self.model._meta.concrete_fields]
def get_readonly_fields(self, request, obj=None):
return list(self.readonly_fields) + \
[field.name for field in obj._meta.fields] + \
[field.name for field in obj._meta.many_to_many]
def has_add_permission(self, request):
return False
def has_delete_permission(self, request, obj=None):
return False
def has_change_permission(self, request, obj=None):
return False
@admin.register(Country)
class CountryAdmin(ReadOnlyAdmin):
search_fields = ('chn_name', 'eng_name',)
```python
INSTALLED_APPS = [
...
'running',]
INSTALLED_APPS = [
'simpleui',
.....
]
https://django-debug-toolbar.readthedocs.io/en/latest/installation.html
settings.py设定
"""
Django settings for training_system project.
Generated by 'django-admin startproject' using Django 3.2.7.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/
"""
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
#BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
BASE_DIR = Path(__file__).resolve().parent.parent
#BASE_DIR = Path(__file__).resolve()
print('BASE_DIR',BASE_DIR)
#print('BASE_DIR2',os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-$z^45$dg5xl!3oo@ma54#n&9x-3p3_*6g^719c80xy*0dww7u='
# SECURITY WARNING: don't run with debug turned on in production!
#DEBUG = False
DEBUG = True
if DEBUG == True:
INTERNAL_IPS = ['127.0.0.1', ]
DEBUG_TOOLBAR_CONFIG = {
'JQUERY_URL': 'https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js',
'SHOW_COLLAPSED': True,
'SHOW_TOOLBAR_CALLBACK': lambda x: True,
}
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'simpleui',
#'grappelli',
'bootstrap4',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'training',
'debug_toolbar',
]
MIDDLEWARE = [
'debug_toolbar.middleware.DebugToolbarMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
#'django.middleware.cache.UpdateCacheMiddleware',#redis中间件
'django.middleware.common.CommonMiddleware',
#'django.middleware.cache.FetchFromCacheMiddleware',#redis中间件
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'training_system.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'training_system.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
print(Path(__file__).resolve().parent)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
#'NAME': BASE_DIR / 'db.sqlite3',
'NAME': Path(__file__).resolve().parent /'SQL' /'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/
# 修改中文,Django内部设置zh_Hans方法指向中文
LANGUAGE_CODE = 'zh-hans'
# 修改中国时区
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
#USE_L10N = True
USE_L10N = False
DATETIME_FORMAT = 'Y-m-d H:i:s'
DATE_FORMAT = 'Y-m-d'
#USE_TZ = True
USE_TZ = False
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
# 通过url直接访问我在项目中的静态文件
STATIC_URL = '/static/'
# 部署静态文件时(pyhtonmanage.pycollectstatic)所有的静态文静聚合的目录
STATIC_ROOT = os.path.join(BASE_DIR, "/static/")
# STATICFILES_DIRS告诉django,首先到STATICFILES_DIRS里面寻找静态文件,其次再到各个app的static文件夹里面找
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
LOGIN_URL = '/user_login/'
# CACHES = {
# "default": {
# "BACKEND": "django_redis.cache.RedisCache",
# "LOCATION": "redis://127.0.0.1:6379/1",
# "OPTIONS": {
# "CLIENT_CLASS": "django_redis.client.DefaultClient",
# "PASSWORD":"mysecret",
# "SOCKET_CONNECT_TIMEOUT": 5, # in seconds
# "SOCKET_TIMEOUT": 5, # r/w timeout in seconds
# }
# }
# }