一、CRM简介

  crm 客户关系管理软件 ( Customer Relationship Management )。

  

二、CRM起步

1、设计表结构和数据库迁移

  

from django.db import models

class Department(models.Model):
"""
部门表
市场部 1000
销售 1001 """
title = models.CharField(verbose_name='部门名称', max_length=16)
code = models.IntegerField(verbose_name='部门编号', unique=True, null=False) def __str__(self):
return self.title class UserInfo(models.Model):
"""
员工表
"""
name = models.CharField(verbose_name='员工姓名', max_length=16)
username = models.CharField(verbose_name='用户名', max_length=32)
password = models.CharField(verbose_name='密码', max_length=64)
email = models.EmailField(verbose_name='邮箱', max_length=64)
# 模仿 SQL 约束 ON DELETE CASCADE 的行为,换句话说,删除一个对象时也会删除与它相关联的外键对象。
depart = models.ForeignKey(verbose_name='部门', to="Department", to_field="code", on_delete=models.CASCADE) def __str__(self):
return self.name class Course(models.Model):
"""
课程表
如:
Linux基础
Linux架构师
Python自动化开发精英班
Python自动化开发架构师班
Python基础班
go基础班
"""
name = models.CharField(verbose_name='课程名称', max_length=32) def __str__(self):
return self.name class School(models.Model):
"""
校区表
如:
北京沙河校区
上海校区 """
title = models.CharField(verbose_name='校区名称', max_length=32) def __str__(self):
return self.title class ClassList(models.Model):
"""
班级表
如:
Python全栈 面授班 5期 10000 2017-11-11 2018-5-11
"""
school = models.ForeignKey(verbose_name='校区', to='School', on_delete=models.CASCADE)
course = models.ForeignKey(verbose_name='课程名称', to='Course', on_delete=models.CASCADE) semester = models.IntegerField(verbose_name="班级(期)")
price = models.IntegerField(verbose_name="学费")
start_date = models.DateField(verbose_name="开班日期")
graduate_date = models.DateField(verbose_name="结业日期", null=True, blank=True)
memo = models.CharField(verbose_name='说明', max_length=256, blank=True, null=True, )
# teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo',limit_choices_to={'depart_id__in':[1003,1004],})
teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo', related_name="abc", limit_choices_to={"depart__in":[1002,1005]})
tutor = models.ForeignKey(verbose_name='班主任', to='UserInfo', related_name='classes', limit_choices_to={"depart": 1001}, on_delete=models.CASCADE) def __str__(self):
return "{0}({1}期)".format(self.course.name, self.semester) class Customer(models.Model):
"""
客户表
"""
qq = models.CharField(verbose_name='qq', max_length=64, unique=True, help_text='QQ号必须唯一') name = models.CharField(verbose_name='学生姓名', max_length=16)
gender_choices = ((1, '男'), (2, '女'))
gender = models.SmallIntegerField(verbose_name='性别', choices=gender_choices) education_choices = (
(1, '重点大学'),
(2, '普通本科'),
(3, '独立院校'),
(4, '民办本科'),
(5, '大专'),
(6, '民办专科'),
(7, '高中'),
(8, '其他')
)
education = models.IntegerField(verbose_name='学历', choices=education_choices, blank=True, null=True, )
graduation_school = models.CharField(verbose_name='毕业学校', max_length=64, blank=True, null=True)
major = models.CharField(verbose_name='所学专业', max_length=64, blank=True, null=True) experience_choices = [
(1, '在校生'),
(2, '应届毕业'),
(3, '半年以内'),
(4, '半年至一年'),
(5, '一年至三年'),
(6, '三年至五年'),
(7, '五年以上'),
]
experience = models.IntegerField(verbose_name='工作经验', blank=True, null=True, choices=experience_choices)
work_status_choices = [
(1, '在职'),
(2, '无业')
]
work_status = models.IntegerField(verbose_name="职业状态", choices=work_status_choices, default=1, blank=True,
null=True)
company = models.CharField(verbose_name="目前就职公司", max_length=64, blank=True, null=True)
salary = models.CharField(verbose_name="当前薪资", max_length=64, blank=True, null=True) source_choices = [
(1, "qq群"),
(2, "内部转介绍"),
(3, "官方网站"),
(4, "百度推广"),
(5, "360推广"),
(6, "搜狗推广"),
(7, "腾讯课堂"),
(8, "广点通"),
(9, "高校宣讲"),
(10, "渠道代理"),
(11, "51cto"),
(12, "智汇推"),
(13, "网盟"),
(14, "DSP"),
(15, "SEO"),
(16, "其它"),
]
source = models.SmallIntegerField('客户来源', choices=source_choices, default=1)
referral_from = models.ForeignKey(
'self',
blank=True,
null=True,
verbose_name="转介绍自学员",
help_text="若此客户是转介绍自内部学员,请在此处选择内部学员姓名",
related_name="internal_referral",
on_delete = models.CASCADE
)
course = models.ManyToManyField(verbose_name="咨询课程", to="Course") status_choices = [
(1, "已报名"),
(2, "未报名")
]
status = models.IntegerField(
verbose_name="状态",
choices=status_choices,
default=2,
help_text=u"选择客户此时的状态"
) consultant = models.ForeignKey(verbose_name="课程顾问", to='UserInfo', related_name='consultanter',
limit_choices_to={'depart_id': 1001}, on_delete=models.CASCADE) date = models.DateField(verbose_name="咨询日期", auto_now_add=True)
recv_date = models.DateField(verbose_name="当前课程顾问的接单日期", null=True)
last_consult_date = models.DateField(verbose_name="最后跟进日期", ) def __str__(self):
return "姓名:{0},QQ:{1}".format(self.name, self.qq, ) class ConsultRecord(models.Model):
"""
客户跟进记录
"""
customer = models.ForeignKey(verbose_name="所咨询客户", to='Customer', on_delete=models.CASCADE)
consultant = models.ForeignKey(verbose_name="跟踪人", to='UserInfo', on_delete=models.CASCADE)
date = models.DateField(verbose_name="跟进日期", auto_now_add=True)
note = models.TextField(verbose_name="跟进内容...") def __str__(self):
return self.customer.name + ":" + self.consultant.name class Student(models.Model):
"""
学生表(已报名)
"""
customer = models.OneToOneField(verbose_name='客户信息', to='Customer', on_delete=models.CASCADE) username = models.CharField(verbose_name='用户名', max_length=32)
password = models.CharField(verbose_name='密码', max_length=64)
emergency_contract = models.CharField(max_length=32, blank=True, null=True, verbose_name='紧急联系人') class_list = models.ManyToManyField(verbose_name="已报班级", to='ClassList', blank=True)
company = models.CharField(verbose_name='公司', max_length=128, blank=True, null=True)
location = models.CharField(max_length=64, verbose_name='所在区域', blank=True, null=True)
position = models.CharField(verbose_name='岗位', max_length=64, blank=True, null=True)
salary = models.IntegerField(verbose_name='薪资', blank=True, null=True)
welfare = models.CharField(verbose_name='福利', max_length=256, blank=True, null=True)
date = models.DateField(verbose_name='入职时间', help_text='格式yyyy-mm-dd', blank=True, null=True)
memo = models.CharField(verbose_name='备注', max_length=256, blank=True, null=True) def __str__(self):
return self.username class CourseRecord(models.Model):
"""
上课记录表
"""
class_obj = models.ForeignKey(verbose_name="班级", to="ClassList", on_delete=models.CASCADE)
day_num = models.IntegerField(verbose_name="节次", help_text=u"此处填写第几节课或第几天课程...,必须为数字")
teacher = models.ForeignKey(verbose_name="讲师", to='UserInfo',limit_choices_to={"depart_id__in":[1002,1003]}, on_delete=models.CASCADE)
date = models.DateField(verbose_name="上课日期", auto_now_add=True) course_title = models.CharField(verbose_name='本节课程标题', max_length=64, blank=True, null=True)
course_memo = models.TextField(verbose_name='本节课程内容概要', blank=True, null=True)
has_homework = models.BooleanField(default=True, verbose_name="本节有作业")
homework_title = models.CharField(verbose_name='本节作业标题', max_length=64, blank=True, null=True)
homework_memo = models.TextField(verbose_name='作业描述', max_length=500, blank=True, null=True)
exam = models.TextField(verbose_name='踩分点', max_length=300, blank=True, null=True) def __str__(self):
return "{0} day{1}".format(self.class_obj, self.day_num) class StudyRecord(models.Model):
course_record = models.ForeignKey(verbose_name="第几天课程", to="CourseRecord", on_delete=models.CASCADE)
student = models.ForeignKey(verbose_name="学员", to='Student', on_delete=models.CASCADE)
record_choices = (('checked', "已签到"),
('vacate', "请假"),
('late', "迟到"),
('noshow', "缺勤"),
('leave_early', "早退"),
)
record = models.CharField("上课纪录", choices=record_choices, default="checked", max_length=64)
score_choices = ((100, 'A+'),
(90, 'A'),
(85, 'B+'),
(80, 'B'),
(70, 'B-'),
(60, 'C+'),
(50, 'C'),
(40, 'C-'),
(0, ' D'),
(-1, 'N/A'),
(-100, 'COPY'),
(-1000, 'FAIL'),
)
score = models.IntegerField("本节成绩", choices=score_choices, default=-1)
homework_note = models.CharField(verbose_name='作业评语', max_length=255, blank=True, null=True)
note = models.CharField(verbose_name="备注", max_length=255, blank=True, null=True) homework = models.FileField(verbose_name='作业文件', blank=True, null=True, default=None)
stu_memo = models.TextField(verbose_name='学员备注', blank=True, null=True)
date = models.DateTimeField(verbose_name='提交作业日期', auto_now_add=True) def __str__(self):
return "{0}-{1}".format(self.course_record, self.student)

models.py

  注意要给ForeignKey和OneToOneField字段添加on_delete=models.CASCADE 属性。

执行数据库迁移:

manage.py@CRM_demo > makemigrations
manage.py@CRM_demo > migrate

2、引入stark组件

  将前面订制的stark组件代码拷入CRM项目中:(stark_demo中的templates目录文件复制到stark下)

  

  在settings.py中添加stark应用信息:

INSTALLED_APPS = [
'django.contrib.admin',
......
'stark.apps.StarkConfig'
]

3、注册stark

  app01/stark.py:

from stark.service.stark import site
from .models import * site.register(School)
site.register(UserInfo)
site.register(ClassList)
site.register(Student)
site.register(Customer)
site.register(Department)
site.register(Course)
site.register(ConsultRecord)
site.register(CourseRecord)
site.register(StudyRecord)

4、路由配置urls.py

from django.contrib import admin
from django.urls import path
from stark.service.stark import site urlpatterns = [
path('admin/', admin.site.urls),
path('stark/', site.urls)
]

三、录入数据

1、录入校区

  

2、录入课程

  

3、录入部门

  

4、录入员工用户

  

5、添加班级

  

  此处涉及models.py中modelform的limit_choices_to属性应用。

  

6、添加咨询客户

  

7、添加客户跟进记录

  

8、添加学生表

  

四、crm/stark.py编写自定义配置

# -*- coding:utf-8 -*-
__author__ = 'Qiushi Huang' from stark.service.stark import site, ModelStark from .models import *
from django.utils.safestring import mark_safe
from django.shortcuts import HttpResponse, redirect site.register(School) class UserConfig(ModelStark):
list_display = ["name", "email", "depart"] site.register(UserInfo, UserConfig) class ClassConfig(ModelStark):
def display_classname(self, obj=None, header=False):
# 班级名
if header:
return "班级名称"
# 将课程名和班级期数合并为班级名
# obj.course是课程对象 obj.course.name是课程名称 obj.semester是数字需要转字符串
class_name = "%s(%s)" % (obj.course.name, str(obj.semester))
return class_name list_display = [display_classname, "tutor", "teachers"] site.register(ClassList, ClassConfig) class StudentConfig(ModelStark):
list_display = ['customer', 'class_list']
list_display_links = ['customer'] site.register(Student, StudentConfig) from django.conf.urls import url class CustomerConfig(ModelStark):
# 如果要展示性别
def display_gender(self, obj=None, header=False):
if header:
return "性别"
return obj.get_gender_display() def display_course(self, obj=None, header=False): # obj:客户对象
"""咨询的课程"""
if header:
return "课程"
temp = []
for course in obj.course.all(): # 遍历所有的课程
s = "<a href='/stark/crm/customer/cancel_course/%s/%s' " \
"style='border:1px solid #369;padding:3px 6px;'>" \
"<span>%s</span></a>&nbsp;" % (obj.pk, course.pk, course.name)
temp.append(s)
return mark_safe("".join(temp)) def cancel_course(self, request, customer_id, course_id):
print(customer_id, course_id) obj = Customer.objects.filter(pk=customer_id).first()
obj.course.remove(course_id) # 删除对象所有的关联课程
return redirect(self.get_list_url()) # 重定向当前表的查看页面 def extra_url(self):
"""扩展路由"""
temp = []
temp.append(url((r"cancel_course/(\d+)/(\d+)"), self.cancel_course))
return temp list_display = ["name", display_gender, display_course, "consultant"] site.register(Customer, CustomerConfig) class DepartmentConfig(ModelStark):
list_display = ['title', 'code'] site.register(Department, DepartmentConfig)
site.register(Course) class ConsultRecordConfig(ModelStark):
list_display = ["customer", "consultant", "date", "note"] site.register(ConsultRecord, ConsultRecordConfig)
site.register(CourseRecord)
site.register(StudyRecord)

crm/stark.py

重点:

1、limit_choices_to()

class ClassList(models.Model):
"""
班级表
"""
# limit_choices_to设置限制条件,只是用来告诉modelform怎么去取option对象
# teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo',limit_choices_to={'depart_id__in':[1003,1004],})
teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo', related_name="abc", limit_choices_to={"depart__in":[1002,1005]}) # __in设置条件
# tutor即班主任,也就是销售
tutor = models.ForeignKey(verbose_name='班主任', to='UserInfo', related_name='classes', limit_choices_to={"depart": 1001}, on_delete=models.CASCADE)

2、将form调整操作从add_view解耦,为change_view添加该功能

  将之前serivce/stark.py中add_view视图函数中对form的调整分拆出来:

class ModelStark(object):
"""默认类,定制配置类""" def get_new_form(self, form):
"""form调整,给特殊字段添加属性修改url"""
for bound_field in form: # 拿到每一个字段
# from django.forms.boundfield import BoundField
# print(bound_field.field) # 字段对象
print(bound_field.name) # title\publishDate\publish 字段名称
# print(type(bound_field.field)) # 字段类型
from django.forms.models import ModelChoiceField # ModelMultipleChoiceField继承ModelChoiceField
if isinstance(bound_field.field, ModelChoiceField): # 通过这个判断是否是一对多或多对多的字段对象
bound_field.is_pop = True # 给所有一对多、多对多对象添加is_pop这个属性 # 需要拿到的不是当前表而是字段关联表
print("===》", bound_field.field.queryset.model)
"""
一对多或者多对多字段的关联模型表
<class 'app01.models.Publish'>
<class 'app01.models.Author'>
"""
# 拿到模型名和应用名
related_model_name = bound_field.field.queryset.model._meta.model_name
related_app_label = bound_field.field.queryset.model._meta.app_label
# 拼出添加页面地址
_url = reverse("%s_%s_add" % (related_app_label, related_model_name))
# url拿到后,再在后面拼接字段名称
bound_field.url = _url + "?pop_res_id=id_%s" % bound_field.name # /?pop_res_id=id_authors
return form def add_view(self, request):
"""添加页面视图"""
ModelFormDemo = self.get_modelform_class()
form = ModelFormDemo() # 实例化步骤提前不管是post请求还是get请求都会传递到模板中 form = self.get_new_form(form) if request.method == "POST":
form = ModelFormDemo(request.POST)
if form.is_valid(): # 校验字段全部合格
obj = form.save() # 将数据保存到数据库
print(obj) # 拿到返回值:当前生成的记录
pop_res_id = request.GET.get("pop_res_id") # 拿到window.open打开页面后面的get请求 if pop_res_id:
# 当属于window.open页面post请求
res = {"pk": obj.pk, "text": str(obj), "pop_res_id": pop_res_id} return render(request, "pop.html", {"res": res})
else:
# 跳转到当前访问表的查看页面
return redirect(self.get_list_url())
# 校验有错误返回页面,且包含了错误信息 return render(request, "add_view.html", locals()) def delete_view(self, request, id):
url = self.get_list_url()
if request.method == "POST":
self.model.objects.filter(pk=id).delete()
return redirect(url) # self.model.objects.filter(pk=id).delete()
return render(request, "delete_view.html", locals()) def change_view(self, request, id):
"""编辑视图"""
ModelFormDemo = self.get_modelform_class() # 拿到当前配置类
# 拿到编辑对象
edit_obj = self.model.objects.filter(pk=id).first() if request.method == "POST":
form = ModelFormDemo(request.POST, instance=edit_obj) # instance就是给这个记录更改为最新的数据
if form.is_valid(): # 校验字段全部合格
form.save()
return redirect(self.get_list_url()) # 跳转到当前访问表的查看页面 # (精髓)校验有错误返回页面,且包含了错误信息
return render(request, "add_view.html", locals()) form = ModelFormDemo(instance=edit_obj) # 用instance放入编辑对象就有了编辑数据
form = self.get_new_form(form) return render(request, "change_view.html", locals())

3、循环名字覆盖的问题

class ShowList(object):
"""展示页面类"""
def get_body(self):
"""构建表单数据"""
new_data_list = []
# for obj in self.data_list:
for obj in self.page_data: # 当前页面的数据
temp = []
for field in self.config.new_list_display(): # ["__str__", ] ["pk","name","age",edit]
if callable(field):
val = field(self.config, obj)
else:
try: # 如果是普通字段
field_obj = self.config.model._meta.get_field(field) # 拿到字段对象
if isinstance(field_obj, ManyToManyField): # 判断是否是多对多
# 反射处理 增加.all
# 多对多的情况 obj.field.all()
ret = getattr(obj, field).all() # <QuerySet [<Author: alex>, <Author: egon>]>
t = []
for mobj in ret: # 多对多的对象
t.append(str(mobj))
val = ",".join(t) # 用join方法实现拼接 alex,egon else:
# 非多对多的情况
val = getattr(obj, field) # 拿到的关联对象 处理不了多对多
if field in self.config.list_display_links:
# _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))
_url = self.config.get_change_url(obj) val = mark_safe("<a href='%s'>%s</a>" % (_url, val))
except Exception as e: # 如果是__str__
val = getattr(obj, field) # 反射拿到对象__str__函数的返回值 self.name 武汉大学出版社
print(val) # <bound method Publish.__str__ of <Publish: 武汉大学出版社>>
temp.append(val) new_data_list.append(temp)
return new_data_list

  多层循环一定要注意起名字,不能都使用obj作为循环的变量,会导致数据紊乱。

4、模型(model)中的choices字段的使用

  Django模型中的字段有个choices属性,这个属性可以提供被选数据。如果一个字段设置了这个属性,在模版中如果我要显示这个字段,那么django模版系统就会将它默认解析为一个下拉菜单。

crm/models.py:

class Customer(models.Model):
"""客户表"""
qq = models.CharField(verbose_name='qq', max_length=64, unique=True, help_text='QQ号必须唯一')
name = models.CharField(verbose_name='学生姓名', max_length=16)
gender_choices = ((1, '男'), (2, '女'))
gender = models.SmallIntegerField(verbose_name='性别', choices=gender_choices)

crm/stark.py:

  obj.gender拿到数据库存的值:1/2

  使用obj.get_gender_display()拿到存的值对应显示的值:男/女

class CustomerConfig(ModelStark):
# 如果要展示性别
def display_gender(self, obj=None, header=False):
if header:
return "性别"
return obj.get_gender_display() list_display = ["name", display_gender] site.register(Customer, CustomerConfig)

4、在自定义配置类,定制展示字段a标签

from django.utils.safestring import mark_safe

class CustomerConfig(ModelStark):
# 如果要展示性别
def display_gender(self, obj=None, header=False):
if header:
return "性别"
return obj.get_gender_display() def display_course(self, obj=None, header=False):
"""咨询的课程"""
if header:
return "课程"
temp = []
for course in obj.course.all(): # 遍历所有的课程
s = "<a href='/stark/crm/customer/cancel_course/%s/%s' " \
"style='border:1px solid #369;padding:3px 6px;'>" \
"<span>%s</span></a> " % (obj.pk, course.pk, course.name)
temp.append(s)
return mark_safe("".join(temp)) list_display = ["name", display_gender, display_course, "consultant"] site.register(Customer, CustomerConfig)

  显示效果:

  

5、扩展url和视图

  在客户页面,点击客户咨询过得课程取消客户课程。这里需要添加一个url,url:/stark/crm/customer/cancel_course/1/3的形式。

(1)首先在service/stark.py中添加url扩展接口

class ModelStark(object):
"""默认类,定制配置类"""
def extra_url(self):
# 扩展路由,自定义配置没有配置则默认为空
return [] def get_urls_2(self):
temp = []
# 用name取别名app名+model名+操作名可以保证别名不会重复
model_name = self.model._meta.model_name
app_label = self.model._meta.app_label
temp.append(url(r"^add/", self.add_view, name="%s_%s_add" % (app_label, model_name)))
temp.append(url(r"^(\d+)/delete/", self.delete_view, name="%s_%s_delete" % (app_label, model_name)))
temp.append(url(r"^(\d+)/change/", self.change_view, name="%s_%s_change" % (app_label, model_name)))
temp.append(url(r"^$", self.list_view, name="%s_%s_list" % (app_label, model_name)))
# 添加扩展路由接口
temp.extend(self.extra_url()) return temp

(2)在Customer自定义配置类订制取消路由和视图

from django.conf.urls import url
from django.shortcuts import HttpResponse, redirect class CustomerConfig(ModelStark):
# 如果要展示性别
def display_gender(self, obj=None, header=False):
if header:
return "性别"
return obj.get_gender_display() def display_course(self, obj=None, header=False): # obj:客户对象
"""咨询的课程"""
if header:
return "课程"
temp = []
for course in obj.course.all(): # 遍历所有的课程
s = "<a href='/stark/crm/customer/cancel_course/%s/%s' " \
"style='border:1px solid #369;padding:3px 6px;'>" \
"<span>%s</span></a> " % (obj.pk, course.pk, course.name)
temp.append(s)
return mark_safe("".join(temp)) def cancel_course(self, request, customer_id, course_id):
print(customer_id, course_id) obj = Customer.objects.filter(pk=customer_id).first()
obj.course.remove(course_id) # 删除对象所有的关联课程
return redirect(self.get_list_url()) # 重定向当前表的查看页面 def extra_url(self):
"""扩展路由"""
temp = []
temp.append(url((r"cancel_course/(\d+)/(\d+)"), self.cancel_course))
return temp list_display = ["name", display_gender, display_course, "consultant"] site.register(Customer, CustomerConfig)

  注意a标签href地址。

(3)显示效果

  点击标签删除对应的课程。

  

CRM——起步的更多相关文章

  1. CRM - 起步

    一.crm简介 crm 客户关系管理软件 ( Customer Relationship Management ) 二.起步 models.py 表结构 from django.db import m ...

  2. Django - 学习目录

    Django 基础 web应用/http协议/web框架 Django简介 Django - 路由层(URLconf) Django - 视图层 Django - 模板层 Django - 模型层 - ...

  3. python全栈开发之路

    一.Python基础 python简介 python数据类型(数字\字符串\列表) python数据类型(元组\字典) python数据类型(集合) python占位符%s,%d,%r,%f prin ...

  4. 医院管理者必须知道的医院客户关系管理(CRM)

    客户关系管理(customer relationship management,CRM)是在二战之后首先由美国IBM.道氏.通用等大型企业提出并运用的一种以有效销售为目的的市场营销思想,其理论基础就是 ...

  5. CRM客户关系管理系统(二)

    第三章.前端页面设计  3.1.前端页面布局 Bootstrap模板下载 (1)静态文件 新建statics目录(存放css/fonts/imgs/js/plugins) settings配置 STA ...

  6. CRM系统(第一部分)

      阅读目录 1.需求分析 2.数据库表设计 3.起步 4.录入数据 5.知识点 1.需求分析 CRM客户关系管理软件---> 学员管理 用户:企业内部用户 用户量: 业务场景: 2.数据库表设 ...

  7. 1 CRM需求分析,数据库表,录入数据

    1.需求分析 CRM客户关系管理软件---> 学员管理 用户:企业内部用户 用户量: 业务场景: 2.数据库表设计 1 .表之间的对应关系 from django.db import model ...

  8. Enterprise Solution 3.1 企业应用开发框架 .NET ERP/CRM/MIS 开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    行业:基于数据库的制造行业管理软件,包含ERP.MRP.CRM.MIS.MES等企业管理软件 数据库平台:SQL Server 2005或以上 系统架构:C/S 开发技术 序号 领域 技术 1 数据库 ...

  9. SAP CRM 性能小技巧

    导言 本页面打算收集SAP CRM实施中可以用于避免性能问题的注意事项,重要的事项会由图标标识. 如果你有其他的技巧想要说出来,别犹豫! 性能注意事项 通用 缓存读取类访问,特别是在性能关键的地方,比 ...

随机推荐

  1. Ubuntu16.04搭建各种开发环境的IDE: QT5 , CodeBlocks ,eclipse-cdt, PyCharm

    搭建Ubuntu下C/C++以及Python的集成开发环境,采用双系统(Win7+Ubuntu)的Ubuntu16.04-LTS系统, 关于双系统的搭建可以参考下面博客(图文十分详细):https:/ ...

  2. selenium滑动验证码操作

    1.首先要找到你要滑动的地方 2.调动鼠标事件按住不动 3.调整坐标即可 我这里是为了调试加了很多的sleep,print(hander)是为了看是否定位到了元素 4.效果如下图,但是我这里的验证文字 ...

  3. .net core UseHttpsRedirection() 正式环境无效

    莫名其妙遇到这样的问题.这样的配置在本地可以,正式环境就不行了. ··· public void Configure(IApplicationBuilder app, Microsoft.AspNet ...

  4. django基础知识之Response对象

    HttpResponse对象 在django.http模块中定义了HttpResponse对象的API HttpRequest对象由Django自动创建,HttpResponse对象由程序员创建 不调 ...

  5. js 获取 屏幕 可用高度...

    document.documentElement.clientWidth 此方法适用于手机... document.documentElement.clientHeight (浏览器(手机或电脑)可用 ...

  6. Windows7下采用cygwin编译安装swoole扩展

    常用命令 查看cygwin当前的版本: cygcheck -c cygwin 检查所有安装软件的版本号:cygcheck -c 查看某一个软件安装的版本:cygcheck -c 软件名称 查看本地已经 ...

  7. POJ_1019 Number Sequence 【递推】

    题目: A single positive integer i is given. Write a program to find the digit located in the position ...

  8. POJ - 1961 最小循环节

    如果循环节存在那在前缀部分也肯定存在 如果循环节存在那至少是可以匹配的 而next是维护最大前缀的,意会意会 注意一定要先判整除,即使别的题目保证是存在循环的 特意画了一张灵魂草图帮助理解 #incl ...

  9. SiteServer CMS简介

    SiteServer CMS 是中国在.NET平台下.强大的企业站开源CMS内容管理系统和网站群系统. 能够最低的成本.最少的人力投入在最短的时间内架设好一个功能齐全.性能优异.规模庞大并易于维护的网 ...

  10. 微信小程序实现图片上传功能

    前端: 微信开发者工具 后端:.Net 服务器:阿里云 这里介绍微信小程序如何实现上传图片到自己的服务器上 前端代码 data: { productInfo: {} }, //添加Banner bin ...