Django, Howto connect (and extent) facebook and django-userena or similar - django

It's been explicitly written in Django-facebook that they recommend it to be used with Userena:
We recommend using Django Userena. It seems easier to work with than
Django Registration. Both are supported and good packages though. To
use django userena simply point to the userena compatability layer.
AUTH_PROFILE_MODULE = 'django_facebook.FacebookProfile'
My question comes from AUTH_PROFILE_MODULE = 'django_facebook.FacebookProfile' part.
I have developed my own UserProfile in Userena and also inherited some system Actors like Student and Tutors based upon their own needs. so my setting is something like this:
AUTH_PROFILE_MODULE = 'profiles.UserProfile'
Within the django-facebook there is also an awesome example project that has written for mixing userena and django-facebook settings. But my problem still exists..
Should I replace my own code with facebook's one ??
This is my code :
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from django.db.models import permalink
from userena.models import UserenaBaseProfile
from courses.models import Course
class UserProfile(UserenaBaseProfile):
user = models.OneToOneField(User, unique=True, verbose_name=_('user'), related_name='user_profile')
department = models.ForeignKey('Department' , null = True , blank = True , related_name=_('user'))
name = models.CharField(max_length = 100)
birthday = models.DateField()
def __unicode__(self):
return self.name
class Student(UserProfile):
courses = models.ManyToManyField(Course , null = True, blank = True, related_name = _('student'))
Thanks beforehand ..

Just add the fields required for Facebook to your existing profile.
class UserProfile(UserenaBaseProfile, FacebookProfileModel):
....
(https://docs.djangoproject.com/en/dev/topics/db/models/#model-inheritance)

Related

Why do I have to reference the user model this way

I was working on a Django project and I was trying to do something like this to make sure that my model worked no matter what user model is set.
from django.contrib.auth import get_user_model
class Item(models.Model):
title = models.CharField(max_length=100, )
description = models.TextField()
seller = models.ForeignKey(get_user_model())
However when I did this it resulted in errors telling me the user model couldn't be accessed so I had to change it to this
from django.conf import settings
class Item(models.Model):
title = models.CharField(max_length=100, )
description = models.TextField()
seller = models.ForeignKey(settings.AUTH_USER_MODEL)
This works fine but I thought I have done this in the past using the first method. The only difference that time being that I was using a custom user model. They both seem like they are doing the same thing to me so why do I have to use the second method? And does get_user_model() not work with the default user?
This is the source code of the get_user_model() in django:
def get_user_model():
"""
Returns the User model that is active in this project.
"""
from django.db.models import get_model
try:
app_label, model_name = settings.AUTH_USER_MODEL.split('.')
except ValueError:
raise ImproperlyConfigured("AUTH_USER_MODEL must be of the form 'app_label.model_name'")
user_model = get_model(app_label, model_name)
if user_model is None:
raise ImproperlyConfigured("AUTH_USER_MODEL refers to model '%s' that has not been installed" % settings.AUTH_USER_MODEL)
return user_model
As you can see, it pulls the AUTH_USER_MODEL variable from your settings as you do but extracting the app_label and the user class itself. If it does not work you should see one of the two errors in the terminal when this call is done.
I think your answer lies in the Django source. It depends on your setup what happens. Older versions might do it a bit differently.

Django social_auth custom user model FacebookBackend explanation

I'm trying to use social_auth (omab) for the first time and I'm find that there is no working example how to store basic facebook user data. Authentication works and user is created without problem as it's explained in the social_auth docs but I need to store gender and locale also. Both of them belongs to the basic facebook user data so they are in the facebook response all the time.
I'm use Django 1.4, Python2.7 and latest social_auth. So I was try to use SOCIAL_AUTH_USER_MODEL = 'myapp.UserProfile' in settings.py file and model.py is:
#!/usr/bin/python
#-*- coding: UTF-8 -*-
from django.db import models
from django.contrib.auth.models import User
from django.db.models import signals
import datetime
from datetime import timedelta
from django.db.models.signals import post_save
from social_auth.signals import pre_update
from social_auth.backends.facebook import FacebookBackend
class CustomUserManager(models.Manager):
def create_user(self, username, email):
return self.model._default_manager.create(username=username)
class UserProfile(models.Model):
gender = models.CharField(max_length=150, blank=True)
locale = models.CharField(max_length=150, blank=True)
#social_auth requirements
username = models.CharField(max_length=150)
last_login = models.DateTimeField(blank=True)
is_active = models.BooleanField()
objects = CustomUserManager()
class Meta:
verbose_name_plural = 'Profiles'
def __unicode__(self):
return self.username
def get_absolute_url(self):
return '/profiles/%s/' % self.id
def facebook_extra_values(sender, user,response, details, **kwargs):
profile = user.get_profile()
current_user = user
profile, new = UserProfile.objects.get_or_create(user=current_user)
profile.gender = response.get('gender')
profile.locale = response.get('locale')
profile.save()
return True
pre_update.connect(facebook_extra_values, sender=FacebookBackend, weak = False, dispatch_uid = 'facebook_extra_values_user')
In the settings.py I'm define pipeline
SOCIAL_AUTH_PIPELINE = (
'social_auth.backends.pipeline.social.social_auth_user',
#'social_auth.backends.pipeline.associate.associate_by_email',
'social_auth.backends.pipeline.user.create_user',
'social_auth.backends.pipeline.social.associate_user',
'social_auth.backends.pipeline.social.load_extra_data',
'social_auth.backends.pipeline.user.update_user_details',
'social_auth.backends.pipeline.misc.save_status_to_session',
)
but with above I get error AssertionError: ForeignKey(None) is invalid. First parameter to ForeignKey must be either a model, a model name, or the string 'self'
Also I was try to use AUTH_PROFILE_MODULE = 'myapp.UserProfile' instead as I was do before to extend user.model, which works well but don't understand how to populate needed data when UserProfile is created. Does anyone can place working code for this problem?
Thanks
There are a couple of ways to archive it, what fits better to your project is up to you of course, here's a list of available options:
Define this setting FACEBOOK_EXTRA_DATA = ('gender', 'locale'), the values will be available at the UserSocialAuth instance, to get them just do user.social_auth.get(provider='facebook').extra_data['gender'] or ['locale']. This is possible just because the information is available in the basic user data response.
Use a user profile to store this data (check django doc about it). Then just add a pipeline entry that stores the values in your profile instance.
Create a custom user model, SOCIAL_AUTH_USER_MODEL = 'myapp.CustomUser', and again add a custom pipeline entry that stores the values in your user instance.
Number 1 is not the best solution IMO, since a user can have several Facebook accounts connected and it could create a mess. Number 2 is good for Django 1.4 and lower, but it's deprecated starting from Django 1.5, something to take into account. Number 3 is a bit messy IMO.

Custom content type appears with an empty option in the admin "add type of page" page in mezzanine

I am doing a small blog in Mezzanine for learning purpose and wanted to add a custom content type by sub-classing "mezzanine.pages.models.Page" and registering this model with admin. My classes look something like this:
models.py:
from django.db import models
from mezzanine.pages.models import Page
class Student(Page):
dob = models.DateField("Date of birth")
name = models.CharField("Name", max_length=30)
gender = models.CharField("Gender", max_length = 5, choices=(('M','Male'),
('F','Female')), default = 'M')
image = models.ImageField(upload_to='Students')
class Project(models.Model):
student = models.ForeignKey("Student")
project_image = models.ImageField(upload_to="StudentProjects")
admin.py:
from copy import deepcopy
from django.contrib import admin
from mezzanine.pages.admin import PageAdmin
from .models import Student, Project
student_extra_fieldsets = ((None, {"fields": ("dob","name","gender","image")}),)
class ProjectInline(admin.TabularInline):
model = Project
class StudentAdmin(PageAdmin):
inlines = (ProjectInline,)
fieldsets = deepcopy(PageAdmin.fieldsets) + student_extra_fieldsets
admin.site.register(Student, StudentAdmin)
Now, when I visit "http://localhost:8000/admin/pages/page/" to add my newly registered content type, I get an empty option with no name, but when I select I get the Custom Content type "Student" Page to add and edit.
Since I have just started with Django and Mezzanine, I cannot simply figure it out.
I am using "sqlite" as backend and not using "South"
Any pointers to this??
Thanx for your help :)
I removed that "*name = models.CharField("Name", max_length=30)*" in models.py and replaced it with:
first_name = models.CharField("First Name", max_length=30)
last_name = models.CharField("Last Name", max_length=30)
And now every thing seems OK!!. (Only if I used "South"

Django multiple User profiles/subprofiles

I am trying to create an intranet/extranet with internal/external user-specific profiles, with a common generic profile. I've looked at several answers on this site, but none specifically address what I'm looking to do. Below are the (stripped down) files I have so far.
What's the best way to create a profile model, with subprofiles for each user type? I'm trying not to require a custom authentication backend if at all possible.
https://gist.github.com/1196077
I have a solution I dont Know if its the best but see it:
models.py
from django.db import models
from django.contrib.auth.models import User
class Pollster(models.Model):
"""docstring for Polister"""
user = models.OneToOneField(User, related_name = 'polister', unique=True)
cedule = models.CharField( max_length = 100 )
class Respondent(models.Model):
""" """
born_date = models.DateField( verbose_name=u'fecha de nacimiento' )
cedule = models.CharField( max_length = 100, verbose_name=u'cedula' )
comunity = models.CharField( max_length = 100, verbose_name=u'comunidad')
phone = models.CharField( max_length = 50, verbose_name=u'telefono')
sanrelation = models.TextField( verbose_name =u'Relacion con SAN')
user = models.OneToOneField( User, related_name = 'respondent')
I create a MiddleWare: so
i create middleware.py
from django.contrib.auth.models import User
from encuestas.models import Pollster, Respondent
class RequestMiddleWare(object):
"""docstring for """
def process_request(self,request):
if isPollster(request.user):
request.user.userprofile = Pollster.objects.get( user = request.user.id)
elif isRespondent(request.user):
request.user.userprofile = Respondent.objects.get(user = request.user.id)
return None
def isPollster(user):
return Pollster.objects.filter(user=user.id).exists()
def isRespondent(user):
return Respondent.objects.filter(user=user.id).exists()
and you need to configure settings.py for the middleware:
add to MIDDLEWARE_CLASSES atribute:
'encuestas.middleware.RequestMiddleWare'
encuestas is my_app name
middleware is the Middleware file
RequestMiddleWare is the middleware class
You need a combination of storing additional information about users and model inheritance.
Basically, you'll need the generic User models we all know and either love or hate, and then you need a generic profile model that is your AUTH_PROFILE_MODULE setting.
That profile model will be a top-level model, with model subclasses for internal and extrernal users. You probably don't want an abstract model in this case since you'll need a common profile table to load user profiles from with User.get_profile().
So...I think the major thing you want to change is to make your Associate, External, etc. models inherit from your Profile model.
Please check this excellent article that describes how to inherit from the User class and add your own information. For me, at least, this clearly seems to be the way to go: http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/
Using this method one should easily be able to add multiple user types to their Django application.

Django: NameError 'Business' is not defined

Not sure what is causing this error. Please help
NameError at /dash/
name 'Business' is not defined
Exception Location: /home/src/common/models.py in ImageBank, line 38
Here's the model:
class Business(models.Model):
business_type = models.ManyToManyField(BusinessType)
business_service_type = models.ManyToManyField(ServiceType)
establishment_type = models.ForeignKey(EstablishmentType)
logo = models.ForeignKey(ImageBank)
phone = PhoneNumberField()
address = models.ForeignKey(Address)
website = models.URLField()
name = models.CharField(max_length=64)
def __unicode__(self):
return self.name
The View:
def dashview(request):
coupon = Coupon.objects.filter()
bdnspk = request.user.id
user = request.user.username
bdns = Business.objects.values('name').get(id=bdnspk)
context = {
'coupon':coupon,
'bdns':bdns,
'user':user
}
return render_to_response(
'dash/dash.html',
{},
context,
context_instance = RequestContext(request),
)
EDIT: my models is located in /home/src/common/models.py but my django app is in /home/proj/site/ How do I import that?
ImageBank model:
class ImageBank(models.Model):
business = models.ForeignKey('Business')
image = models.ImageField(upload_to="images/bank")
def url(self):
return self.image.url
Please look at your error: Exception Location: /home/src/common/models.py in ImageBank, line 38 the problem exists in the ImageBank class, which you also seem to be using a ForeignKey reference to in the logo field.
I'm assuming that what the issue is is that you are referencing Business before it is defined as something like a ForeignKey reference inside a field in ImageBank. If this is the case, is ImageBank defined before the Business model inside your models.py? Because doing so will throw this error. The proper way of doing circular ForeignKey references would be to enforce a single ForeignKey with a unique constraint.
Django has this concept built in as a type of field called a OnetoOne field. Have you looked into using a OnetoOne field? See: http://docs.djangoproject.com/en/dev/ref/models/fields/#onetoonefield
Did you import the models in the view? Something like:
from models import Business
at the beginning of the view file
You forgot to import the model in the view, or you're referring to it incorrectly.
If that model is in an app you wrote:
Make sure that the app is listed in INSTALLED_APPS in your settings.py
#settings.py
INSTALLED_APPS = (
'django....',
... more defaults ...,
'myproject.appname',
)
and at the top of your views
#views.py
from appname.models import Business
#or import all models from that app
from appname.models import *
You are making things a lot more complicated on yourself by having your models.py in a strange unrelated location.
Models can only be imported from python modules so you'll need to make sure that your models.py is in a directory that is a python module and that it is on the python path.
You'll be a whole lot better of just putting your models into an app in your project rather than trying to do something like you are.
More or less you're working against the grain and python is a lot nicer if you work with the grain.