So I have an app that takes a form, and sends and e-mail address to somebody, but I want a way to stick and activation URL generated by Django into that e-mail, and not have the form data commit to the database until that activation link is clicked. Is there any way to do this?
Based on the comments on my first answer, here's a reworked one more suited to your needs.
Create a model, e.g. ServiceHours, that next to the data you want to collect (hours done, supervisor_email, ...), has the following fields:
activation_key=models.CharField(_('activation key'), max_length=40, null=True, blank=True)
validated=models.BooleanField(default=False)
I'd suggest adding a post_save signal to the Model, so that whenever a new ServiceHours instance is created (by saving the form), the email to the supervisor is sent.
# Add this to your models file
# Required imports
from django.db.models.signals import post_save
from django.utils.hashcompat import sha_constructor
import random
def _create_and_send_activation_key(sender, instance, created, **kwargs):
if created: # Only do this for newly created instances.
salt = sha_constructor(str(random.random())).hexdigest()[:5]
# Set activation key based on supervisor email
instance.activation_key = sha_constructor(salt+instance.supervisor_email).hexdigest()
instance.save()
# Create email
subject = "Please validate"
# In the message, you can use the data the volunteer has entered by accessing
# the instance properties
message = "Include instance hours, volunteer's name etc\n"
# Insert the activation key & link
messsage += "Click here: %s" % (reverse("validate_hours", kwargs={'id': instance.id, 'activation_key':instance.activation_key})
# Send the mail
from django.core.mail import send_mail # Move this import to top of your file ofcourse, I've just put it here to show what module you need
send_mail(subject, message, sender, recipients)
post_save.connect(_create_and_send_activation_key, sender=ServiceHours)
Define a view to validate service hours based on an activation key
# in views.py
def validate_hours(request, id, activation_key):
# find the corresponding ServiceHours instance
service_hours = ServiceHours.objects.get(id=id, activation_key=activation_key)
service_hours.validated = True
service_hours.save()
In your urls.py, define an url to your validate_hours view:
urlpatterns += patterns('',
url(r'^validate-hours/(?P<id>[0-9]+)/(?P<activation_key>\w+)', validate_hours, name='validate_hours'),
This has all been off the top of my head, so please excuse any errors. I hope you get the gist of the process and can extend according to your exact needs.
You might want to set/unset the is_active flag on the user.
Conceptually:
When a user registers succesfully, be sure to set the flag to False;
Autogenerate a unique string that is tied to the user's ID and send the activation url via email;
In the activation view, decompose the key into the user ID and set the is_active flag to True;
In your login view, check whether the user trying to log in has is_active is True.
Then you'll be sure that users who are logged in have a confirmed email address.
The page in Django's documentation on user authentication provides all necessary information. For a sample login view, the chapter "How to log a user in" has one.
If you'd prefer to use a reusable app, django-registration might fit your needs perfectly.
(Post-reply addition:) why not commit the data to the database? The "waste" of having unactivated users residing in your database does not outweigh the effort you'd need to implement a solution that does not commit the data to the database. Moreover, it might be more than interesting to have an idea of the amount of unactivated users (and act accordingly).
Related
Task: I would like to catch data sending by flask-admin to database after fill in forms in admin panel.
I have overridden default User view as follows:
from flask_admin.contrib.sqla import ModelView
class UserModelView(ModelView):
def is_accessible(self):
return current_user.is_active and current_user.is_authenticated and current_user.has_role("admin")
def _handle_view(self, name, **kwargs):
if not self.is_accessible():
return redirect(url_for("admin.index"))
All modifications on admin panel after save are going to database (flask-sqlalchemy) and it works fine.
Now I would like to catch the data that is sending, for example:
I have changed username from X to Y and click "save".
I want to catch that piece of information with username = "Y" sending to database.
In docs I saw that there is method:
on_model_change(form, model, is_created)[source]
Perform some actions before a model is created or updated.
So I think this is a place where I should put my code, but question is, how can I get that data sending from there to database?
Normally, when I fill in something on web, its form defined by me so I just use data from this form, but here its defined by flask-admin and I have to idea how to access there.
Any ideas?
I have an application which is school based. Each tenant is a different school and to access the application all users for each school have the same password.
Alongside this each school user has to have a google email if they want access to the application. So the application first checks they are a google user, checks wether they are a school user and finally checks that their google email is in the school user list before they are allowed access to any page.
The school user part is using session data from webapp2 sessions to ensure each request they have appropriate access
class Handler(webapp2.RequestHandler):
def dispatch(self):
# Get a session store for this request.
self.session_store = sessions.get_store(request=self.request)
try:
# Dispatch the request.
webapp2.RequestHandler.dispatch(self)
finally:
# Save all sessions.
self.session_store.save_sessions(self.response)
#webapp2.cached_property
def session(self):
# Returns a session using the default cookie key.
return self.session_store.get_session()
When a user logins I check the password then create a session which checks their password / user combination every request.
def check_u(self):
try:
uid = self.session.get('user')
parent = self.session.get('school-id')
udl = m.models.User.by_id(int(uid),parent)
if uid and udl:
return udl
else:
return False
except (TypeError,AttributeError):
return False
A parent datastore entity for each different school is used called MetaSchool which I have been currently using to ensure that there is no data leak across schools. Each datastore entry uses this parent session key as a way of setting the datastore entry with MetaSchool as parent then using this session key again to read back this data.
This method works but is onerous. I would like to use namespace as a way of separating the data but would like to use the Metaschool id as the name.
def namespace_manager_default_namespace_for_request():
### Here I need to get ------ parent = self.session.get('school-id')
### use this session to gain the MetaSchool key id
### Set this as the namespace name
Basically trying to emulate from the docs the below scenario
from google.appengine.api import users
def namespace_manager_default_namespace_for_request():
# assumes the user is logged in.
return users.get_current_user().user_id()
I am having difficulty getting the session data from Handler object???
Any thoughts
This is what I came up with.
from google.appengine.api import namespace_manager
from webapp2_extras import sessions
def namespace_manager_default_namespace_for_request():
session = sessions.get_store()
s = session.get_session()
name = s.get('key')
if name:
return name
else:
return namespace_manager.set_namespace('string')
I have just started working on Django, angularjs , The issue currently i am facing is I have created a model in django as following
**class Car_Booking(models.Model):
owner = models.ForeignKey('auth.User', related_name='booking_user')
car_id=models.IntegerField(max_length=4,default=1)
extra_field1=models.CharField(max_length=100,null=True)
extra_field2=models.CharField(max_length=50,null=True)
extra_field3=models.CharField(max_length=50,null=True)**
The Serializer is as following
**class CarBookingSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Car_Booking
fields = ('car_id','owner','extra_field1','extra_field2','extra_field3')**
And view is as following
**class CarBookingViewSet(viewsets.ModelViewSet):
"""
This viewset automatically provides `list`, `create`, `retrieve`,
`update` and `destroy` actions.
Additionally we also provide an extra `highlight` action.
"""
queryset = Car_Booking.objects.all()
serializer_class = CarBookingSerializer
permission_classes = (permissions.AllowAny,
def perform_create(self, serializer):
serializer.save(owner=self.request.user)**
Now i developed a front end on Angularjs, the templelates i built were on the same server say localhost:8000 so when i call the view to insert the data by passing car_id, extra_field1, extra_field2 and extra_field 3 it gets saved successfully because i already get logged in and saved the user information into the cookies so i guess the Owner field is resolved automatically. Now when i call the same view from the IONIC framework on server localhost:5000(port is differnt) it give me the error, "Owner must be a user instance". I have searched a lot but can not find how to send the user authentication information, or save it accross the domains. Secondly i have tried to pass the owner_id but when i write the owner_id into the serializer it says "Owner_id is not a valid modlebase" but while calling throught the command prompt i can set the owner_id, Any Help on the following questions
***1. How can i send the username and password along the Post URL
How can i set the owner_id instead of OWNER object instance.***
Regards
we are making a social network using GAE, and when we are going to create user's, we need to save contact's data about facebook, twitter, etc...
This extra contact data must be administrable by an administrator, so if the administrator adds "Whatsapp", to all users must appear a field "Whatsapp" optional, and if the administrator deletes the facebook data, all users' facebook info must be deleted.
What is the best option to save this data, considering the most efficient way, for example, for get the all user's facebook, for delete all user's twitter... by an administrator?
Thanks
There are many ways to solve this problem. One would be to have a config model, such as (assuming python) ...
class Config(db.Model):
""" singleton model """
twitter = db.BooleanProperty(default=False)
facebook = db.BooleanProperty(default=False)
whatsapp = db.BooleanProperty(default=False)
And separate fields on your profile model for each social username ...
class Profile(db.Model):
name = db.StringProperty() # users name
twitter = db.StringProperty() # store twitter username here
facebook = db.StringProperty() # store facebook username here
whatsapp = db.StringProperty() # store whatsapp username here
When you render the profile to the client, check the Config class to see what social fields have been enabled, and only render those fields.
To handle the deletion, you may need to write a cron job to iterate through all profiles and delete whatever data has been disabled on the config model.
Hope this helps
You should certainly store all entities that contain a User's specific data in the User's entity group. That enables you to retrieve and manipulate those entities using ancestor queries, which perform better than non-ancestor queries.
To make the detail entities part of a User's entity group, you simply have to create them with the parent parameter. For instance:
class TwitterData(db.Model):
twitter_name = db.StringProperty
def addTwitterData(user, twitter_name):
# User is an instance of users.User
new_twitter_entity = TwitterData(parent=user)
new_twitter_entity.twitter_name = twitter_name
new_twitter_entity.put()
Now, I can get User's data like this:
twitter_accounts = TwitterData.all().ancestor(user).fetch(1000)
Also, you can use a kindless ancestor query to get all of the entities in user's entity group:
all_networks = db.Query()
all_networks.ancestor(user).fetch(1000)
# Now, ancestor has all of user's Twitter, Facebook, Myspace accounts.
One of the strengths of this approach is that it allows your users to have more than one account on any of the various services.
If the data that you need to store for the different social sites varies too much to be served by a single, simple model, you can use Expando classes to store entities that store different types of data.
I am quite new to this Google app engine. I am learning things every day.
I am have a forum on google app engine.
But I want is to be having private or restricted parts.
Some features should be locked for certain google account users, which are in some sort of access control list.
I plain words I can say, only those user who are in list of access can see the forum rest will be redirect to the "contact to admin" page.
As I am new I wanna know that is it something possible.
if yes, how can I achieve it ?
Thanks,
Alok
If you are using the built-in Users API, you can check users.is_current_user_admin() as an access control mechanism. Administrators can be managed via the dashboard.
If you need more granular, application-specific authorization logic, generally you would create a User model in the datastore that references the built-in UserProperty and also holds a list of roles or whatever else you need to check authorization.
To follow up Drew's reply, I use a similar system in my app, so my server code has something like the following class definition (simplified here for clarity)
class myUser(db.Model):
user = db.UserProperty(required=True)
rights = db.StringProperty(required=True, choices=set(["public", "private"]))
created = db.DateTimeProperty(auto_now_add=True)
lastaccess = db.DateTimeProperty(auto_now=True)
and then I have code like this where I handle queries
def checkUserRights(user):
q = db.GqlQuery("SELECT * from myUser WHERE user = :1", user)
u = q.get()
if not u:
# create a new 'public access' user if we haven't seen this person before
u = myUser(user=user, rights="public")
# always update the user record after the source is fetched (updates the lastaccess field)
db.put( u )
return u.rights
rights = checkUser(users.get_current_user())
if isPrivateArea and rights == "private":
....
This way I create a user for EVERY visitor, and then I have an admin interface to change the rights of selected users - you may decide, for example, to not create a record for every visitor
def checkUserRights(user):
q = db.GqlQuery("SELECT * from myUser WHERE user = :1", user)
u = q.get()
if not u:
# grant default public rights to anyone...
return "public"
# always update the user record after the source is fetched (updates the lastaccess field)
db.put( u )
return u.rights
This is, of course, on a page where the app.yaml specifies "login: required"