Django中social_django对接Google OAuth2:用户信息来源与存储问题
Hey there! Let's tackle your two questions about social_django and Google OAuth since you're already halfway set up. I've been through this exact setup before, so let's break it down clearly.
The process is handled automatically by the social_core.backends.google.GoogleOAuth2 backend that social_django uses—here's the step-by-step flow:
- When a user clicks your Google login button,
social_djangoredirects them to Google's authorization page. - After the user grants permission, Google sends an authorization code back to your app.
social_djangotakes that code and exchanges it for an access token from Google's token endpoint.- With the access token,
social_djangomakes a request to Google's User Info API (default endpoint:https://www.googleapis.com/oauth2/v3/userinfo) to pull the user's public data (name, email, avatar URL, etc.). - All this fetched data gets stored in the
extra_datafield of theSocialAuthmodel (linked to your user). You can access it in views like this:# Inside a view where user is authenticated social_user = request.user.social_auth.get(provider='google-oauth2') user_data = social_user.extra_data # user_data will have keys like 'email', 'name', 'picture'
The cleanest way to handle this is using social_django's pipeline system—it lets you hook into the authentication flow to run custom code after a user logs in. Here are two common approaches:
Option 1: Extend the default User model
If you're using a custom User model (recommended for Django 1.10+), add the avatar field directly to it:
# models.py from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): avatar_url = models.URLField(blank=True, null=True)
Don't forget to update your settings.py to use this model:
AUTH_USER_MODEL = 'your_app_name.CustomUser'
Then create a pipeline.py file in your app to handle saving the data:
# pipeline.py def save_user_details(backend, user, response, *args, **kwargs): # Only run this for Google OAuth if backend.name == 'google-oauth2': # Pull data from Google's response user.email = response.get('email') user.username = response.get('given_name') # Or use 'name' for full name user.avatar_url = response.get('picture') user.save()
Add this pipeline step to your settings.py (append it to the default pipeline):
SOCIAL_AUTH_PIPELINE = ( # Default pipeline steps (keep these) 'social_core.pipeline.social_auth.social_details', 'social_core.pipeline.social_auth.social_uid', 'social_core.pipeline.social_auth.auth_allowed', 'social_core.pipeline.social_auth.social_user', 'social_core.pipeline.user.get_username', 'social_core.pipeline.user.create_user', 'social_core.pipeline.social_auth.associate_user', 'social_core.pipeline.social_auth.load_extra_data', 'social_core.pipeline.user.user_details', # Your custom step 'your_app_name.pipeline.save_user_details', )
Option 2: Use a separate Profile model
If you don't want to extend the User model, create a one-to-one Profile model to store the avatar:
# models.py from django.contrib.auth.models import User from django.db import models class UserProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) avatar_url = models.URLField(blank=True, null=True) def __str__(self): return self.user.username
Update your pipeline function to create/update the profile:
# pipeline.py def save_user_profile(backend, user, response, *args, **kwargs): if backend.name == 'google-oauth2': # Get or create the profile for the user profile, created = UserProfile.objects.get_or_create(user=user) profile.avatar_url = response.get('picture') profile.save() # Update User model fields too user.email = response.get('email') user.username = response.get('given_name') user.save()
Add this pipeline step to your settings.py just like in Option 1.
Either way, the pipeline will run every time a user logs in with Google, ensuring their data stays up-to-date if they change their Google profile info.
内容的提问来源于stack exchange,提问作者Piyush Jiwane

