1、中介模型:多对多添加的时候用到中介模型html
本身建立的第三张表就属因而中介模型
class Article(models.Model): ''' 文章表 ''' title = models.CharField(max_length=64,verbose_name="文章标题") summary = models.CharField(max_length=244, verbose_name="文章概要") create_time = models.DateTimeField(verbose_name="建立时间",auto_now_add=True) update_time = models.DateTimeField(verbose_name="修改时间",auto_now=True) up_count = models.IntegerField(verbose_name="点赞数",default=0) down_count = models.IntegerField(verbose_name="点灭数",default=0) comment_count = models.IntegerField(verbose_name="评论数",default=0) read_count = models.IntegerField(verbose_name="阅读数",default=0) user = models.ForeignKey(to="UserInfo",verbose_name="所属做者",null=True,blank=True) classify = models.ForeignKey(to="Classfication",verbose_name="所属类别",null=True,blank=True) tags = models.ManyToManyField(to="Tag",through="Article2tag",through_fields=('article', 'tag'),verbose_name="所属标签") site_article_category = models.ForeignKey(to="SiteArticleCategory",verbose_name="所属文章分类",null=True,blank=True) class Meta: verbose_name_plural = "文章表" def __str__(self): return self.title class Tag(models.Model): '''标签表''' name = models.CharField(max_length=32,verbose_name="标签名") blog = models.ForeignKey(to="Blog",verbose_name="所属博客") class Meta: verbose_name_plural = "标签表" def __str__(self): return self.name class Article2tag(models.Model): article = models.ForeignKey(verbose_name="文章",to="Article") tag = models.ForeignKey(verbose_name="标签",to="Tag") class Meta: verbose_name="文章和标签关系表" '''联合惟一''' unique_together = [ ("article","tag") ] def __str__(self): return self.article.title + " "+self.tag.name
像是这样本身建立的第三张表就属因而中介模型。通常就Django会给咱们自动建立第三张表,
人家本身建立的只是有关系字段,不能在增长其余的字段了,
若是根据需求添加其余字段,不须要ManytoMany本身建立第三张表就本身设置第三张表
这就须要咱们本身去建立第三张表。
固然我如今设计的Article2tag这个第三张表就能够在里面添加其余你须要的字段。
若是用了中介模型了,就不能在用add,remove了ajax
为何不能这样作? 这是由于你不能只建立 article和 tag之间的关联关系,你还要指定 Membership模型中所须要的全部信息;而简单的add、create 和赋值语句是作不到这一点的。因此它们不能在使用中介模型的多对多关系中使用。此时,惟一的办法就是建立中介模型的实例。sql
remove()方法被禁用也是出于一样的缘由。可是clear() 方法倒是可用的。它能够清空某个实例全部的多对多关系:数据库
cate = request.POST.get("cate")
tag = request.POST.getlist("tag")
article_obj = models.Article.objects.create(title=title,summary=content[0:30],create_time=datetime.datetime.now(),user=request.user,classify_id = cate) models.Article_detail.objects.create(content=content,article=article_obj) if tag: for i in tag: #[2,4] models.Article2tag.objects.create(tag_id=i,article_id=article_obj.id) #直接从关系表里面去查
remove()方法被禁用也是出于一样的缘由。可是clear() 方法倒是可用的。它能够清空某个实例全部的多对多关系:django
2、优化查询缓存
简单使用
对于一对一字段(OneToOneField)和外键字段(ForeignKey),可使用select_related 来对QuerySet进行优化。函数
select_related 返回一个QuerySet,当执行它的查询时它沿着外键关系查询关联的对象的数据。它会生成一个复杂的查询并引发性能的损耗,可是在之后使用外键关系时将不须要数据库查询。post
简单说,在对QuerySet使用select_related()函数后,Django会获取相应外键对应的对象,从而在以后须要的时候没必要再查询数据库了。性能
下面的例子解释了普通查询和select_related() 查询的区别。测试
查询id=2的文章的分类名称,下面是一个标准的查询:
obj = models.Article.objects.get(id=2)
print(obj.classify.title) #走两次数据库,基于对象的属于子查询,基于双下划线的属于连表查询
sql是这样的
''' SELECT "blog_article"."nid", "blog_article"."title", "blog_article"."desc", "blog_article"."read_count", "blog_article"."comment_count", "blog_article"."up_count", "blog_article"."down_count", "blog_article"."category_id", "blog_article"."create_time", "blog_article"."blog_id", "blog_article"."article_type_id" FROM "blog_article" WHERE "blog_article"."nid" = 2; args=(2,) SELECT "blog_category"."nid", "blog_category"."title", "blog_category"."blog_id" FROM "blog_category" WHERE "blog_category"."nid" = 4; args=(4,) '''
若是咱们使用select_related()函数:
articleList=models.Article.objects.select_related("category").all() for article_obj in articleList: # Doesn't hit the database, because article_obj.category # has been prepopulated in the previous query. print(article_obj.category.title)
#查询全部书的分类标题
obj_list=models.Article.objects.select_related("user").select_related("classify").all()
for obj in obj_list:
print(obj,"2222222",type(obj))
print(obj.classify.title)
# obj_list = models.Article.objects.select_related("user","classify").all()
# for obj in obj_list:
# print(obj.classify.title)
# 要看需求查的数据多很少,若是一次的话就没有必要了
SELECT "blog_article"."nid", "blog_article"."title", "blog_article"."desc", "blog_article"."read_count", "blog_article"."comment_count", "blog_article"."up_count", "blog_article"."down_count", "blog_article"."category_id", "blog_article"."create_time", "blog_article"."blog_id", "blog_article"."article_type_id", "blog_category"."nid", "blog_category"."title", "blog_category"."blog_id" FROM "blog_article" LEFT OUTER JOIN "blog_category" ON ("blog_article"."category_id" = "blog_category"."nid");
总结
- select_related主要针一对一和多对一关系进行优化。
- select_related使用SQL的JOIN语句进行优化,经过减小SQL查询的次数来进行优化、提升性能。
- 能够经过可变长参数指定须要select_related的字段名。也能够经过使用双下划线“__”链接字段名来实现指定的递归查询。
- 没有指定的字段不会缓存,没有指定的深度不会缓存,若是要访问的话Django会再次进行SQL查询。
- 也能够经过depth参数指定递归的深度,Django会自动缓存指定深度内全部的字段。若是要访问指定深度外的字段,Django会再次进行SQL查询。
- 也接受无参数的调用,Django会尽量深的递归查询全部的字段。但注意有Django递归的限制和性能的浪费。
- Django >= 1.7,链式调用的select_related至关于使用可变长参数。Django < 1.7,链式调用会致使前边的select_related失效,只保留最后一个。
3、CBV模式
就是把以前的函数视图用类实现了
简单测试一下:
urls.py
#CBV模式 url(r'^login_cbv/$', views.Login_cbv.as_view()),
注意:这里的Login_cbv是类名,它必须后面调用as_view()
views.py
from django.views import View class Login_cbv(View): def get(self,request): #若是是get请求须要执行的代码 return render(request,"login_cbv.html") def post(self,request): #若是是post请求须要执行的代码 return HttpResponse(".....") def delete(self,request): pass
login_cbv.html
<form action="/login_cbv/" method="post"> {% csrf_token %} 姓名:<input type="text"> <input type="submit"> </form>
对于form表单只支持post和get请求,对于ajax请求支持8种,
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
4、总体插入
建立对象时,尽量使用bulk_create()来减小SQL查询的数量。例如:
Entry.objects.bulk_create([ Entry(headline="Python 3.0 Released"), Entry(headline="Python 3.1 Planned") ])
...更优于:
Entry.objects.create(headline="Python 3.0 Released") Entry.objects.create(headline="Python 3.1 Planned")
注意该方法有不少注意事项,因此确保它适用于你的状况。
这也能够用在ManyToManyFields中,因此:
my_band.members.add(me, my_friend)
...更优于:
my_band.members.add(me) my_band.members.add(my_friend)
...其中Bands和Artists具备多对多关联。