Login

UserForeignKey

Author:
hawkeye
Posted:
February 22, 2008
Language:
Python
Version:
.96
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. Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
  5. Help text hyperlinks by sa2812 1 year, 8 months ago

Comments

Please login first before commenting.