1

I'm using Django, I import the User models by following:

from django.contrib.auth.models import User, Group, Permission

But now I want to add some class method to the User model class.

So here comes my general question: Can we add class method after the class was define?

for example:

class A:
    value = 123

def myfunc(self):
    return self.value

I want the myfunc to be member function of class A, how can it be? Plz help.

Maxime Lorant
  • 34,607
  • 19
  • 87
  • 97
Alfred Huang
  • 17,654
  • 32
  • 118
  • 189
  • This is ordinarily as simple as `A.myfunc = myfunc`, but I'm not sure whether Django's use of metaclasses interferes with this. – user2357112 Jun 04 '14 at 08:16
  • Why not just extend/sublcass the user class and add your method. Why add the method after the class is defined? – rix Jun 04 '14 at 08:17
  • Not a dupe. This is about adding new methods to a class, not an individual instance of the class. – user2357112 Jun 04 '14 at 08:19
  • Oh thank you @user2357112, I've been trying to define one directly, but not notice that I can first define it then assign it to the class. – Alfred Huang Jun 04 '14 at 08:20
  • The question isn't an exact duplicate, but the answers also cover your question. Note that "class method" has a [specific meaning](http://stackoverflow.com/questions/12179271/python-classmethod-and-staticmethod-for-beginner) in Python that you probably don't mean. – otus Jun 04 '14 at 08:30

3 Answers3

1

Since you are talking about the Django User model, you should create your own model, extending the User. To do this, you just need to create a model with a OneToOne relation with the User model:, you should create a new User model, by extending AbstractUser:

from django.contrib.auth.models import AbstractUser

class MyUserModel(AbstractUser):
    # AbstractUser has already every fields needed: username, password, is_active...
    def myfunc(self):
        # Just a dummy working example
        return "My Username in uppercase: %s" % self.username.upper()

And put AUTH_USER_MODEL = "yourapp.MyUserModel" in settings.py

Then, you can use this new user model as if it was the User: it has the same methods than User (like create_user, check_password...), and you can access to myfunc with user.myfunc(), where user is the regular MyUserModel instance (get from request.user or the ORM). This is more consistent with the framework organisation and allow you to add more fields to the User if you want.


Side-note: As @Daniel Roseman pointed out in comments, you should really extend the AbstractUser model now (since Django 1.6) instead of make an UserProfile "proxy".

Related questions:

Community
  • 1
  • 1
Maxime Lorant
  • 34,607
  • 19
  • 87
  • 97
  • Don't recommend creating a UserProfile model any more. As you hint in your first sentence, OP should actually *extend* User, preferably by subclassing AbstractUser and pointing settings.AUTH_USER_MODEL to the new class. – Daniel Roseman Jun 04 '14 at 09:04
  • So, can I understand this way: since I just want to add a method, and doesn't want to affect the data-fields, I'd better not to extend the User model but just adding a method to it? @Daniel Roseman – Alfred Huang Jun 04 '14 at 09:09
  • @DanielRoseman Cleary, yes. Sorry for this old Django < 1.6 habit :-) See my updated answer – Maxime Lorant Jun 04 '14 at 09:13
  • @fish_ball no, you should extend the model as Maxime shows. The alternative is to subclass the concrete auth.User model, but set `proxy=True` in the Meta class: you'd still need to set AUTH_USER_MODEL to the new class, so there's not much difference between those approaches. – Daniel Roseman Jun 04 '14 at 09:27
0

You can add a class method by assignment, as user2357112 suggested.

class A(object):
    value = 123

def myfunc(cls):
    return cls.value

A.myfunc = classmethod(myfunc)

print A.myfunc()
> 123

As for Django models, you probably might want to use a custom Manager to handle functionality for all users instead of class methods. But I can't say more without further information.

Germano
  • 2,452
  • 18
  • 25
0

Profile is just fine, it will work and there is no problem with that. One option that is actually meant in Django ORM is proxy models. In proxied model you can have all the fields of parent model and add your custom methods or managers without changing parent model.

from django.contrib.auth.models import User

class MyUser(User):
    class Meta:
        proxy = True


    def my_method(self):
        return self.name
jtiai
  • 611
  • 5
  • 11