Thewebframeworkforperfectionistswithdeadlines.
Django自带了一个可选的“站点”框架。它是一个钩子,用于将对象和功能关联到特定的网站上,它是你的Django驱动的网站的域名和“啰嗦”名称的保存地。
如果你的单个Django安装支持多个站点,并且你需要以某种方式区分这些站点,那么就使用它。
站点框架主要基于这个模型:
储存网站domain和name属性的模型。
一个人类可读的“啰嗦”的网站名称。
如何使用这个功能由你决定,但Django通过几个约定自动使用它。
为什么要用站点?通过例子来解释是最好的。
解决这个问题的天真方法是要求网站制作者将同一篇报道发布两次:一次发布在LJWorld.com,另一次发布在Lawrence.com。但这对网站制作者来说效率很低,而且在数据库中存储同一故事的多个副本是多余的。
fromdjango.contrib.sites.modelsimportSitefromdjango.dbimportmodelsclassArticle(models.Model):headline=models.CharField(max_length=200)#...sites=models.ManyToManyField(Site)这就很好地完成了几件事:
fromdjango.contrib.sites.modelsimportSitefromdjango.dbimportmodelsclassArticle(models.Model):headline=models.CharField(max_length=200)#...site=models.ForeignKey(Site,on_delete=models.CASCADE)这与上一节所述的好处相同。
你可以在你的Django视图中使用站点框架,根据视图被调用的站点来做特定的事情。例如:
fromdjango.confimportsettingsdefmy_view(request):ifsettings.SITE_ID==3:#Dosomething.passelse:#Dosomethingelse.pass这样硬编码的网站ID很脆弱,万一变了呢。比较干净的方法是检查当前网站的域名:
下面是表单处理视图的一个例子:
fromdjango.contrib.sites.shortcutsimportget_current_sitefromdjango.core.mailimportsend_maildefregister_for_newsletter(request):#Checkformvalues,etc.,andsubscribetheuser.#...current_site=get_current_site(request)send_mail("Thanksforsubscribingto%salerts"%current_site.name,"Thanksforyoursubscription.Weappreciateit.\n\n-The%steam."%(current_site.name,),"editor@%s"%current_site.domain,[user.email],)#...在Lawrence.com上,这封邮件的主题是“感谢您订阅Lawrence.com的提醒”。在LJWorld.com上,这封邮件的主题是“感谢您订阅LJWorld.com的提醒”。邮件的信息主体也是如此。
fromdjango.core.mailimportsend_mailfromdjango.templateimportloaderdefregister_for_newsletter(request):#Checkformvalues,etc.,andsubscribetheuser.#...subject=loader.get_template("alerts/subject.txt").render({})message=loader.get_template("alerts/message.txt").render({})send_mail(subject,message,"editor@ljworld.com",[user.email])#...在这种情况下,你必须为LJWorld.com和Lawrence.com模板目录创建subject.txt和message.txt模板文件。这给你更多的灵活性,但也更复杂。
由于当前站点存储在数据库中,每次调用Site.objects.get_current()都可能导致数据库查询。但Django比这更聪明:在第一次请求时,当前站点会被缓存,随后的任何调用都会返回缓存的数据,而不是打到数据库。
如果你出于任何原因想要强制查询数据库,你可以使用Site.objects.clear_cache()告诉Django清除缓存:
使用CurrentSiteManager,将其显式添加到你的模型中。例如:
换个角度看,这两种说法是等价的:
fromdjango.contrib.sites.modelsimportSitefromdjango.contrib.sites.managersimportCurrentSiteManagerfromdjango.dbimportmodelsclassPhoto(models.Model):photo=models.FileField(upload_to="photos")photographer_name=models.CharField(max_length=100)pub_date=models.DateField()publish_on=models.ForeignKey(Site,on_delete=models.CASCADE)objects=models.Manager()on_site=CurrentSiteManager("publish_on")如果你试图使用CurrentSiteManager并传递一个不存在的字段名,Django将引发一个ValueError。