When trying to access the database, I am unable to access the column. I have run the init database script multiple times. Here's the code:
View
from .models import Session, Admin
#view_config(route_name='admin', renderer='templates/admin.pt')
def admin(request):
session = Session()
user = authenticated_userid(request)
admin = bool(session.query(Admin).filter_by(username = user).first())
message = ''
if admin:
if 'form.submitted' in request.params:
session.add(Admin(request.params['admin']))
session.commit()
message = "%s has been added as an Admin!" % request.params['admin']
return dict(url=request.route_url('admin'),
message = message,
)
return dict(message = message)
else:
return HTTPForbidden()
Models
class Admin(Base):
__tablename__='admins'
__table_args__={
'mysql_engine':'InnoDB',
'mysql_charset':'utf8',
}
username = Column(String(255), ForeignKey('users.username'), primary_key=True)
def __init(self, user):
self.username = user
The database script can't add column on an already existing table. If you modified or added the column after running the script, that's where your problem come from.
You have three possibilities :
Delete the database and let the script recreate it the right way
Run the sql to add the column by hand.
Take a look at Alembic, which can help you do that automatically.
Related
I was able to create a schema (and I confirmed this via database) but for some reason, I am getting a Can't create tenant outside the public schema. Current schema is error when creating schema and then also I am getting this error No tenant for hostname when I try to visit the tenants domain and I am not sure what is causing it. Below is my code:
views.py
def post(self, request):
form = CreatePortalForm(request.POST)
if form.is_valid():
getDomain = form.cleaned_data.get('name')
instance = form.save(commit=False)
user_id = request.user.id
user = User.objects.get(id=user_id)
tenant = Client(schema_name=getDomain, name=getDomain, created_by=user)
tenant.save()
domain = Domain()
domain.domain = getDomain + ".example.com:8000"
domain.tenant = tenant
domain.is_primary = True
domain.save()
with schema_context(tenant.schema_name):
instance.save()
redirect = 'http://' + getDomain + '.example.com:8000'
return HttpResponseRedirect(redirect)
return render(request, "registraton/create_portal.html", {"form": form})
For example, I have created three schemas:
tenant1
tenant2
tenant3
All three tenants have created the tables in the database, but I get the Can't create tenant outside the public schema. Current schema is error when running the above script to create the schema and domain or I get the No tenant for hostname when trying to visit the tenants domain.
Like I said, the schema is creating and migrating successfully but I still cannot get to the domain.example.com as it throws the No tenant for hostname error. Any ideas on what is causing this?
The django-tenants docs says that you shouldn't specify the port for your domain.
See this here
Summary: (Python+Flask+MongoDB) Defined two models - User and Post. Post references User. Trying to create a Post by referencing a saved User but getting You can only reference documents once they have been saved to the database error.
Detail
Hello! I'm following a python (installed v3.7), flask (installed v1.1.2), MongoDB (installed mongoengine v0.23.0) tutorial to write a simple blogging app.
I have a User model and a Post model. A User may register, login and write Posts. I am able to create and save Users. However, when I try to create a Post by referencing a (previously created & saved) User, I get a Mongoengine ValidationError You can only reference documents once they have been saved to the database
The User object referenced in the Post object is present in the DB - confirmed that via the Mongo shell.
Any pointers/help/inputs would be much appreciated. I am new to MongoDB.
Code
# models.py
from flask_mongoengine import MongoEngine
db = MongoEngine()
class User(db.Document):
_id = db.ObjectIdField()
username = db.StringField(required = True)
email = db.EmailField(required = True)
class Post(db.Document):
_id = db.ObjectIdField()
created_by = db.ReferenceField(User)
title = db.StringField(required = True)
body = db.StringField(required = True)
# blog.py
""" Module that creates blog posts
from app.models import User, Post
def create():
if request.method == 'POST':
title = request.form['title']
body = request.form['body']
user = User.objects.get(_id=g.user['_id'])
# check user fetched by printing object id
# user[_id] matches the User ObjectID obtained via the mongo shell
print('user id = ' + str(user['_id']))
post = Post(title=title, body=body)
post.created_by = user
post.save() # --> this line generates the error
return redirect(url_for('blog.index'))
return render_template('blog/create.html')
Error
File "/Users/<my_username>/.pyenv/versions/3.7.3/lib/python3.7/site-packages/mongoengine/base/document.py", line 433, in validate
raise ValidationError(message, errors=errors)
mongoengine.errors.ValidationError: ValidationError (Post:None) (You can only reference documents once they have been saved to the database: ['created_by'])
Based on this Stackoverflow question, I was able to make this work by saving the User and then passing the DBRef of the User into the Post.
user = User.objects.get(_id=g.user['_id'])
user.save()
post = Post(title=title, body=body)
post.created_by = user.to_dbref()
post.save()
I am trying to register a new user on the site,
class UserInfo(models.Model):
user = models.ForeignKey(User,primary_key=True)#user profile
email_id=models.CharField(max_length=32, null=True, blank=True)
When I am registering the user, I am getting stuck by Integrity Error, please help me to resolve the problem.
def registration(request):
registration_dict = {}
if 1==1 :
#if request.POST:
#username=request.POST['email']
#password=request.POST['password']
username="admin#admin.com"
password='123456'
#try:
UserInfo.objects.get_or_create(email_id=username,user__username=username,user__email=username,user__password=password)
#except:
# registration_dict["status"]="0"
# registration_dict["message"]="Username already present"
# return HttpResponse(simplejson.dumps(registration_dict),content_type="application/json")
registration_dict["status"]="1"
registration_dict["message"]="Thank You for registering"
return HttpResponse(simplejson.dumps(registration_dict),content_type="application/json")
else:
registration_dict["status"]="0"
registration_dict["message"]="Unable to process the request"
return HttpResponse(simplejson.dumps(registration_dict),content_type="application/json")
EDIT 1
I have tried changing
UserInfo.objects.get_or_create(email_id=username,user__username=username,user__email=username,user__password=password,user_id=1)
and then the error changes, to
'Cannot add or update a child row: a foreign key constraint fails (`app_info`.`appdata_userinfo`, CONSTRAINT `user_id_refs_id_b0fd803b` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`))')
From the limited information I would say the problem is
it does not find a UserInfo that matches. It then tries to create a new UserInfo, but it has no User to assign to the User ForeignKey. I would suggest the following:
user = authenticate(username=email, password=password)
if user is None:
user = User(username=email, password=password, email=email)
user_info = UserInfo.objects.get_or_create(user=user, email_id=email)
If the original User object doesn't exist, you'll run into all kinds of problems. So, you need to break the process down into two steps.
Check if a User object exists or not, if it doesn't create it.
Check if a UserInfo object exists for that user, if it doesn't create it.
As there is a ForeignKey, you cannot do it in one step:
username = "admin#admin.com"
password = '123456'
obj, created = User.objects.get_or_create(username=username)
obj.set_password(password) # the proper way to set the password
obj.save()
# Now fetch or create a UserInfo object
info, created = UserInfo.objects.get_or_create(email_id=username,user=obj)
I cant understand why you need UserInfo because email is already there in User.
Issue can be corrected by splitting the fetching process
username = "admin#admin.com"
password = '123456'
user,status = User.objects.get_or_create(username=username, password=password)
user_info = UserInfo.objects.get_or_create(user=user,email_id=username)
I am using google app engine in python with a Jinja2 template engine.
This may be a silly solution but I have a list of a few thousand users and right now they can only access their own profile pages and have to be logged in to do it. I would like to give every user a unique URL for their profile page and I am wondering how to do it. I am not sure if this would work but could something like this be feasible?
class ProfilePage
userlist = GQL query to return all users in the system
user = users.get_by_id()
for user in userlist:
id = user.federated_id
posts = GQL query to return all posts by that user
self.render('/profile/id', posts=posts)
app = webapp2.WSGIApplication([('/', MainPage),
('/profile/([0-9]+)', ProfilePage),])
My HTML for the profile page just displays the user's name and then displays all of their recent posts.
Update:
So here is my current code but I am just getting a 404 error:
class ProfilePage(webapp2.RequestHandler):
def get(self, profile_id):
user = User.get_by_id(profile_id)
#profile_id = some unique field
if user:
#Get all posts for that user and render....
theid = user.theid
personalposts = db.GqlQuery("select * from Post where theid =:1 order by created desc limit 30", theid)
else:
personalposts = None
global visits
logout = users.create_logout_url(self.request.uri)
currentuser = users.get_current_user()
self.render('profile.html', user = currentuser, visits = visits, logout=logout, personalposts=personalposts)
How can I test it out I tried just entering www.url.com/profile/https://www.google.com/accounts/o8/id?id=AItOawlILoSKGNwU5RuTiRtXug1l8raLEv5-mZg
Update:
The ID I was retrieving was not their OpenID URL but rather a app specific id that each user is given and thus that is the correct to use
An easy way to do this would be to assign a unique URL identifier to each user (or use their key name), that way you can query the user by their ID or do a query based on a unique URL identifier property. You can also use their federated_id if you wanted.
Example:
class User(ndb.Model):
unique_identifier = ndb.StringProperty()
...
class ProfilePage(webapp2.RequestHandler):
def get(self, profile_id):
#profile_id = key name of user
user = User.get_by_id(profile_id)
#profile_id = some unique field
#user = User.query(User.unique_identifier == profile_id).get()
if user:
#Get all posts for that user and render....
app = webapp2.WSGIApplication([('/', MainPage),
('/profile/<profile_id>', ProfilePage),])
I am a newbie to python. I am not able to query from the entities- UserDetails and PhoneBook I loaded to the app engine datastore. I have written this UI below based on the youtube video by Brett on "Developing and Deploying applications on GAE" -- shoutout application. Well I just tried to do some reverse engineering to query from the datastore but failed in every step.
#!/usr/bin/env python
import wsgiref.handlers
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
import models
class showPhoneBook(db.Model):
""" property to store user_name from UI to persist for the session """
user_name = db.StringProperty(required=True)
class MyHandler(webapp.RequestHandler):
def get(self):
## Query to get the user_id using user_name retrieved from UI ##
p = UserDetails.all().filter('user_name = ', user_name)
result1 = p.get()
for itr1 in result1:
userId = itr.user_id
## Query to get the phone book contacts using user_id retrieved ##
q = PhoneBook.all().filter('user_id = ', userId)
values = {
'phoneBookValues': q
}
self.request.out.write(
template.render('phonebook.html', values))
def post(self):
phoneBookuser = showPhoneBook(
user_name = self.request.get('username'))
phoneBookuser.put()
self.redirect('/')
def main():
app = webapp.WSGIApplication([
(r'.*',MyHandler)], debug=True)
wsgiref.handlers.CGIHandler().run(app)
if __name__ == "__main__":
main()
This is my models.py file where I've defined my UserDetails and PhoneBook classes,
#!/usr/bin/env python
from google.appengine.ext import db
#Table structure of User Details table
class UserDetails(db.Model):
user_id = db.IntegerProperty(required = True)
user_name = db.StringProperty(required = True)
mobile_number = db.PhoneNumberProperty(required = True)
#Table structure of Phone Book table
class PhoneBook(db.Model):
contact_id = db.IntegerProperty(required=True)
user_id = db.IntegerProperty(required=True)
contact_name = db.StringProperty(required=True)
contact_number = db.PhoneNumberProperty(required=True)
Here are the problems I am facing,
1) I am not able to call user_name (retrieved from UI-- phoneBookuser = showPhoneBook(user_name = self.request.get('username'))) in get(self) method for querying UserDetails to to get the corresponding user_name.
2) The code is not able to recognize UserDetails and PhoneBook classes when importing from models.py file.
3) I tried to define UserDetails and PhoneBook classes in the main.py file itself, them I get the error at result1 = p.get() saying BadValueError: Unsupported type for property : <class 'google.appengine.ext.db.PropertiedClass'>
I have been struggling since 2 weeks to get through the mess I am into but in vain. Please help me out in straightening out my code('coz I feel what I've written is a error-prone code all the way).
I recommend that you read the Python documentation of GAE found here.
Some comments:
To use your models found in models.py, you either need to use the prefix models. (e.g. models.UserDetails) or import them using
from models import *
in MyHandler.get() you don't lookup the username get parameter
To fetch values corresponding to a query, you do p.fetch(1) not p.get()
You should also read Reference properties in GAE as well. I recommend you having your models as:
class UserDetails(db.Model):
user_name = db.StringProperty(required = True)
mobile_number = db.PhoneNumberProperty(required = True)
#Table structure of Phone Book table
class PhoneBook(db.Model):
user = db.ReferenceProperty(UserDetails)
contact_name = db.StringProperty(required=True)
contact_number = db.PhoneNumberProperty(required=True)
Then your MyHandler.get() code will look like:
def get(self):
## Query to get the user_id using user_name retrieved from UI ##
user_name = self.request.get('username')
p = UserDetails.all().filter('user_name = ', user_name)
user = p.fetch(1)[0]
values = {
'phoneBookValues': user.phonebook_set
}
self.response.out.write(template.render('phonebook.html', values))
(Needless to say, you need to handle the case where the username is not found in the database)
I don't quite understand the point of showPhoneBook model.
Your "session variable" being stored to the datastore isn't going to follow your redirect; you'd have to fetch it from the datastore in your get() handler, although without setting a session ID in a cookie or something this isn't going to implement sessions at all, but rather allow anyone getting / to use whatever value was send with a POST request whether it was sent by them or someone else. Why use the redirect at all; responding to a POST request should be done in the post() method, not through a redirect to a GET method.