source: subversion/applications/editors/django/osmeditor/simple/views.py @ 13463

Last change on this file since 13463 was 13463, checked in by crschmidt, 10 years ago

add support for logging in. this requires setting up a db (settings.py modified
accordingly): to use sessions, run python manage.py syncdb. Your username and
password are stored in the session and used as a fallback i the form doesn't
provide a username and password. User credentials inputs are not displayed if
the user is logged in. Also, add a couple handy links to the homepage -- one
to login, one to edit my house.

File size: 6.2 KB
Line 
1import xml.dom.minidom as m
2from django.conf import settings
3from django import forms
4from django.shortcuts import render_to_response
5from django.http import HttpResponseRedirect
6try:
7    import httplib2
8except:
9    from third import httplib2
10
11try:
12    from xml.etree.cElementTree import Element, SubElement, tostring
13except:
14    from third.ElementTree import Element, SubElement, tostring
15
16import urllib
17
18def get_xml(type, id):
19    url = "%s/%s/%s" % (settings.OSM_API, type, id)
20    u = urllib.urlopen(url)
21    data = u.read()
22    doc = m.parseString(data)
23    return doc
24
25def get_osm_obj(type, id, doc=None):
26    obj = {}
27    if not doc:
28        doc = get_xml(type, id)
29    parent = doc.getElementsByTagName(type)[0]
30    obj['timestamp'] = parent.getAttribute("timestamp")
31    obj['child'] = [] #everyone now gets 0 or more children
32    if type == "node":
33        obj['lat'] = parent.getAttribute("lat")
34        obj['lon'] = parent.getAttribute("lon")
35    elif type == "way":
36        for node in parent.getElementsByTagName("nd"):
37            obj['child'].append( {'ref': node.getAttribute("ref"),
38                                  'type':'node'
39                                 } )
40    elif type == "relation":
41        for member in parent.getElementsByTagName("member"):
42            obj['child'].append( { 'ref': member.getAttribute("ref"),
43                                   'type': member.getAttribute("type"),
44                                   'role': member.getAttribute("role")
45                                 } )
46    obj['child_count'] = len(obj['child'])
47    obj['id'] = int(id)
48    obj['type'] = type
49    obj['tags'] = {}
50    for tag in parent.getElementsByTagName("tag"):
51        obj['tags'][tag.getAttribute("k")] = tag.getAttribute("v")
52    #hmm, not sure how the UI should manage the created_by tag
53    #obj['tags']['created_by'] = "%s (%s)" % (settings.APP_NAME,settings.APP_URI)
54    obj['user'] = { 'id': parent.getAttribute("user") ,
55                    'uri': settings.OSM_USER % parent.getAttribute("user") 
56                  }
57    obj['uri'] = settings.OSM_BROWSE % (type.lower(),id)
58    return obj
59
60def edit_osm_obj(type, id, post, session={}):
61    xml = get_xml(type, id)
62    obj = get_osm_obj(type, id, xml)
63    if obj['timestamp'] != post['timestamp']:
64        raise Exception("Object changed since you started editing it.")
65    osm = Element('osm', {'version': '0.5'})
66    if type == "node":
67        parent = SubElement(osm, type, {'id':id, 
68                                        'lat':obj['lat'],
69                                        'lon':obj['lon']
70                                        })
71    elif type == "way":
72        parent = SubElement(osm, type, {'id':id, })
73        for nd in xml.getElementsByTagName("nd"):
74            nd = SubElement(parent, "nd", {'ref': nd.getAttribute("ref")})
75   
76    elif type == "relation":
77        parent = SubElement(osm, type, {'id':id, })
78        for m in xml.getElementsByTagName("member"):
79            member = SubElement(parent, "member", {'type': nd.getAttribute("type"),
80                                                   'id': nd.getAttribute("id"),
81                                                   'role': nd.getAttribute("role")
82                                                  }
83                               )
84    else:
85        raise Exception("%s not supported" % type)
86    changed = False
87    for key in filter(lambda x: x.startswith("delete_"), post.keys()):
88        k = key.replace("delete_key_", "")
89        if k in obj['tags']:
90            changed = True
91            del obj['tags'][k]
92        else:
93            raise Exception("Huh? %s is not in tags" % k)
94   
95    for key in filter(lambda x: x.startswith("key_"), post.keys()):
96        k = key.replace("key_", "")
97        if k in obj['tags'] and post[key] != obj['tags'][k]:
98            changed = True
99            obj['tags'][k] = post[key]
100   
101    for key in filter(lambda x: x.startswith("new_key_"), post.keys()):
102        new_id = key.replace("new_key_", "")
103        kname = "new_key_%s" % new_id
104        vname = "new_value_%s" % new_id
105        if kname in post and vname in post:
106            k = post[kname]
107            v = post[vname]
108            if k and v:
109                obj['tags'][k] = v
110                changed = True
111           
112    if not changed: return
113
114    for k, v in obj['tags'].items():
115        SubElement(parent, "tag", {'k': k, 'v': v})
116 
117    username = post.get('username', None) or session.get("username", None)
118    password = post.get('password', None) or session.get("password", None)
119    if not username or not password:
120        raise Exception("Need username and password")
121    xml = tostring(osm)
122    change_obj(type, id, xml, username, password)
123
124def change_obj(type, id, xml, username, password):   
125    url = "%s/%s/%s" % (settings.OSM_API, type, id)
126    http = httplib2.Http()   
127    http.add_credentials(username, password)
128    resp, content = http.request(url, "PUT", body=xml)   
129    if int(resp.status) != 200:
130        raise Exception(resp.status)
131
132def load(request, type="node", id=0):
133    if request.method == "POST":
134        edit_osm_obj(type, id, request.POST, request.session)
135        return HttpResponseRedirect("/%s/%s/" % (type, id))   
136    obj = get_osm_obj(type, id)
137   
138    return render_to_response("obj.html",{'obj':obj, 
139        'logged_in': ('username' in request.session)})
140
141def home(request):
142    return render_to_response("home.html", {'logged_in': 'username' in request.session})
143
144class UserForm(forms.Form):
145    email = forms.CharField(max_length=255)
146    password = forms.CharField(widget=forms.PasswordInput)
147
148def login(request):
149    if request.method == "POST":
150        form = UserForm(request.POST)
151        if form.is_valid():
152            username = form.cleaned_data['email']
153            password = form.cleaned_data['password']
154            http = httplib2.Http()   
155            http.add_credentials(username, password)
156            url = "%s/user/details" % (settings.OSM_API)
157            resp, content = http.request(url, "GET")
158            if int(resp.status) == 200:
159                request.session['username'] = username
160                request.session['password'] = password
161                return HttpResponseRedirect("/")   
162    else:
163        form = UserForm()
164    return render_to_response("login.html", {'form': form})   
Note: See TracBrowser for help on using the repository browser.