Skip to content

Commit f4e727a

Browse files
committed
working on foreignkey django examples
1 parent 80e2085 commit f4e727a

2 files changed

Lines changed: 10 additions & 224 deletions

File tree

content/pages/examples/django/django-db-models-foreignkey.markdown

Lines changed: 9 additions & 223 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ from django.contrib.auth import authenticate
293293
from django.contrib.sites.models import Site
294294
from django.contrib.sites.shortcuts import get_current_site
295295
from django.core.exceptions import PermissionDenied
296-
from django.db import models
296+
~~from django.db import models
297297
from django.utils.crypto import get_random_string
298298

299299
import allauth.app_settings
@@ -312,60 +312,13 @@ from .adapter import get_adapter
312312
from .fields import JSONField
313313

314314

315-
class SocialAppManager(models.Manager):
316-
def get_current(self, provider, request=None):
317-
cache = {}
318-
if request:
319-
cache = getattr(request, '_socialapp_cache', {})
320-
request._socialapp_cache = cache
321-
app = cache.get(provider)
322-
if not app:
323-
site = get_current_site(request)
324-
app = self.get(
325-
sites__id=site.id,
326-
provider=provider)
327-
cache[provider] = app
328-
return app
329-
330-
331-
@python_2_unicode_compatible
332-
class SocialApp(models.Model):
333-
objects = SocialAppManager()
334-
335-
provider = models.CharField(verbose_name=_('provider'),
336-
max_length=30,
337-
choices=providers.registry.as_choices())
338-
name = models.CharField(verbose_name=_('name'),
339-
max_length=40)
340-
client_id = models.CharField(verbose_name=_('client id'),
341-
max_length=191,
342-
help_text=_('App ID, or consumer key'))
343-
secret = models.CharField(verbose_name=_('secret key'),
344-
max_length=191,
345-
help_text=_('API secret, client secret, or'
346-
' consumer secret'))
347-
key = models.CharField(verbose_name=_('key'),
348-
max_length=191,
349-
blank=True,
350-
help_text=_('Key'))
351-
# Most apps can be used across multiple domains, therefore we use
352-
# a ManyToManyField. Note that Facebook requires an app per domain
353-
# (unless the domains share a common base name).
354-
# blank=True allows for disabling apps without removing them
355-
sites = models.ManyToManyField(Site, blank=True)
356-
357-
class Meta:
358-
verbose_name = _('social application')
359-
verbose_name_plural = _('social applications')
360-
361-
def __str__(self):
362-
return self.name
315+
## ... source file abbreviated to get to ForeignKey examples ...
363316

364317

365318
@python_2_unicode_compatible
366319
class SocialAccount(models.Model):
367-
user = models.ForeignKey(allauth.app_settings.USER_MODEL,
368-
on_delete=models.CASCADE)
320+
~~ user = models.ForeignKey(allauth.app_settings.USER_MODEL,
321+
~~ on_delete=models.CASCADE)
369322
provider = models.CharField(verbose_name=_('provider'),
370323
max_length=30,
371324
choices=providers.registry.as_choices())
@@ -401,8 +354,8 @@ class SocialAccount(models.Model):
401354
def authenticate(self):
402355
return authenticate(account=self)
403356

404-
def __str__(self):
405-
return force_str(self.user)
357+
~~ def __str__(self):
358+
~~ return force_str(self.user)
406359

407360
def get_profile_url(self):
408361
return self.get_provider_account().get_profile_url()
@@ -419,8 +372,8 @@ class SocialAccount(models.Model):
419372

420373
@python_2_unicode_compatible
421374
class SocialToken(models.Model):
422-
app = models.ForeignKey(SocialApp, on_delete=models.CASCADE)
423-
account = models.ForeignKey(SocialAccount, on_delete=models.CASCADE)
375+
~~ app = models.ForeignKey(SocialApp, on_delete=models.CASCADE)
376+
~~ account = models.ForeignKey(SocialAccount, on_delete=models.CASCADE)
424377
token = models.TextField(
425378
verbose_name=_('token'),
426379
help_text=_(
@@ -442,174 +395,7 @@ class SocialToken(models.Model):
442395
return self.token
443396

444397

445-
class SocialLogin(object):
446-
"""
447-
Represents a social user that is in the process of being logged
448-
in. This consists of the following information:
449-
450-
`account` (`SocialAccount` instance): The social account being
451-
logged in. Providers are not responsible for checking whether or
452-
not an account already exists or not. Therefore, a provider
453-
typically creates a new (unsaved) `SocialAccount` instance. The
454-
`User` instance pointed to by the account (`account.user`) may be
455-
prefilled by the provider for use as a starting point later on
456-
during the signup process.
457-
458-
`token` (`SocialToken` instance): An optional access token token
459-
that results from performing a successful authentication
460-
handshake.
461-
462-
`state` (`dict`): The state to be preserved during the
463-
authentication handshake. Note that this state may end up in the
464-
url -- do not put any secrets in here. It currently only contains
465-
the url to redirect to after login.
466-
467-
`email_addresses` (list of `EmailAddress`): Optional list of
468-
e-mail addresses retrieved from the provider.
469-
"""
470-
471-
def __init__(self, user=None, account=None, token=None,
472-
email_addresses=[]):
473-
if token:
474-
assert token.account is None or token.account == account
475-
self.token = token
476-
self.user = user
477-
self.account = account
478-
self.email_addresses = email_addresses
479-
self.state = {}
480-
481-
def connect(self, request, user):
482-
self.user = user
483-
self.save(request, connect=True)
484-
485-
def serialize(self):
486-
serialize_instance = get_adapter().serialize_instance
487-
ret = dict(account=serialize_instance(self.account),
488-
user=serialize_instance(self.user),
489-
state=self.state,
490-
email_addresses=[serialize_instance(ea)
491-
for ea in self.email_addresses])
492-
if self.token:
493-
ret['token'] = serialize_instance(self.token)
494-
return ret
495-
496-
@classmethod
497-
def deserialize(cls, data):
498-
deserialize_instance = get_adapter().deserialize_instance
499-
account = deserialize_instance(SocialAccount, data['account'])
500-
user = deserialize_instance(get_user_model(), data['user'])
501-
if 'token' in data:
502-
token = deserialize_instance(SocialToken, data['token'])
503-
else:
504-
token = None
505-
email_addresses = []
506-
for ea in data['email_addresses']:
507-
email_address = deserialize_instance(EmailAddress, ea)
508-
email_addresses.append(email_address)
509-
ret = cls()
510-
ret.token = token
511-
ret.account = account
512-
ret.user = user
513-
ret.email_addresses = email_addresses
514-
ret.state = data['state']
515-
return ret
516-
517-
def save(self, request, connect=False):
518-
"""
519-
Saves a new account. Note that while the account is new,
520-
the user may be an existing one (when connecting accounts)
521-
"""
522-
assert not self.is_existing
523-
user = self.user
524-
user.save()
525-
self.account.user = user
526-
self.account.save()
527-
if app_settings.STORE_TOKENS and self.token:
528-
self.token.account = self.account
529-
self.token.save()
530-
if connect:
531-
# TODO: Add any new email addresses automatically?
532-
pass
533-
else:
534-
setup_user_email(request, user, self.email_addresses)
535-
536-
@property
537-
def is_existing(self):
538-
"""
539-
Account is temporary, not yet backed by a database record.
540-
"""
541-
return self.account.pk is not None
542-
543-
def lookup(self):
544-
"""
545-
Lookup existing account, if any.
546-
"""
547-
assert not self.is_existing
548-
try:
549-
a = SocialAccount.objects.get(provider=self.account.provider,
550-
uid=self.account.uid)
551-
# Update account
552-
a.extra_data = self.account.extra_data
553-
self.account = a
554-
self.user = self.account.user
555-
a.save()
556-
# Update token
557-
if app_settings.STORE_TOKENS and self.token:
558-
assert not self.token.pk
559-
try:
560-
t = SocialToken.objects.get(account=self.account,
561-
app=self.token.app)
562-
t.token = self.token.token
563-
if self.token.token_secret:
564-
# only update the refresh token if we got one
565-
# many oauth2 providers do not resend the refresh token
566-
t.token_secret = self.token.token_secret
567-
t.expires_at = self.token.expires_at
568-
t.save()
569-
self.token = t
570-
except SocialToken.DoesNotExist:
571-
self.token.account = a
572-
self.token.save()
573-
except SocialAccount.DoesNotExist:
574-
pass
575-
576-
def get_redirect_url(self, request):
577-
url = self.state.get('next')
578-
return url
579-
580-
@classmethod
581-
def state_from_request(cls, request):
582-
state = {}
583-
next_url = get_next_redirect_url(request)
584-
if next_url:
585-
state['next'] = next_url
586-
state['process'] = get_request_param(request, 'process', 'login')
587-
state['scope'] = get_request_param(request, 'scope', '')
588-
state['auth_params'] = get_request_param(request, 'auth_params', '')
589-
return state
590-
591-
@classmethod
592-
def stash_state(cls, request):
593-
state = cls.state_from_request(request)
594-
verifier = get_random_string()
595-
request.session['socialaccount_state'] = (state, verifier)
596-
return verifier
597-
598-
@classmethod
599-
def unstash_state(cls, request):
600-
if 'socialaccount_state' not in request.session:
601-
raise PermissionDenied()
602-
state, verifier = request.session.pop('socialaccount_state')
603-
return state
604-
605-
@classmethod
606-
def verify_and_unstash_state(cls, request, verifier):
607-
if 'socialaccount_state' not in request.session:
608-
raise PermissionDenied()
609-
state, verifier2 = request.session.pop('socialaccount_state')
610-
if verifier != verifier2:
611-
raise PermissionDenied()
612-
return state
398+
## ... source file continues with no further ForeignKey examples ...
613399

614400
```
615401

content/pages/meta/00-change-log.markdown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ on GitHub.
1818
### December
1919
* Merged PR [#224](https://github.com/mattmakai/fullstackpython.com/pull/224)
2020
with information and resources on the Masonite web framework for the
21-
[other.web frameworks](/other-web-frameworks.html) page.
21+
[other web frameworks](/other-web-frameworks.html) page.
2222
* Updated the [RQ](/redis-queue-rq.html) page with a couple of new fresh
2323
resources.
2424
* Added new Django code example pages:

0 commit comments

Comments
 (0)