Python之路,Day18 - Django适当进阶篇

本节内容

学员管理系统练习

Django ORM操作进阶

用户认证

Django练习小项目:学员管理系统设计开发

带着项目需求学习是最有趣和效率最高的,今天就来基于下面的需求来继续学习Django

项目需求:

1.分讲师\学员\课程顾问角色,2.学员可以属于多个班级,学员成绩按课程分别统计3.每个班级至少包含一个或多个讲师4.一个学员要有状态转化的过程 ,比如未报名前,报名后,毕业老学员5.客户要有咨询纪录, 后续的定期跟踪纪录也要保存6.每个学员的所有上课出勤情况\学习成绩都要保存7.学校可以有分校区,默认每个校区的员工只能查看和管理自己校区的学员8.客户咨询要区分来源

#_*_coding:utf-8_*_
from django.db import models# Create your models here.
from django.core.exceptions import ValidationErrorfrom django.db import models
from django.contrib.auth.models import Userclass_type_choices= (('online',u'网络班'),('offline_weekend',u'面授班(周末)',),('offline_fulltime',u'面授班(脱产)',),)
class UserProfile(models.Model):user = models.OneToOneField(User)name = models.CharField(u"姓名",max_length=32)def __unicode__(self):return self.nameclass School(models.Model):name = models.CharField(u"校区名称",max_length=64,unique=True)addr = models.CharField(u"地址",max_length=128)staffs = models.ManyToManyField('UserProfile',blank=True)def __unicode__(self):return self.nameclass Course(models.Model):name = models.CharField(u"课程名称",max_length=128,unique=True)price = models.IntegerField(u"面授价格")online_price = models.IntegerField(u"网络班价格")brief = models.TextField(u"课程简介")def __unicode__(self):return self.nameclass ClassList(models.Model):course = models.ForeignKey('Course')course_type = models.CharField(u"课程类型",choices=class_type_choices,max_length=32)semester = models.IntegerField(u"学期")start_date = models.DateField(u"开班日期")graduate_date = models.DateField(u"结业日期",blank=True,null=True)teachers = models.ManyToManyField(UserProfile,verbose_name=u"讲师")#def __unicode__(self):#    return "%s(%s)" %(self.course.name,self.course_type)class Meta:verbose_name = u'班级列表'verbose_name_plural = u"班级列表"unique_together = ("course","course_type","semester")class Customer(models.Model):qq = models.CharField(u"QQ号",max_length=64,unique=True)name = models.CharField(u"姓名",max_length=32,blank=True,null=True)phone = models.BigIntegerField(u'手机号',blank=True,null=True)stu_id = models.CharField(u"学号",blank=True,null=True,max_length=64)#id = models.CharField(u"身份证号",blank=True,null=True,max_length=128)source_type = (('qq',u"qq群"),('referral',u"内部转介绍"),('51cto',u"51cto"),('agent',u"招生代理"),('others',u"其它"),)source = models.CharField(u'客户来源',max_length=64, choices=source_type,default='qq')referral_from = models.ForeignKey('self',verbose_name=u"转介绍自学员",help_text=u"若此客户是转介绍自内部学员,请在此处选择内部学员姓名",blank=True,null=True,related_name="internal_referral")course = models.ForeignKey(Course,verbose_name=u"咨询课程")class_type = models.CharField(u"班级类型",max_length=64,choices=class_type_choices)customer_note = models.TextField(u"客户咨询内容详情",help_text=u"客户咨询的大概情况,客户个人信息备注等...")status_choices = (('signed',u"已报名"),('unregistered',u"未报名"),('graduated',u"已毕业"),)status = models.CharField(u"状态",choices=status_choices,max_length=64,default=u"unregistered",help_text=u"选择客户此时的状态")consultant = models.ForeignKey(UserProfile,verbose_name=u"课程顾问")date = models.DateField(u"咨询日期",auto_now_add=True)class_list = models.ManyToManyField('ClassList',verbose_name=u"已报班级",blank=True)def __unicode__(self):return "%s,%s" %(self.qq,self.name )class ConsultRecord(models.Model):customer = models.ForeignKey(Customer,verbose_name=u"所咨询客户")note = models.TextField(u"跟进内容...")status_choices = ((1,u"近期无报名计划"),(2,u"2个月内报名"),(3,u"1个月内报名"),(4,u"2周内报名"),(5,u"1周内报名"),(6,u"2天内报名"),(7,u"已报名"),)status = models.IntegerField(u"状态",choices=status_choices,help_text=u"选择客户此时的状态")consultant = models.ForeignKey(UserProfile,verbose_name=u"跟踪人")date = models.DateField(u"跟进日期",auto_now_add=True)def __unicode__(self):return u"%s, %s" %(self.customer,self.status)class Meta:verbose_name = u'客户咨询跟进记录'verbose_name_plural = u"客户咨询跟进记录"class CourseRecord(models.Model):course = models.ForeignKey(ClassList,verbose_name=u"班级(课程)")day_num = models.IntegerField(u"节次",help_text=u"此处填写第几节课或第几天课程...,必须为数字")date = models.DateField(auto_now_add=True,verbose_name=u"上课日期")teacher = models.ForeignKey(UserProfile,verbose_name=u"讲师")def __unicode__(self):return u"%s 第%s天" %(self.course,self.day_num)class Meta:verbose_name = u'上课纪录'verbose_name_plural = u"上课纪录"unique_together = ('course','day_num')class StudyRecord(models.Model):course_record = models.ForeignKey(CourseRecord, verbose_name=u"第几天课程")student = models.ForeignKey(Customer,verbose_name=u"学员")record_choices = (('checked', u"已签到"),('late',u"迟到"),('noshow',u"缺勤"),('leave_early',u"早退"),)record = models.CharField(u"上课纪录",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(u"本节成绩",choices=score_choices,default=-1)date = models.DateTimeField(auto_now_add=True)note = models.CharField(u"备注",max_length=255,blank=True,null=True)def __unicode__(self):return u"%s,学员:%s,纪录:%s, 成绩:%s" %(self.course_record,self.student.name,self.record,self.get_score_display())class Meta:verbose_name = u'学员学习纪录'verbose_name_plural = u"学员学习纪录"unique_together = ('course_record','student')学员管理系统表结构

学员管理系统表结构

常用ORM操作

from django.db import modelsclass Blog(models.Model):name = models.CharField(max_length=100)tagline = models.TextField()def __str__(self):              # __unicode__ on Python 2return self.nameclass Author(models.Model):name = models.CharField(max_length=50)email = models.EmailField()def __str__(self):              # __unicode__ on Python 2return self.nameclass Entry(models.Model):blog = models.ForeignKey(Blog)headline = models.CharField(max_length=255)body_text = models.TextField()pub_date = models.DateField()mod_date = models.DateField()authors = models.ManyToManyField(Author)n_comments = models.IntegerField()n_pingbacks = models.IntegerField()rating = models.IntegerField()def __str__(self):              # __unicode__ on Python 2return self.headline示例models

示例models

创建

>>> from blog.models import Blog
>>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
>>> b.save()

This performs an INSERT SQL statement behind the scenes. Django doesn’t hit the database until you explicitly call save().

The save() method has no return value.

处理带外键关联或多对多关联的对象

ForeignKey的关联

>>> from blog.models import Entry
>>> entry = Entry.objects.get(pk=1)
>>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
>>> entry.blog = cheese_blog
>>> entry.save()

ManyToManyField关联 

>>> from blog.models import Author
>>> joe = Author.objects.create(name="Joe")
>>> entry.authors.add(joe)

添加多个ManyToMany对象

>>> john = Author.objects.create(name="John")
>>> paul = Author.objects.create(name="Paul")
>>> george = Author.objects.create(name="George")
>>> ringo = Author.objects.create(name="Ringo")
>>> entry.authors.add(john, paul, george, ringo)

查询

all_entries = Entry.objects.all() #查询所有
Entry.objects.filter(pub_date__year=2006) #查询所有pub_date为2006年的纪录
Entry.objects.all().filter(pub_date__year=2006) #与上面那句一样
>>> Entry.objects.filter(   #链式查询
...     headline__startswith='What'
... ).exclude(
...     pub_date__gte=datetime.date.today()
... ).filter(
...     pub_date__gte=datetime(2005, 1, 30)
... )one_entry = Entry.objects.get(pk=1) #单条查询

Entry.objects.all()[:5] #查询前5条
Entry.objects.all()[5:10] #你猜

Entry.objects.order_by('headline')[0] #按headline排序取第一条

Entry.objects.filter(pub_date__lte='2006-01-01') #相当于sql语句SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';

Entry.objects.get(headline__exact="Cat bites dog") #相当于SELECT ... WHERE headline = 'Cat bites dog';
Blog.objects.get(name__iexact="beatles blog") #与上面相同,只是大小写不敏感

Entry.objects.get(headline__contains='Lennon') #相当 于SELECT ... WHERE headline LIKE '%Lennon%';

单表内查询语句

单表内查询语句

#This example retrieves all Entry objects with a Blog whose name is 'Beatles Blog':
Entry.objects.filter(blog__name='Beatles Blog')Blog.objects.filter(entry__headline__contains='Lennon')

关联查询

对同一表内不同的字段进行对比查询,In the examples given so far, we have constructed filters that compare the value of a model field with a constant. But what if you want to compare the value of a model field with another field on the same model?

Django provides F expressions to allow such comparisons. Instances of F() act as a reference to a model field within a query. These references can then be used in query filters to compare the values of two different fields on the same model instance.

For example, to find a list of all blog entries that have had more comments than pingbacks, we construct an F() object to reference the pingback count, and use that F() object in the query:

>>> from django.db.models import F
>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks'))

Django supports the use of addition, subtraction, multiplication, division, modulo, and power arithmetic with F() objects, both with constants and with other F() objects. To find all the blog entries with more than twice as many comments as pingbacks, we modify the query:

>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)

To find all the entries where the rating of the entry is less than the sum of the pingback count and comment count, we would issue the query:

>>> Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks'))

For date and date/time fields, you can add or subtract a timedelta object. The following would return all entries that were modified more than 3 days after they were published:

>>> from datetime import timedelta
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))

Caching and QuerySets

Each QuerySet contains a cache to minimize database access. Understanding how it works will allow you to write the most efficient code.

In a newly created QuerySet, the cache is empty. The first time a QuerySet is evaluated – and, hence, a database query happens – Django saves the query results in the QuerySet’s cache and returns the results that have been explicitly requested (e.g., the next element, if the QuerySet is being iterated over). Subsequent evaluations of the QuerySet reuse the cached results.

Keep this caching behavior in mind, because it may bite you if you don’t use your QuerySets correctly. For example, the following will create two QuerySets, evaluate them, and throw them away:

>>> print([e.headline for e in Entry.objects.all()])
>>> print([e.pub_date for e in Entry.objects.all()])

That means the same database query will be executed twice, effectively doubling your database load. Also, there’s a possibility the two lists may not include the same database records, because an Entry may have been added or deleted in the split second between the two requests.

To avoid this problem, simply save the QuerySet and reuse it:

>>> queryset = Entry.objects.all()
>>> print([p.headline for p in queryset]) # Evaluate the query set.
>>> print([p.pub_date for p in queryset]) # Re-use the cache from the evaluation.

When QuerySets are not cached¶

Querysets do not always cache their results. When evaluating only part of the queryset, the cache is checked, but if it is not populated then the items returned by the subsequent query are not cached. Specifically, this means that limiting the querysetusing an array slice or an index will not populate the cache.

For example, repeatedly getting a certain index in a queryset object will query the database each time:

>>> queryset = Entry.objects.all()
>>> print queryset[5] # Queries the database
>>> print queryset[5] # Queries the database again

However, if the entire queryset has already been evaluated, the cache will be checked instead:

>>> queryset = Entry.objects.all()
>>> [entry for entry in queryset] # Queries the database
>>> print queryset[5] # Uses cache
>>> print queryset[5] # Uses cache

Complex lookups with Q objects(复杂查询)

Keyword argument queries – in filter(), etc. – are “AND”ed together. If you need to execute more complex queries (for example, queries with OR statements), you can use Q objects.

Q object (django.db.models.Q) is an object used to encapsulate a collection of keyword arguments. These keyword arguments are specified as in “Field lookups” above.

For example, this Q object encapsulates a single LIKE query:

from django.db.models import Q
Q(question__startswith='What')

Q objects can be combined using the & and | operators. When an operator is used on two Q objects, it yields a new Q object.

For example, this statement yields a single Q object that represents the “OR” of two "question__startswith" queries:

Q(question__startswith='Who') | Q(question__startswith='What')

This is equivalent to the following SQL WHERE clause:

WHERE question LIKE 'Who%' OR question LIKE 'What%'

You can compose statements of arbitrary complexity by combining Q objects with the & and | operators and use parenthetical grouping. Also, Q objects can be negated using the ~ operator, allowing for combined lookups that combine both a normal query and a negated (NOT) query:

Q(question__startswith='Who') | ~Q(pub_date__year=2005)

Each lookup function that takes keyword-arguments (e.g. filter()exclude()get()) can also be passed one or more Qobjects as positional (not-named) arguments. If you provide multiple Q object arguments to a lookup function, the arguments will be “AND”ed together. For example:

Poll.objects.get(Q(question__startswith='Who'),Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)

... roughly translates into the SQL:

SELECT * from polls WHERE question LIKE 'Who%'AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

Lookup functions can mix the use of Q objects and keyword arguments. All arguments provided to a lookup function (be they keyword arguments or Q objects) are “AND”ed together. However, if a Q object is provided, it must precede the definition of any keyword arguments. For example:

Poll.objects.get(Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),question__startswith='Who')

... would be a valid query, equivalent to the previous example; but:

# INVALID QUERY
Poll.objects.get(question__startswith='Who',Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))

... would not be valid.

更新 

Updating multiple objects at once

# Update all the headlines with pub_date in 2007.
Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')

在原有数据的基础上批量自增

Calls to update can also use F expressions to update one field based on the value of another field in the model. This is especially useful for incrementing counters based upon their current value. For example, to increment the pingback count for every entry in the blog:

>>> Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)

However, unlike F() objects in filter and exclude clauses, you can’t introduce joins when you use F() objects in an update – you can only reference fields local to the model being updated. If you attempt to introduce a join with an F() object, a FieldErrorwill be raised:

# THIS WILL RAISE A FieldError
>>> Entry.objects.update(headline=F('blog__name'))

Aggregation(聚合)

from django.db import modelsclass Author(models.Model):name = models.CharField(max_length=100)age = models.IntegerField()class Publisher(models.Model):name = models.CharField(max_length=300)num_awards = models.IntegerField()class Book(models.Model):name = models.CharField(max_length=300)pages = models.IntegerField()price = models.DecimalField(max_digits=10, decimal_places=2)rating = models.FloatField()authors = models.ManyToManyField(Author)publisher = models.ForeignKey(Publisher)pubdate = models.DateField()class Store(models.Model):name = models.CharField(max_length=300)books = models.ManyToManyField(Book)registered_users = models.PositiveIntegerField()示例models

示例models

# Total number of books.
>>> Book.objects.count()# Total number of books with publisher=BaloneyPress
>>> Book.objects.filter(publisher__name='BaloneyPress').count()# Average price across all books.
>>> from django.db.models import Avg
>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35}# Max price across all books.
>>> from django.db.models import Max
>>> Book.objects.all().aggregate(Max('price'))
{'price__max': Decimal('81.20')}# Cost per page
>>> Book.objects.all().aggregate(
...    price_per_page=Sum(F('price')/F('pages'), output_field=FloatField()))
{'price_per_page': 0.4470664529184653}# All the following queries involve traversing the Book<->Publisher
# foreign key relationship backwards.# Each publisher, each with a count of books as a "num_books" attribute.
>>> from django.db.models import Count
>>> pubs = Publisher.objects.annotate(num_books=Count('book'))
>>> pubs
[<Publisher BaloneyPress>, <Publisher SalamiPress>, ...]
>>> pubs[0].num_books# The top 5 publishers, in order by number of books.
>>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5]
>>> pubs[0].num_books常用聚合场景需求

常用聚合场景需求

更多聚合查询例子:https://docs.djangoproject.com/en/1.9/topics/db/aggregation/

用户认证 

from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:# the password verified for the userif user.is_active:print("User is valid, active and authenticated")else:print("The password is valid, but the account has been disabled!")
else:# the authentication system was unable to verify the username and passwordprint("The username and password were incorrect.")

How to log a user out¶

from django.contrib.auth import logoutdef logout_view(request):logout(request)# Redirect to a success page.

转载于:https://www.cnblogs.com/luolingfeng/p/5552950.html

Python学习路程day18相关推荐

  1. python学习路程1

    常用的转义字符还有: \n 表示换行 \t 表示一个制表符 \\ 表示 \ 字符本身 任务 请将下面两行内容用Python的字符串表示并打印出来: Python was started in 1989 ...

  2. Python学习路程day9

    本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko SS ...

  3. Python学习路程day12

    前端内容学习:HTML和CSS <!DOCTYPE html> <html lang="en"> <head><meta http-equ ...

  4. 小涛python学习路程-(2)编程基本概念

    字符串 不同的字符串所占的字节数不同,所以要计算字符串的长度,就需要了解各字符所占的字节数. python中字符串使用的是unicode字符集,数字.英文.小数点.下划线.空格占1个字节:汉字在GBK ...

  5. Python学习路程day20

    本节内容: 项目:开发一个简单的BBS论坛 需求: 整体参考"抽屉新热榜" + "虎嗅网" 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 ...

  6. Python学习笔记(五.数据分析 ——上)

    系列文章持续更新中- 文章目录 前言 一.相关性分析 A.获取股票价格 a.获取日K线的股票价格 b.获取每分钟的股票价格 B. 合并股票价格 C.股票价格相关性分析 二.假设检验 三.方差分析 A. ...

  7. Python学习:day21正则表达式

    写在前面: 此博客仅用于记录个人学习进度,学识浅薄,若有错误观点欢迎评论区指出.欢迎各位前来交流.(部分材料来源网络,若有侵权,立即删除) 传送门: day01基础知识 day02知识分类 day03 ...

  8. Python学习:day20正则表达式

    写在前面: 此博客仅用于记录个人学习进度,学识浅薄,若有错误观点欢迎评论区指出.欢迎各位前来交流.(部分材料来源网络,若有侵权,立即删除) 传送门: day01基础知识 day02知识分类 day03 ...

  9. pygame是python的一个库吗,python学习pygame,,基本库导入impor

    python学习pygame,,基本库导入impor 基本库导入 import pygame import sys from pygame.locals import * 初始化 pygame.ini ...

最新文章

  1. POJ Mayor's posters——线段树+离散化
  2. windows Redis绑定ip无效,Redis设置密码无效,Windows Redis 配置不生效, Windows Redis requirepass不生效...
  3. 机器学习系列-随机过程
  4. 【自动驾驶】相机标定 疑问总结
  5. javafx隐藏_JavaFX技巧14:StackPane子项-隐藏但不消失
  6. 【链接攻击,差分攻击,去标识化代码实现】差分隐私代码实现系列(二)
  7. Borland Enterprise Core Object II (ECO II)第一次接觸
  8. springmvc与ajax交互常见问题
  9. Kotlin — 适用于数据科学
  10. 机器换人是走向智能制造的必然过程,那么机器人的价值主要体现在哪些方面?
  11. C语言实现客房管理系统
  12. 一號倉:《漫》--《3D》
  13. 2021年二级c语言软件下载,2021计算机二级宝典
  14. 中企海外周报 | 华为在西班牙启动Wi-Fi 6高校创新应用测试试点;爱奇艺人脸识别技术获全球学术会议认可...
  15. 大数据计算的四支精干队伍,你造吗
  16. Mac系统下Carina初体验
  17. 康奈尔大学的计算机专业怎么样,美国名校康奈尔大学计算机专业介绍
  18. python实现简单的ps色阶调整过程
  19. tomcat从零开始配置https
  20. 转:微信米聊遇阻 移动飞聊免流量费搅局

热门文章

  1. php bootstraptable分页,php+bootstrap+dataTable+jquery分页列表
  2. 女生学计算机教学,女生学计算机专业好吗 计算机辅助数学教学之我见
  3. 昆明二级计算机考试报名时间2015,4月15日开始网上报名!云南省2021年上半年中小学教师资格考试(面试)安排来了——昆明广播电视台...
  4. 侧边栏配置_vscode入门:熟悉vscode和初级配置
  5. Java多线程闲聊(六):synchronized关键字
  6. Finding Similar Items 文本相似度计算的算法——机器学习、词向量空间cosine、NLTK、diff、Levenshtein距离...
  7. ES doc_values介绍2——本质是field value的列存储,做聚合分析用,ES默认开启,会占用存储空间...
  8. SQL UNION 操作符
  9. 在Qt(C++)中使用QThread实现多线程
  10. 欠采样(undersampling)和过采样(oversampling)会对模型带来怎样的影响