54、choice参数、创建多对多的三种方式、Ajax神器、前后端编码格式

136 阅读7分钟

choices参数

1.用处:当表字段的数据可能被列举完的时候,我们如何存储数据?
  我们一般使用choices参数来存储这样的数据
  

案例

创建表--models.py

class User(models.Model):
    username = models.CharField(max_length=64)
    gender_choice= ((1,'male'),
                    (2,'female'),
                    (3,'other'))
    score_choices = (('A','优先'),
                     ('B','良好'),
                     ('C','及格'),
                     ('D','不及格'))
    gender = models.IntegerField(choices=gender_choice)
    score = models.CharField(max_length=64,choices=score_choices)
    
    ps:IntegerField参数如何选:(1, '男'),的第一个参数是什么类型就选择对应的数据类型

添加数据--tests.py

models.User.objects.create(username = 'nana',gender = 1,score = 'A')
models.User.objects.create(username='xiao', gender=2, score='A')
models.User.objects.create(username='jason', gender=3, score='B')  # 数据照样添加进去
models.User.objects.create(username='tank', gender=4, score='C')  # 数据照样添加进去
models.User.objects.create(username='jack', gender=5, score='E')  # 数据照样添加进去

读取数据--tests.py

# 从数据库中读取原始数据,得到的是整型,然后做判断
if res.gender == 1:
		gender = '男'
elif res.gender == 2:
		gender = '女'
# 读取数据 get_字段名_display()  
res = models.User.objects.filter(pk=4).first()
print(res)  # User object
print(res.username,res.gender,res.score)  # jason 3 B  数据正常读出
print(res.username,res.get_gender_display(),res.get_score_display())  # jason other 良好

ps:user_obj.get_字段_display()  ------>如果查出来的数字在范围中,就会映射对应的关系,如果超出了范围,就原样输出

例子

# 实际项目案例
# CRM相关内部表
class School(models.Model):
    """
    校区表
    如:
        北京沙河校区
        上海校区
    """
    title = models.CharField(verbose_name='校区名称', max_length=32)

    def __str__(self):
        return self.title

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 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)
    email = models.EmailField(verbose_name='邮箱', max_length=64)
    depart = models.ForeignKey(verbose_name='部门', to="Department",to_field="code")
    user=models.OneToOneField("User",default=1)
    def __str__(self):
        return self.name

class ClassList(models.Model):
    """
    班级表
    如:
        Python全栈  面授班  5期  10000  2017-11-11  2018-5-11
    """
    school = models.ForeignKey(verbose_name='校区', to='School')
    course = models.ForeignKey(verbose_name='课程名称', to='Course')
    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':1002})
    tutor = models.ForeignKey(verbose_name='班主任', to='UserInfo',related_name="class_list",limit_choices_to={'depart':1006})
    
    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"
    )
    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':1001})

    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 self.name

class ConsultRecord(models.Model):
    """
    客户跟进记录
    """
    customer = models.ForeignKey(verbose_name="所咨询客户", to='Customer')
    consultant = models.ForeignKey(verbose_name="跟踪人", to='UserInfo',limit_choices_to={'depart':1001})
    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')
    class_list = models.ManyToManyField(verbose_name="已报班级", to='ClassList', blank=True)

    emergency_contract = models.CharField(max_length=32, blank=True, null=True, verbose_name='紧急联系人')
    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.customer.name

class ClassStudyRecord(models.Model):
    """
    上课记录表 (班级记录)
    """
    class_obj = models.ForeignKey(verbose_name="班级", to="ClassList")
    day_num = models.IntegerField(verbose_name="节次", help_text=u"此处填写第几节课或第几天课程...,必须为数字")
    teacher = models.ForeignKey(verbose_name="讲师", to='UserInfo',limit_choices_to={'depart':1002})
    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 StudentStudyRecord(models.Model):
    '''
    学生学习记录
    '''
    classstudyrecord = models.ForeignKey(verbose_name="第几天课程", to="ClassStudyRecord")
    student = models.ForeignKey(verbose_name="学员", to='Student')
    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.classstudyrecord, self.student)
         

MVC与MTV模型

1.MVC
	1.Web服务器开发领域里著名的MVC模式
  2.MVC
    M:model(模型层:跟数据库打交道的)
    V:views(模板层:处理html文件相关)
    C:controller(控制器:接收请求,处理请求)
2.MTV
	1.Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系
  2.Django的MTV分别是值
    ● M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。
    ● T 代表模板 (Template):负责如何把页面展示给用户(html)。
    ● V 代表视图(View): 负责业务逻辑,并在适当时候调用Model和Template。

3.其实还有一层:services层
  S:services层------>服务层---------->一般用在项目比较大的时候才会抽象这一层

MVC

MVC.png

MTV

MTV.png

多对多关系的三种创建

1.全自动的

特点就是扩展性太差,可以正反向查询,还可以使用那4个方法,add set remove clear

class Book(models.Model):
    title = models.CharField(max_length=32)
    authors = models.ManyToManyField(to='Author')
       
class Author(models.Model):
    name = models.CharField(max_length=32)

2.纯手动的

我们自己创建第三张表,极大的好处:扩展性高了

class Book(models.Model):
    title = models.CharField(max_length=32)

class Author(models.Model):
    name = models.CharField(max_length=32)

class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
    bind_time = models.DateTimeField(auto_now_add=True)

3.半自动化

注意:
    1. 还是需要一个虚拟字段authors----->models.ManyToManyField
    2. through:指定第三张表的表名
    3. through_fields:指定第三张表里面哪两个字段是关系字段
    4. through_fields=('author', 'book')里面的两个字段是有顺序要求的
    5. 这种方式是可以支持正反向查询的,但是不能使用那4个方法了,add remove set clear
class Book(models.Model):
    title = models.CharField(max_length=32)
    authors = models.ManyToManyField(to='Author',
                                     through='Book2Author',
                                     through_fields=('book','author'))
class Author(models.Model):
    name = models.CharField(max_length=32)

class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
    bind_time = models.DateTimeField(auto_now_add=True)
class Book(models.Model):
    title = models.CharField(max_length=32)
    # authors = models.ManyToManyField(to='Author',
    #                                  through='Book2Author',
    #                                  through_fields=('book','author'))
class Author(models.Model):
    name = models.CharField(max_length=32)
    authors=models.ManyToManyField(to='Book',
                                   through='Book2Author',
                                   through_fields=('author','book'))

class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
    bind_time = models.DateTimeField(auto_now_add=True)

Ajax技术

1.什么事Ajax?
	AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。
  ● 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
  ● 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
  
2.Ajax的特点:
	异步传输------>指的是数据的传输方式是异步的
  局部刷新------>浏览器页面局部刷新的
  例子:github的注册功能,实时验证邮箱的合法性,每次输完邮箱,就朝后盾发起一次请求
  
3.ajax技术是属于前端的技术,并且它不是一个新的技术栈,它是有其他的技术栈演变过来的(python的装饰器)

ps:1.ajax 的学习我们只学习jQuery封装之后的,原生的ajax我们不学,过于复杂了,对于专业前端,肯定要学;
   2.想使用ajax技术,必须确保引入jQuery文件(能发起ajax请求的不但只是jQuery可以,其他的也可以,axios,vue)

4.参数:
  1.url:'', //指定请求的地址,如果不写,朝当前地址提交
  2.type:'post', //指定请求方式,默认不写是get请求
  3.data:{k:v,k:v},
  4.dataType:'json',  // ajax固定你返回的就是i对象的形式,反序列化之后的结果
  
5.ajax的书写结构
$.ajax({
    url:'',
    type:'post',
    data:{'a':1, 'b':1, c:2},
    dataType:'json'
    # 当后端成功返回数据的时候,回调的函数
    success:function(res) {
        # res--------->后盾返回的数据
    }
})

6.总结
  1.当后端用HttpResponse返回的时候,前端应该
    1. 反序列化:JSON.parse(res)
    2. 指定一个参数:dataType:'json'
  2. 后端直接用JsonResponse,前端什么都不用做,直接取值

案例

通过Ajax,实现前端输入两个数字,服务器做加法,返回到前端页面

<body>
<input type="text"  id='d1'>
+
<input type="text" id ='d2' >
=
<input type="text" id ='d3'>
<input type="submit" id = 'btn'>

<script>
    $('#btn').click(function (){
        //1.获取数据
        var d1 = $('#d1').val()
        var d2 = $('#d2').val()

        //2.启动ajax
        $.ajax({
            url:'', //指定请求的地址,如果不写,朝当前地址提交
            type:'post', //指定请求方式,默认不写是get请求
            data:{'a':d1,'b':d2},
            //接收django后端返回过来的数据
            success:function (res){
                console.log(res,typeof(res))  // 4 string
                //设置值
                $('#d3').val(res)

            }
        })
    })
</script>
</body>
def ab_ajax(request):
    # 判断是ajax请求
    if request.is_ajax():
        # ajax接收数据
        print(request.POST)  # <QueryDict: {'a': ['1'], 'b': ['2']}>
        a = request.POST.get('a')
        b= request.POST.get('b')
        res = int(a)+int(b)
        return HttpResponse(res)
    return render(request,'ab_ajax.html')