Login

UserForeignKey

Author:
hawkeye
Posted:
February 22, 2008
Language:
Python
Version:
.96
Tags:
foreignkey user auth
Score:
4 (after 4 ratings)

Many models are tightly coupled to the default Django User model (django.contrib.auth.models.User).

Sometimes this user model just doesn't fit everyone's needs. By using UserForeignKey it is possible to make the User model configurable, encouraging loose coupling.

Additionally, this can help to prevent circular imports between User and another model.

Use it like a standard ForeignKey... it accepts all the same arguments.

If you want to use a User model other than the default, just add USER_MODEL to your settings file.... it uses dotted notation (app_label.model_name).

Example:

class BlogPost(models.Model):
    user = UserForeignKey(related_name="blog_posts")
    title = models.CharField(...)
    content = models.TextField(...)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from django.db import models
from django.db.models import signals
from django.conf import settings
from django.dispatch import dispatcher

_USER_APP_NAME, _USER_MODEL_NAME = getattr(settings, 'USER_MODEL', 'auth.User').split('.') # We default to the django.contrib.auth.models.User model
_pending_user_lookups = []

__all__ = ['UserForeignKey',]

class UserForeignKey(models.ForeignKey):
    def __init__(self, **kwargs):
        self._stored_kwargs = kwargs
        self.initialized = False

        user_model = models.get_model(_USER_APP_NAME, _USER_MODEL_NAME, seed_cache=False)

        if user_model is None:
            _pending_user_lookups.append(self)
        else:
            self.__reinit__(user_model)

    def __reinit__(self, to):
        kwargs = self._stored_kwargs
        kwargs['to'] = to
        models.ForeignKey.__init__(self, **kwargs)
        self.initialized = True

    def contribute_to_class(self, cls, name):
        if self.initialized:
            models.ForeignKey.contribute_to_class(self, cls, name)
            if hasattr(self, '_cached_contribute_to_class_args'):
                del self._cached_contribute_to_class_args
        else:
            self._cached_contribute_to_class_args = (cls, name)

def do_user_lookup(sender):
    if _USER_APP_NAME == sender._meta.app_label and _USER_MODEL_NAME == sender._meta.object_name:
        for fk in _pending_user_lookups:
            fk.__reinit__(sender)
            fk.contribute_to_class(*fk._cached_contribute_to_class_args)

dispatcher.connect(do_user_lookup, signal=signals.class_prepared)

More like this

  1. Duplicate related objects of model instance by johnboxall 6 years, 4 months ago
  2. convenience parent class for UserProfile model by willhardy 6 years, 1 month ago
  3. Owner required decorator by polarbear 6 years, 10 months ago
  4. Full Model History by willhardy 6 years, 5 months ago
  5. Clean Reversion History: Remove unimportant Changes by guettli 3 years, 3 months ago

Comments

Please login first before commenting.