django+jquery 实现级联选择菜单
最近在做一个基于django框架的项目,需要实现级联选择菜单,比如省-市-区,记录下来,希望能帮助碰到同样问题的人。
--------------------------------------------------------------------------------------------
无代码无真相,直接上代码:
js代码:
<script src="/site_media/js/jquery-1.5.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
function getCityOptions(province_id){
$.ajax({
type: "GET",
url: "/getCityList?provinceID="+province_id,
dataType:'json',
success: function(data,textStatus){
var citySelect = document.getElementById("id_city");
for ( var i=citySelect.options.length-1; i>-1; i--){
citySelect[i] = null;
}
if(data.length > 0) {
$("#id_city").show();
for(i=0;i<data.length;i++){
citySelect.options[i] = new Option();
citySelect.options[i].text = data[i].label;
citySelect.options[i].value = data[i].text;
}
}else
$("#id_city").hide();
}
})
}
</script>
模板代码:
<label>省市:</label>
{{form.province}}
{{form.city}}
Form.py:
provinces = Province.objects.all()
PROVINCE_CHOICES = []
for province in provinces:
PROVINCE_CHOICES.append([province.id, province.provinceName])
class myForm(forms.Form): province = forms.ChoiceField(widget = forms.Select(attrs={'class':'select', 'onChange':'getCityOptions(this.value)'}), choices = PROVINCE_CHOICES, label= u'选择省') city = forms.ChoiceField(widget = forms.Select(attrs={'class':'select', 'onChange':'getDistrictOptions(this.value)','style':'display:none'}), label = u'选择市')
model.py:
class Province(models.Model): provinceName = models.CharField(max_length = 20) class City(models.Model): cityName = models.CharField(max_length = 20) provinceID = models.ForeignKey(Province)
view.py
def city_list(request):
city_list = []
province = request.GET['provinceID']
citys = City.objects.filter(provinceID = province)
for city in citys:
c = {}
c['label'] = city.cityName
c['text'] = city.id
city_list.append(c)
return HttpResponse(simplejson.dumps(city_list), mimetype='application/json')
ubuntu10.10+django+apache2+(mod-python 或 wsgi)
这几天一直在折腾django在apache上的部署,网上的资料鱼龙混杂,特将经验记录下来,希望能帮助更多的人。
mod-python:
1.安装apache,mod-python:
sudo apt-get install apache2 libapache2-mod-python
2.在/etc/apache2/available/目录下建立配置文件:mytest
<VirtualHost *:80>
ServerName localhost
DocumentRoot /home/sarlmolapple/workspace/django-site/mytest
<Directory "/home/sarlmolapple/workspace/django-site">
Allow from all
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mytest.settings
PythonDebug On
PythonPath "['/home/sarlmolapple/workspace/django-site', '/home/sarlmolapple/workspace/django-site/mytest', '/home/sarlmolapple/workspace/django-site/mytest/mysite'] + sys.path"
</Directory>
</VirtualHost>
注:django项目为mytest, 路径为:/home/sarlmolapple/workspace/django-site/mytest,
‘/home/sarlmolapple/workspace/django-site/mytest/mysite’为mytest中的app所在路径
3.运行命令:
sudo a2ensite mytest sudo /etc/init.d/apache2 reload
然后你在浏览器中输入http://localhost就可以看到你想要看到的页面了
WSGI:
1.安装apache,mod-python:
sudo apt-get install apache2 libapache2-wsgi-python
2.在/etc/apache2/available/目录下建立配置文件:mytest
<VirtualHost *:80>
ServerName wsgi.mytest
DocumentRoot /home/sarlmolapple/workspace/django-site/mytest
<Directory /home/sarlmolapple/workspace/django-site/mytest>
Order allow,deny
Allow from all
PythonPath "['/home/sarlmolapple/workspace/django-site', '/home/sarlmolapple/workspace/django-site/mytest', '/home/sarlmolapple/workspace/django-site/mytest/mysite'] + sys.path"
</Directory>
WSGIDaemonProcess wsgi.mytest processes=2 threads=15 display-name=%{GROUP}
WSGIProcessGroup wsgi.mytest
WSGIScriptAlias / /home/sarlmolapple/workspace/django-site/mytest/apache/django.wsgi
</VirtualHost>
3.在mytest目录下建立apache/django.wsgi
import os
import sys
sys.path.append('/home/sarlmolapple/workspace/django-site')
sys.path.append('/home/sarlmolapple/workspace/django-site/mytest')
sys.path.append('/home/sarlmolapple/workspace/django-site/mytest/mysite')
os.environ['DJANGO_SETTINGS_MODULE'] = 'mytest.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
注: mytest路径为:/home/sarlmolapple/workspace/django-site/mytest,‘/home/sarlmolapple/workspace/django-site/mytest/mysite’为mytest中的app所在路径
4.运行命令:
sudo a2ensite mytest sudo /etc/init.d/apache2 reload
同理,你在浏览器中输入http://localhost就可以看到你想要看到的页面了。
对数据库索引的理解
最近在写一个项目,其中涉及表test的访问,我想设计复合索引以提高查询效率。
表test如下:
id: INT primary key x1: INT x2: INT x3: INT
我用存储过程生成200w行数据
建立索引:
create index x1_x2_x3 on test(x1, x2, x3);
查询语句:
select * from test where x1 > xx and x2 < xx and x3 > xx;
explain之后发现type为all,也就是扫描全表,索引x1_x2_x3并没有用到,这让我百思不得其解;经过不断的纠结与实验后,基本找到了答案:索引需要对每一列有一个范围约束,比如:select * from test where x1 > xx and x1 < xx...;这样type才能为range,ps:range不能小于总行数的四分之一。所以查询应该是类似:
select * from test where x1 > xx and x1 < xx and x2 < xx and x2 > xx and x3 > xx;
本来到此结束了,我又蛋疼的想分析下单独索引与复合索引的效率:
测试一组数据:
x1,x2,x3分别索引 0.01s 扫描了48686行 X1,X2分别索引 0.10s x1索引 0.18s x1_x2_x3复合索引 0.20s 扫描了40117行 无索引 0.34s
我个人感觉复合索引虽然扫描行数少,但是有一部分资源消耗,导致没有单独索引快。
关于sina api上传图片接口(upload) c#版
之前我写了sinaapi c#的sdk:opensinaapi,没有实现上传图片的接口。因为要忙实验室和其他项目,一直没有去研究。期间很多人询问过我有关上传图片接口的问题,最近刚好有些时间,花了一个晚上实现出来,需要的同学可以去http://code.google.com/p/opensinaapi/downloads/list下载。
在研究的过程中我发现相关的资料非常少,基本上不能找到有用的信息。相对来说,twitter api的upload借口实现有其借鉴意义,但是其并不适用在sina api上,如果有人去研究的话应该会发现大多会返回401错误(未能授权)。原因是:sina api和twitter api中post的参数不一样,sina api中多了一个参数:source,少了oauth_verify。POST的参数和Update的接口一样,需要将status加入签名。
我在研究过程中主要是抓取upload的POST包,对包结构进行分析,从而用c#构造POST包(抓包工具HttpAnalyzer)。以下为一个真实的POST包:
POST /statuses/upload.json HTTP/1.1 Authorization: OAuth oauth_consumer_key="3587646579", oauth_signature_method="HMAC-SHA1",oauth_timestamp="1289113593", oauth_nonce="7472747", oauth_version="1.0", oauth_token="9f273ceccf51e528b302a3a47053badd",oauth_signature="O5b4XTaazF6T50YqSsyLM6RtRsk%3d" User-Agent: Jakarta Commons-HttpClient/3.1 Content-Type: multipart/form-data; boundary=bb9f588b-0eaf-4d95-aaec-b10f057bccd7 Host: api.t.sina.com.cn Content-Length: 26509 --bb9f588b-0eaf-4d95-aaec-b10f057bccd7 Content-Disposition: form-data; name="status" Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 8bit %e6%88%91%e6%98%af%e9%99%88%e7%9d%80 --bb9f588b-0eaf-4d95-aaec-b10f057bccd7 Content-Disposition: form-data; name="source" Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 8bit 3587646579 --bb9f588b-0eaf-4d95-aaec-b10f057bccd7 Content-Disposition: form-data; name="pic"; filename="sample_image.png" Content-Type: application/octet-stream; charset=UTF-8 Content-Transfer-Encoding: binary XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX --bb9f588b-0eaf-4d95-aaec-b10f057bccd7
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX为二进制文件串
以下是构造POST包的c#代码
public string oAuthWebRequestWithPic(Method method, string url, string postData,string filepath,string picName)
{
var UploadApiUrl = url;
string status = postData.Split('=').GetValue(1).ToString();
postData += "&source=" + _consumerKey;//多了一个source参数
if (postData.Length > 0)
{
NameValueCollection qs = HttpUtility.ParseQueryString(postData);
postData = "";
foreach (string key in qs.AllKeys)
{
if (postData.Length > 0)
{
postData += "&";
}
qs[key] = HttpUtility.UrlEncode(qs[key]);
qs[key] = this.UrlEncode(qs[key]);
postData += (key + "=" + qs[key]);
}
if (url.IndexOf("?") > 0)
{
url += "&";
}
else
{
url += "?";
}
url += postData;
}
var oauthSignaturePattern = "OAuth oauth_consumer_key=\"{0}\", oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"{1}\", oauth_nonce=\"{2}\", oauth_version=\"1.0\", oauth_token=\"{3}\",oauth_signature=\"{4}\"";
var contentEncoding = "iso-8859-1";
string normalizedString, normalizedParameters;
var timestamp = this.GenerateTimeStamp();
var nounce = this.GenerateNonce();
var signature = this.GenerateSignature(
new Uri(url),
this.ConsumerKey,
this.ConsumerSecret,
this.Token,
this.TokenSecret,
method.ToString(),
timestamp,
nounce,
out normalizedString,
out normalizedParameters);
signature = HttpUtility.UrlEncode(signature);
var boundary = Guid.NewGuid().ToString();
var request = (HttpWebRequest)System.Net.WebRequest.Create(UploadApiUrl);
request.PreAuthenticate = true;
request.AllowWriteStreamBuffering = true;
request.Method = method.ToString();
request.UserAgent = "Jakarta Commons-HttpClient/3.1";
var authorizationHeader = string.Format(
CultureInfo.InvariantCulture,
oauthSignaturePattern,
this.ConsumerKey,
timestamp,
nounce,
this.Token,
signature);
request.Headers.Add("Authorization", authorizationHeader);
var header = string.Format("--{0}", boundary);
var footer = string.Format("--{0}--", boundary);
var contents = new StringBuilder();
request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
contents.AppendLine(header);
contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "status"));
contents.AppendLine("Content-Type: text/plain; charset=US-ASCII");
contents.AppendLine("Content-Transfer-Encoding: 8bit");
contents.AppendLine();
contents.AppendLine(status);
contents.AppendLine(header);
contents.AppendLine(string.Format("Content-Disposition: form-data; name=\"{0}\"", "source"));
contents.AppendLine("Content-Type: text/plain; charset=US-ASCII");
contents.AppendLine("Content-Transfer-Encoding: 8bit");
contents.AppendLine();
contents.AppendLine(this.ConsumerKey);
contents.AppendLine(header);
string fileHeader = string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"", "pic", picName);
string fileData = System.Text.Encoding.GetEncoding(contentEncoding).GetString(File.ReadAllBytes(@filepath));
contents.AppendLine(fileHeader);
contents.AppendLine("Content-Type: application/octet-stream; charset=UTF-8");
contents.AppendLine("Content-Transfer-Encoding: binary");
contents.AppendLine();
contents.AppendLine(fileData);
contents.AppendLine(footer);
byte[] bytes = Encoding.GetEncoding(contentEncoding).GetBytes(contents.ToString());
request.ContentLength = bytes.Length;
var requestStream = request.GetRequestStream();
try
{
requestStream.Write(bytes, 0, bytes.Length);
}
catch
{
throw;
}
finally
{
requestStream.Close();
requestStream = null;
}
return WebResponseGet(request);
}
其次,需要修改oAuthBase.cs,这是因为签名参数的问题:多了source少了oauth_verify
将 public string GenerateSignatureBase(Uri url, string consumerKey, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, string signatureType, out string normalizedUrl, out string normalizedRequestParameters)中 if (!string.IsNullOrEmpty(oauth_verifier)) 改为 if (!string.IsNullOrEmpty(oauth_verifier) && httpMethod == "GET")
有个比较奇怪的问题,sina api的update接口可以不需要将oauth_verify换为source,而upload接口则必须将oauth_verify换为source。
最后,本版本的sdk中,upload的status必须为英文,暂时还没解决中文问题。
注:由于本人时间有限,而sdk还相当不完善,如有同学想加入opensinaapi,请联系sarlmolapple@gmail.com,不胜荣幸,希望能帮助更多的人。
75道逻辑题
【1】假设有一个池塘,里面有无穷多的水。现有2个空水壶,容积分别为5升和6升。问题是如何只用这2个水壶从池塘里取得3升的水。