-
Notifications
You must be signed in to change notification settings - Fork 0
/
models_v1.py
163 lines (136 loc) · 5.41 KB
/
models_v1.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# Console datastore
# http://localhost:8000/instances
# Get the Google database
# from google.appengine.ext import db
from google.appengine.ext import ndb
# Migration documentation
# https://cloud.google.com/appengine/docs/standard/python/ndb/db_to_ndb
import os
import jinja2
from pybcrypt import bcrypt
template_dir = os.path.join(os.path.dirname(__file__), 'www')
jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(template_dir),
autoescape=True) # autoescape is important for security!!
# User stuff
def users_key(group = 'default'):
# return db.Key.from_path('users', group)
return ndb.Key('users', group)
def make_pw_hash(email, pw, salt = None): # Course function
if not salt:
salt = bcrypt.gensalt()
h = bcrypt.hashpw(email + pw, salt)
return( "%s|%s" % (salt, h))
# def check_pw(name, pw, h):
# salt = h.split("|")[2]
# return h == hash_pw(name + pw, salt)
def valid_pw(email, pw, h): # Course function
if (h == None): # Can happen if user was a google user (no password was used on 1st login)
salt = None
else:
salt = h.split("|")[0]
return h == make_pw_hash(email, pw, salt)
class User(ndb.Model):
username = ndb.StringProperty(required = True)
last_name = ndb.StringProperty(required = False)
email = ndb.StringProperty(required = True)
pw_hash = ndb.StringProperty(required = False)
# If google user
guser_id = ndb.StringProperty(required = False) # googleUser
nickname = ndb.StringProperty(required = False) # googleUser
avatar = ndb.BlobProperty() # For storing images
created = ndb.DateTimeProperty(auto_now_add = True)
last_modified = ndb.DateTimeProperty(auto_now = True)
# @decorator:
# means that you can call the
# object's method without instantiating the object
@classmethod
def by_id(cls, uid):
# 'cls' refers to the User class
return cls.get_by_id(uid, parent = users_key())
@classmethod
def by_google_id(cls, gid):
# 'cls' refers to the User class
# return cls.query().filter('guser_id =', gid).get()
return cls.query(cls.guser_id == gid).get()
@classmethod
def by_name(cls, username):
# Query the db without GQL
u = cls.query(cls.username == username).get()
return u
@classmethod
def by_email(cls, email):
# Query the db without GQL
u = cls.query(cls.email == email).get()
return u
@classmethod
def by_gtoken(cls, idtoken):
# Query the db without GQL
u = cls.query(cls.idtoken == idtoken).get()
return u
@classmethod
def register(cls, username, last_name, pw, email):
pw_hash = make_pw_hash(email, pw)
return User(parent = users_key(),
username = username,
last_name = last_name,
pw_hash = pw_hash,
email = email)
@classmethod
def login(cls, email, password):
u = cls.by_email(email)
if u and valid_pw(email, password, u.pw_hash):
return u
# Blog stuff
def blog_key(name='default'):
# Method to organize the database in case more than one blog.
# return db.Key.from_path('blogs', name)
return ndb.Key('blogs', name)
class Articles(ndb.Model):
# create entities
author = ndb.StringProperty(required = False)
subject = ndb.StringProperty(required = True)
content = ndb.TextProperty(required = True)
image_1st = ndb.BlobProperty() # For storing images
image_1st_w = ndb.StringProperty() # Allows
image_1st_h = ndb.StringProperty()
image_2nd = ndb.BlobProperty() # For storing images
image_2nd_w = ndb.StringProperty()
image_2nd_h = ndb.StringProperty()
image_3rd = ndb.BlobProperty() # For storing images
image_3rd_w = ndb.StringProperty()
image_3rd_h = ndb.StringProperty()
has_image = ndb.BooleanProperty() # Controls post.html layout
images_num = ndb.IntegerProperty() # Controls the onepost.html layout
created = ndb.DateTimeProperty(auto_now_add = True)
last_modified = ndb.DateTimeProperty(auto_now = True)
# Careful when naming properties, if
# create a model, and get an error when using it first it will break that
# propert and the name assigned (e.g. "location") won't work again.
# My mistake was when I assigned
# a['location'] = ... instead of:
# a.location = ...
# location = ndb.GeoPtProperty()
location2 = ndb.GeoPtProperty()
coords = ndb.GeoPtProperty()
map_url = ndb.StringProperty()
def render(self):
self._render_text = self.content.replace('\n', '<br>')
# Use global method render_str()
return render_str("post.html", p = self) # self is 'art' (ie. one article)
def render_one(self):
self._render_text = self.content.replace('\n', '<br>')
# Use global method render_str()
return render_str("onepost.html", p = self) # self is 'art' (ie. one article)
@classmethod
def by_id(cls, aid):
# 'cls' refers to the User class
return cls.get_by_id(aid, parent = blog_key())
# TODO: define a similar method here for Articles.
# @classmethod
# def by_id(cls, id):
# # 'cls' refers to the User class
# return cls.get_by_id(id, parent = users_key())
# Exact same method as in the Handler class
def render_str(template, **params):
t = jinja_env.get_template(template)
return t.render(params)