Cannot import name save_status_to_session - python

I am using python-social-auth API for authentication for facebook in my website. But I am getting an exception.
while using 'apps.pipeline.save_profile'
'cannot import name save_status_to_session'
I am using django-pipeline version 1.6.13
This code in pipelne.py
def require_email(strategy, details, user=None, is_new=False, *args, **kwargs):
if kwargs.get('ajax') or user and user.email:
return
elif is_new and not details.get('email'):
email = strategy.request_data().get('email')
if email:
details['email'] = email
elif email is None:
error = "Sorry, but your social network (Facebook or Google)
needs to provide us your email address."
return HttpResponseRedirect(reverse('django.contrib.auth.views.login') + "?error=" + urllib.quote_plus(error))
else:
return redirect('require_email')
def save_profile(backend, details, response, uid,user, *args, **kwargs):
if backend.name == 'facebook':
url = "http://graph.facebook.com/%s/picture?type=large" % response['id']
avatar = urlopen(url)
profile = Profile.objects.filter(user_id=user.id)
if profile.count()==0:
profile = Profile(user_id=user.id)
else:
profile = Profile.objects.get(user_id=user.id)
profile.profile_image.save(slugify(user.username + " social") + '.jpg',
ContentFile(avatar.read()))
profile.save()
elif backend.name == 'google-oauth2':
if response.get('image') and response['image'].get('url'):
url = response['image'].get('url')
ext = url.split('.')[-1]
profile = Profile.objects.filter(user_id=user.id)
if profile.count()==0:
profile = Profile(user_id=user.id)
else:
profile = Profile.objects.get(user_id=user.id)
profile.profile_image.save(
'{0}.{1}'.format(user.username, ext),
ContentFile(urllib2.urlopen(url).read()),
save=False
)
profile.save()
And settings
SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.social_details',
'social.pipeline.social_auth.social_uid',
'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user',
'social.pipeline.social_auth.associate_by_email',
'social.pipeline.user.get_username',
'polls.pipeline.require_email',
'social.pipeline.user.create_user',
'polls.pipeline.save_profile',
'social.pipeline.social_auth.associate_user',
'social.pipeline.social_auth.load_extra_data',
)
enter image description here

It's very hard to give a correct answer based on the very limited amount of information you provided. I'll give it a try based on the screenshot you linked.
First, it seems there is an attempt to import save_status_to_session from social_core.pipeline.partial in file social/pipeline/partial.py. The import error is not surprising, as social_core.pipeline.partial does not define these this function (see https://github.com/python-social-auth/social-core/blob/master/social_core/pipeline/partial.py).
The file social/pipeline/partial.py seems to correspond to a module that is no longer maintained (see https://github.com/omab/python-social-auth/blob/master/social/pipeline/partial.py and the README at the root of the repository).
As you import that module in mysite/polls/pipeline.py, I suggest to replace your import from social.pipeline.partial import partial by from social_core.pipeline.partial import partial.

Related

ExtractionError: Can't extract file(s) to egg cache

I'm developing my app on Windows with GAE, but the below error message was shown.
C:\Python27\Lib\site-packages
Perhaps your account does not have write access to this directory? You can
change the cache directory by setting the PYTHON_EGG_CACHE environment
variable to point to an accessible directory.
So I checked some post in this site and I found some articles but I could not understand it. My understanding is that I need to create cache directory with write access in home directory, but I did not understand where "home directory" is.
Also in other post, I found the answer saying This approach solved my issue. I did uninstall pyyaml using pip and then installed it with easy_install -z pyyaml
Which approach is correct?
import webapp2
import os
import jinja2
import cloudstorage
import mimetypes
from PIL import Image
from google.appengine.ext import ndb
from google.appengine.ext import blobstore
from google.appengine.api import users
from google.appengine.api import app_identity
from google.appengine.api import images
from models import Note
from models import CheckListItem
from models import NoteFile
jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(os.path.dirname(__file__)))
images_formats = {
'0':'image/png',
'1':'image/jpeg',
'2':'image/webp',
'-1':'image/bmp',
'-2':'image/gif',
'-3':'image/ico',
'-4':'image/tiff',
}
class MainHandler(webapp2.RequestHandler):
def get(self):
user = users.get_current_user()
if user is not None:
logout_url = users.create_logout_url(self.request.uri)
template_context = {
'user': user.nickname(),
'logout_url' : logout_url,
}
template = jinja_env.get_template('main.html')
self.response.out.write(template.render(template_context))
else:
login_url = users.create_login_url(self.request.uri)
self.redirect(login_url)
def post(self):
user = users.get_current_user()
if user is None:
self.error(401)
bucket_name = app_identity.get_default_gcs_bucket_name()
uploaded_file = self.request.POST.get('uploaded_file')
file_name = getattr(uploaded_file,'filename',None)
file_content = getattr(uploaded_file,'file',None)
real_path = ''
if file_name and file_content:
content_t = mimetypes.guess_type(file_name)[0]
real_path = '/' + bucket_name + '/' + user.user_id() + "/" + file_name
with cloudstorage.open(real_path,'w',content_type=content_t,options={'x-goog-acl':'public-read'}) as f:
f.write(file_content.read())
self._create_note(user, file_name, real_path)
logout_url = users.create_logout_url(self.request.uri)
template_context = {
'user':user.nickname(),
'logout_url': logout_url,
}
self.response.out.write(self._render_template('main.html',template_context))
def _render_template(self,template_name,context=None):
if context is None:
context = {}
user = users.get_current_user()
ancestor_key = ndb.Key("User",user.nickname())
qry = Note.owner_query(ancestor_key)
context['notes'] = qry.fetch()
template = jinja_env.get_template(template_name)
return template.render(context)
#ndb.transactional
def _create_note(self,user,file_name,file_path):
note = Note(parent=ndb.Key("User", user.nickname()), title=self.request.get('title'), content=self.request.get('content'))
note.put()
item_titles = self.request.get('checklist_items').split(',')
for item_title in item_titles:
item = CheckListItem(parent=note.key, title=item_title)
item.put()
note.checklist_items.append(item.key)
if file_name and file_path:
url, thumbnail_url = self._get_urls_for(file_name)
f = NoteFile(parent=note.key, name=file_name, url=url,thumbnail_url=thumbnail_url,full_path=file_path)
f.put()
note.files.append(f.key)
note.put()
def _get_urls_for(self,file_name):
user = users.get_current_user()
if user is None:
return
bucket_name = app_identity.get_default_gcs_bucket_name()
path = '/' + bucket_name + '/' + user.user_id() + '/' + file_name
real_path = '/gs' + path
key = blobstore.create_gs_key(real_path)
try:
url = images.get_serving_url(key, size=0)
thumbnail_url = images.get_serving_url(key,size=150,crop=True)
except images.TransformationError,images.NotImageError:
url = "http://storage.googleapis.com{}".format(path)
thumbnail_url = None
return url,thumbnail_url
class MediaHandler(webapp2.RequestHandler):
def get(self,file_name):
user = users.get_current_user()
bucket_name = app_identity.get_default_gcs_bucket_name()
content_t = mimetypes.guess_type(file_name)[0]
real_path = '/' + bucket_name + '/' + user.user_id() + '/' + file_name
try:
with cloudstorage.open(real_path,'r')as f:
self.response.headers.add_header('Content-Type',content_t)
self.response.out.write(f.read())
except cloudstorage.errors.NotFoundError:
self.abort(404)
class ShrinkHandler(webapp2.RequestHandler):
def _shrink_note(self,note):
for file_key in note.files:
file = file_key.get() # this is the same as "file.get().url" in html file. we add the comment.
try:
with cloudstorage.open(file.full_path) as f:
image = images.Image(f.read())
image.resize(640)
new_image_data = image.execute_transforms()
content_t = images_format.get(str(image.format))
with cloudstorage.open(file.full_path,'w',content_type=content_t) as f:
f.write(new_image_data)
except images.NotImageError:
pass
def get(self):
user = users.get_current_user()
if user is None:
login_url = users.create_login_url(self.request.url)
return self.redirect(login_url)
ancestor_key = ndb.Key("User",user.nickname())
notes = Note.owner_query(ancestor_key).fetch()
for note in notes:
self._shrink_note(note)
self.response.write('Done.')
app = webapp2.WSGIApplication([
(r'/', MainHandler),
(r'/media/(?P<file_name>[\w.]{0,256})',MediaHandler),
(r'/shrink',ShrinkHandler)
], debug=True)
It looks like you're developing a standard env GAE app but you're attempting to install third party libraries in (and use them from) your local system's site packages. This won't work.
You need to install the third party libraries in your app's library directory (i.e. using -t <your_lib_dir> option for pip install, for which you shouldn't need special permissions. See also:
Using third-party libraries.
No module named warnings when starting GAE inside virtualenv locally

How do I assign specific users to a user-uploaded file so they can modify it/delete it (Django + Apache)

Im using django 1.10 + Apache in Linux.
I've created a small webapp to upload documents (with dropzone.js) and want to implement the ability for a user to specify who can view/modify/delete a specific file but i can't figure out a way how. I attempted using a ManyToManyField but maybe im not understading the Field itself correctly.
The "Document" model is this:
Model
class Document(models.Model):
file = models.FileField(upload_to = 'files/')
#validators=[validate_file_type])
uploaded_at = models.DateTimeField(auto_now_add = True)
extension = models.CharField(max_length = 30, blank = True)
thumbnail = models.ImageField(blank = True, null = True)
is_public = models.BooleanField(default = False)
accesible_by = models.ManyToManyField(User) #This is my attempt at doing this task.
def clean(self):
self.extension = self.file.name.split('/')[-1].split('.')[-1]
if self.extension == 'xlsx' or self.extension == 'xls':
self.thumbnail = 'xlsx.png'
elif self.extension == 'pptx' or self.extension == 'ppt':
self.thumbnail = 'pptx.png'
elif self.extension == 'docx' or self.extension == 'doc':
self.thumbnail = 'docx.png'
def delete(self, *args, **kwargs):
#delete file from /media/files
self.file.delete(save = False)
#call parent delete method.
super().delete(*args, **kwargs)
#Redirect to file list page.
def get_absolute_url(self):
return reverse('dashby-files:files')
def __str__(self):
return self.file.name.split('/')[-1]
class Meta():
ordering = ['-uploaded_at']
My View to handle the creation of documents:
View
class DocumentCreate(CreateView):
model = Document
fields = ['file', 'is_public']
def form_valid(self, form):
self.object = form.save(commit = False)
## I guess here i would Add the (self.request.user) to the accesible_by Field.
self.object.save()
data = {'status': 'success'}
response = JSONResponse(data, mimetype =
response_mimetype(self.request))
return response
Thanks in advance to anyone for any ideas or suggestions...
You have a model and a view that hopefully works for adding new documents, you still have a number of steps to go.
You'll need a place to assign users that can view/modify/delete your files. If you need to store access levels (view/delete...), your accessible_by will not suffice and you'll do well with a through table to add more information like access level.
You need to write views for various actions like view, delete... that users will request and here you ensure users have the right privileges. An implementation would be to get the request.user and the document id, look up if the user has the permission for what she's doing, return an http unauthorized exception or allow the action to proceed.
Edit: My question is about how can I assign user-permissions to each
individual file
If we're keeping this to access control from the django level, using the document model you already have, and you've taken some steps and for every document, you can assign users (accessible_by). Something like this can get you started:
from django.core.exceptions import PermissionDenied
def view_document(request, doc_pk):
doc = get_object_or_404(Document, pk=doc_pk)
if not doc.accessible_by.filter(username=request.user.username):
raise PermissionDenied
#perform rest of action
Or do you mean to use the permissions framework itself?

Django redirect/call with parameter from another function

I'm building application with custom python-social-auth pipline for logining via facebook.
The situation is so simple, I need to redirect user from non-view function to url with parameter.
Here is my related urls:
url(r'^.*', login, name = 'login'),
url(r'^logout/.*', logout, name = 'FBAuth.views.logout'),
url(r'^/new_user/.*', login, {'new_user':1}, name = 'new_user' ),
url(r'^succeeded/.*', login, {'new_user':2}, name = 'succeeded' ),
from views.py:
def login(request, new_user=None):
logger.debug("I'm in login view, new_user = %s", new_user)
message = 'Welcome to application!'
if new_user:
if new_user == 1: #new one
message = 'Wellcome to our app! Thanks for registration'
else:
if new_user == 2: #loggined
message = "Successfully logged in"
else:
message = new_user
context = RequestContext(request, {
'request': request, 'user': request.user, 'message' : message})
return render_to_response('login.html', context_instance=context)
custom.py:
def check_if_exists(strategy, request, *args, **kwargs):
login_type = strategy.request.GET.get('login_type')
if kwargs['is_new']:
...
some code
...
else:
#if login_type == 2:
#raise AuthAlreadyAssociated #need to add message
new_user = 1
#return redirect('/new_user/')
#return redirect('/new_user/', {'new_user' : new_user} )
return login(new_user=1)
#return redirect(reverse('new_user'))
#reverse('FBAuth.views.login', kwargs={'new_user' : new_user} ) #, new_user=new_user) #, args =(new_user,))
#reverse(redirect_uri, args=(backend,))
return None
Here is my auth pipeline:
SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.social_details',
'social.pipeline.social_auth.social_uid',
'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user',
'FBAuth.facebook.check_if_exists',
'social.pipeline.user.get_username',
'social.pipeline.user.create_user',
'social.pipeline.social_auth.associate_user',
'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.user_details',
)
The pipelene cals by url:
href="{% url 'social:begin' 'facebook' %}?next={{ request.path }}&login_type={{1}}"
I tried a million variants, nothing works. Redirection always fails or I get new_user=None in my view.
Please, help me to find some way to pass my parameter.
Note: I also tried:
return redirect('/new_user/1/')
and
return redirect('/new_user/?new_user=1/')
for the url:
url(r'^/new_user/(?P<new_user>)/$', login, name = 'new_user' ),
The page is opened, but no message (new_user in None)
I think the issue is in the way you are handling urls.
url(r'^/new_user/(?P<new_user>)/$', login, name = 'new_user' )
While redirecting use this.
return redirect('/new_user/1/')
This is not tested. Hope this helps.

Partial Pipeline to ask user's phone number

I am creating a partial pipeline to get user's phone number on signup and skip the step on subsequent logins. My partial pipeline looks like this:
#partial
def other_info(strategy, details, user=None, is_new=False, *args, **kwargs):
if is_new or not details.get('email'):
request = kwargs['request']
return redirect('require_phone')
else:
return
On the page-welcome.html there is a form. Corresponding view looks like this:
def require_phone(request):
if request.method == 'POST':
phone = request.POST.get('phone',None)
user = User.objects.get(username = request.user.username)
if phone is not None:
up = UserProfile.objects.get_or_create(user=request.user,
phone = phone)
up.save()
backend = request.session['partial_pipeline']['backend']
return redirect('social:complete', backend=backend)
else:
return render(request,'app/page-welcome.html')
The problem is, the request object is not passed correctly to the view and hence the user shows anonymous. I am not able to access user object and hence cannot save phone no.
You might be able to get the user with
user = User.objects.get(id=request.session['partial_pipeline']['kwargs']['user'])
and then update this object, instead of trying to get it from the request (which will not work during the pipeline).

Using tastypie resource in view

my first question here :
So I'm using tastypie to have api's for my app.
I want to be able to use tastypie to render json and then include that in a django view so that I can bootstrap my app's data.
There is an example of this in django tastypie cookbook here : http://django-tastypie.readthedocs.org/en/latest/cookbook.html#using-your-resource-in-regular-views
The problem is that I CANNOT get this to work, I've tried variants from simpler to more complex and I just cant get it, here some code for my models :
class ChatMessage(models.Model):
content = models.TextField()
added = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(ChatUser, related_name="messages")
chat_session = models.ForeignKey(ChatSession, related_name="messages")
answer_to = models.ForeignKey('self', blank=True, null=True)
flagged = models.BooleanField(blank=True,default=False)
mododeleted = models.BooleanField(blank=True,default=False)
mododeleted_by = models.ForeignKey(ChatUser,blank=True,null=True,default=None)
mododeleted_at = models.DateTimeField(blank=True,null=True,default=None)
[...]
class ChatSession (models.Model):
title = models.CharField(max_length=200)
link_title = models.CharField(max_length=200)
description = tinymce_models.HTMLField()
date = models.DateTimeField()
online = models.BooleanField(default=False)
next_session = models.BooleanField(default=False)
meps = models.ManyToManyField(ChatMep)
uid_newsupdate = models.CharField(max_length=200,blank=True,null=True,default="")
[...]
and my resources :
class ChatMessageResource(MyModelResource):
chat_session = fields.ForeignKey(ChatSessionResource, 'chat_session')
def renderOne(self,request,pkval):
data = self.obj_get(None,pk=pkval)
dbundle = self.build_bundle(obj=data,request=request)
return self.serialize(None,self.full_dehydrate(dbundle),'application/json')
def dehydrate(self, bundle):
bundle.data['likes'] = bundle.obj.get_likes()
bundle.data['likes_count'] = len(bundle.data['likes'])
return bundle
class Meta:
authentication = Authentication()
authorization = Authorization()
queryset = ChatMessage.objects.all()
resource_name = 'message'
fields = ('content', 'added', 'flagged', 'mododeleted','author','answer_to','chat_session')
filtering = {
'chat_session': ALL_WITH_RELATIONS,
}
and my view index :
def index(request):
cur_sess = get_current_chat_session()
data1= ChatMessageResource().renderOne(request,723)
return render_to_response('test.html',
{
'all_data' : data1
},
context_instance=RequestContext(request))
What I want is my renderOne() function to give me the json of ONE ChatMessageResource
And also I'd like a renderAll() function to gice me ALL (or filtered) ChatMessageResources in json.
And I want to use tastypie internals, I KNOW i could serialize it by myself but that's not the point..
Right now the error is :
NoReverseMatch at /live/
Reverse for 'api_dispatch_detail' with arguments '()' and keyword arguments '{'pk': 14L, 'resource_name': 'session'}' not found.
I'm just getting crazy, I've been trying for hours.
So please, how to get ONE/ALL resource as JSON by code using tastypie in a django view !
If It's not clear or I need to clarify, please just ask, thanks
Really what I want to do is to be able to get the JSON returned by an API url I created, but from code, not by visiting the url .. So If I have /api/v1/messages/?chat_session=14 which return a list of messages, I want to be able to do the same by code (and not by fetching the url with curl or something please).
Note :
definition of ModelResource.obj_get from https://github.com/toastdriven/django-tastypie/blob/master/tastypie/resources.py
def obj_get(self, request=None, **kwargs):
"""
A ORM-specific implementation of ``obj_get``.
Takes optional ``kwargs``, which are used to narrow the query to find
the instance.
"""
try:
base_object_list = self.get_object_list(request).filter(**kwargs)
object_list = self.apply_authorization_limits(request, base_object_list)
stringified_kwargs = ', '.join(["%s=%s" % (k, v) for k, v in kwargs.items()])
if len(object_list) <= 0:
raise self._meta.object_class.DoesNotExist("Couldn't find an instance of '%s' which matched '%s'." % (self._meta.object_class.__name__, stringified_kwargs))
elif len(object_list) > 1:
raise MultipleObjectsReturned("More than '%s' matched '%s'." % (self._meta.object_class.__name__, stringified_kwargs))
return object_list[0]
except ValueError:
raise NotFound("Invalid resource lookup data provided (mismatched type).")
So here I found the solution, the problem was with url resolving ... I needed to add
def get_resource_uri(self, bundle_or_obj):
return '/api/v1/%s/%s/' % (self._meta.resource_name,bundle_or_obj.obj.id)
to the related object (session here) in order for it to work (don't ask why!)
So here is my working solution for renderDetail and renderList :
def renderDetail(self,pkval):
request = HttpRequest()
request.GET = {'format': 'json'}
resp = self.get_detail(request, pk=pkval)
return resp.content
def renderList(self,options={}):
request = HttpRequest()
request.GET = {'format': 'json'}
if len(options) > 0:
request.GET.update(options)
resp = self.get_list(request)
return resp.content
And here is an example usage :
cmr = ChatMessageResource()
dataOne= cmr.renderDetail("723")
dataAll = cmr.renderList({'limit':'0','chat_session':cur_sess.pk})
https://github.com/toastdriven/django-tastypie/issues/962
I've found that obj_get method needs a bundled request object. See the link.
def user_detail(request, username):
ur = UserResource()
# Add this request bundle to the obj_get() method as shown.
req_bundle = ur.build_bundle(request=request)
user = ur.obj_get(req_bundle, username=username)
....
Your problem seems to be here:
data = self.obj_get(None,pk=pkval)
The parameters to obj_get should be kwargs that can be passed directly to a standard get. None should not be in there.

Categories

Resources