django学习笔记
django
一、model
model层是与数据库相关联的层,每一个类映射到一个数据表
对于model有一些注意点:
1、主键
如果不设置 primary_key=True
对所有的类属性, 将自动增加一个整数递增来作为主键 (如果对原来的表修改主键,新表和旧表会同时存在吗)
2、choices
choices是一个元组,第一个参数会存储到数据库,第二个参数我觉着就是对第一个参数的具体描述
3、对应关系
1、ForeignKey
from django.db import models class Manufacturer(models.Model): # ... pass class Car(models.Model): manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE) # models.CASCADE表示如果主表记录删除,则关联表相关记录也应该删除
class Person(models.Model): SHIRT_SIZES = ( ('S', 'Small'), ('M', 'Medium'), ('L', 'Large'), ) name = models.CharField(max_length=60) shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES) >>> p = Person(name="Fred Flintstone", shirt_size="L") >>> p.save() >>> p.shirt_size 'L' >>> p.get_shirt_size_display() 'Large'
4、class Meta(object)
给model定义元数据,比如排序
ordering = ['-order_date'] 表示降序 ordering = ['order_date'] 表示升序
5、 annotate 参考博客
annotate主要用来统计在某个相关联表下的数量
Post 表: id title body category_id 1 post 1 ... 1 2 post 2 ... 1 3 post 3 ... 1 4 post 4 ... 2 Category 表: name id category 1 1 category 2 2 blog/templatetags/blog_tags.py from django.db.models.aggregates import Count from blog.models import Category @register.simple_tag def get_categories(): # 记得在顶部引入 count 函数 # Count 计算分类下的文章数,其接受的参数为需要计数的模型的名称 return Category.objects.annotate(num_posts=Count('post')).filter(num_posts__gt=0)
这个Category.objects.annotate
方法和Category.objects.all
有点类似,它会返回数据库中全部 Category 的记录,但同时它还会做一些额外的事情,
在这里我们希望它做的额外事情就是去统计返回的 Category 记录的集合中每条记录下的文章数。代码中的Count
方法为我们做了这个事,它接收一个和 Categoty
相关联的模型参数名(这里是Post
,通过 ForeignKey 关联的),然后它便会统计 Category 记录的集合中每条记录下的与之关联的 Post 记录的行数,也就是文章数
,最后把这个值保存到num_posts
属性中。
django操作数据库
进入到shell,利用model进行操作
mysql> describe user_app_topic -> ; +------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | text | varchar(20) | NO | | NULL | | | date_added | datetime(6) | NO | | NULL | | +------------+-------------+------+-----+---------+----------------+ 3 rows in set (0.02 sec) mysql> describe user_app_entry -> ; +------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | text | longtext | NO | | NULL | | | date_added | datetime(6) | NO | | NULL | | | topic_id | int(11) | NO | MUL | NULL | | +------------+-------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec)
>>> from user_app.models import Topic, Entry >>> topic = Topic(text="Chess") >>> topic.save() >>> topic = Topic(text="Climbing") >>> topic.save() >>> Topic.objects.all() [<Topic: Chess>, <Topic: Climbing>] >>> entry = Entry(topic_id = 1,text="The opening is the first part of the game, roughly the first ten moves or so.") >>> entry.save() >>> t = Topic.objects.get(id=1) >>> t.text u'Chess'
4、select_related 和 prefetch_related
select_related主要在查询外键使用,在select_related()里面加入指定的外键可以将关联的对象也一并查询出来,与普通相比减少了查询次数,select_related主要用于一对一,一对多(foreignkey),它的实现原理就是与关联表进行 inner join 具体讲解
prefetch_related主要用于多对多关系的查询,他不能使用join 进行连接,因为多对多的关系使用join进行连接会使得生成的表非常长,效率不高。他是先查询一个表,在根据python处理他们之间的关系 具体讲解
5、related_name
related_name是关联对象反向引用
class Apple( models.Model): origin_level = models.ForeignKey(AppleLevel, related_name='orgin_level_appleset') new_level = models.ForeignKey(AppleLevel, related_name='new_level_appleset') 通过origin_level引用AppleLevel 中id为12的Apple的所有对象 AppleLevel.object.get(id=12).origin_level_appleset.objects.all()
Form
ModelForm https://www.jianshu.com/p/3d04309445e4
1、
二、view
1、django.shortcuts
render
(request, template_name, context=None, content_type=None, status=None, using=None)
2、class-base-views 基于类的通用视图
https://www.jianshu.com/p/00bf223873b3
Mixin
Django把基本的http请求和响应抽象出来, 封装成各自的类, 在使用过程中只需把各个基类聚合到一起使用, 并按照自己的要求重写自己需要的方法就可以了, 那么就把这些基类叫Mixin吧. 在Django中比较基础的Mixin主要有几类:
-
View(视图基础类)
-
SingleObjectMixin(单对象类)
-
MultipleObjectMixin(多对象类)
-
TemplateResponseMixin(模板响应类)
-
FormMixin(表单类)
-
YearMixin, MonthMixin, DayMixin, WeekMixin, DateMixin(几个基于时间关系的类)
TemplateView
TemplateView继承 View, ContextMixin, TemplateResponseMinxin
View类提供as_view()方法,在这个方法中要做的事情就是dispatch
ContextMixin类只实现了一个方法 get_context_data
TemplateResponseMixin 在render_to_response()方法中返回一个TemplateResponse对象,template用的就是类属性template_name指定的
from django.views.generic import TemplateView class AboutView(TemplateView): template_name = "about.html"
FormMixin
提供 form_class 指定form表单,
方法中有: form_valid(self, forml) 判断form是否有效,若有效转向 get_success_url
ListView: 获取一系列的model然后将其封装到context中
在ListView中有两个主要的函数 get_queryset() 和 get_context_data(),
get_queryset()主要就是取查询model, 类似于article_list = Article.objects.all(), 如果只是单纯的查询就不需要重写, 直接指名一个查询的model即可(model = Article); get_context_data 就是把查询到的内容添加到context中, kwargs应该指的就是context,如果还需要再添加内容就要重写该方法,如下代码所示。
return super(IndexView, self).get_context_data(**kwargs) 语句的作用是添加了 category_list 到上下文中,还要把默认的一些上下文变量也返回给视图函数,以便其后续处理
class IndexView(ListView): template_name = "blog/index.html" #需要渲染的模板文件 context_object_name = "article_list" #get_queryset返回的list,如果不指定名字,默认位object_list def get_queryset(self): article_list = Article.objects.all() for article in article_list: article.body = markdown2.markdown(article.body, extras=['fenced-code-blocks'], ) return article_list def get_context_data(self, **kwargs): kwargs['category_list'] = Category.objects.all().order_by('name') return super(IndexView, self).get_context_data(**kwargs)
DetailView
detailview依赖于SingleObjectMinxin,
get_object方法它根据请求的URL来确定对象
get_object 方法默认情况下获取 id 为pk_url_kwarg 的对象
class ArticleDetailView(DetailView): model = Article template_name = "blog/detail.html" context_object_name = "article" pk_url_kwarg = 'article_id' #根据什么来去 def get_object(self, queryset=None): obj = super(ArticleDetailView, self).get_object() obj.body = markdown2.markdown(obj.body, extras=['fenced-code-blocks'], ) return obj
form
Templates
1、模板里面可以使用四则运算
{{ num|add:1}} 表示加一操作
2、可以自定义filters来对templates里面的数据进行处理,具体操作过程:
1、在 应用目录(app)下 创建templatetags文件夹,在templatetags文件夹下创建app_filters.py
2、app_filters.py
from django import template register = template.Library() @register.filter(name='get_due_date_string') def get_due_date_string(value): delta = value - date.today() if delta.days == 0: return "Today!" elif delta.days < 1: return "%s %s ago!" % (abs(delta.days), ("day" if abs(delta.days) == 1 else "days")) elif delta.days == 1: return "Tomorrow" elif delta.days > 1: return "In %s days" % delta.days
3、在templates里面加入注释,如果是单行注释 {# #},如果是多行注释 {% comment %} {% endcomment %}
4、 如果使用赋值语句需要在 {with } {with}里面