Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Migrating existing models to Django built-in User Models

I am running a Django 1.4.2 project. I have a database of class User(models.Model), and would now like to change this so that I used the built in model User from django.contrib.auth.models. Can I simply use my existing code and simply make my own custon User model a subclass of Django's built in one? Here is the model now.

class User(models.Model):
    u_id = models.AutoField(primary_key=True)
    #password = models.CharField(max_length=765)
    old_password = models.CharField(max_length=765, null=True, blank=True)
    birthday = models.DateField(null=True, blank=True)
    school_year = models.CharField(max_length=765, blank=True)
    gender = models.CharField(max_length=18, blank=True)
    #email = models.CharField(max_length=765, blank=True)
    profile_pic = models.CharField(max_length=765, blank=True)
    is_cloudinary_pic = models.BooleanField(default=False)
    fb_id = models.CharField(max_length=765, blank=True)
    phone_num = models.CharField(max_length=765, blank=True)
    name = models.CharField(max_length=765, blank=True)
    confirmcode = models.CharField(max_length=765, blank=True)
    status = models.CharField(max_length=765, blank=True)
    netid = models.CharField(max_length=765, blank=True)
    favorites = models.ManyToManyField('listings.Listing', blank=True, related_name='favorites')
    stripe = models.CharField(max_length=765, blank=True)
    rating = models.IntegerField(null=True, blank=True)
    preferences = models.CharField(max_length=765, blank=True)
    b_notification = models.CharField(max_length=765, blank=True)
    l_notification = models.CharField(max_length=765, blank=True)
    address = models.CharField(max_length=765, blank=True)
    city = models.CharField(max_length=765, blank=True)
    state = models.CharField(max_length=6, blank=True)
    zip = models.CharField(max_length=15, blank=True)
    emailprefs = models.CharField(max_length=30, blank=True)
    exp_month = models.CharField(max_length=6, blank=True)
    exp_year = models.CharField(max_length=12, blank=True)
    last4 = models.CharField(max_length=12, blank=True)
    c_type = models.CharField(max_length=765, blank=True)
    user_type = models.CharField(max_length=10, blank=True)
    contract = models.ForeignKey('contracts.Contract', null=True,blank=True, default=None, on_delete=models.SET_NULL)
    last_listing_booked = models.ForeignKey('listings.Listing', null=True,blank=True, default=None, on_delete=models.SET_NULL, related_name='last_listing_booked')
    last_locked_on = models.IntegerField(null=True, blank=True)
    waitlist_number = models.IntegerField(null=True, blank=True)
    waitlist_listing = models.ForeignKey('listings.Listing', null=True, blank=True, on_delete=models.SET_NULL, related_name='waitlist_listing')
    uploaded_contract = models.FileField(upload_to=contract_file_name, max_length=765, null=True, blank=True, default=None, storage=FileSystemStorage(location=os.path.join(MEDIA_ROOT, 'contracts')))

When I try to migrate using Django South after making my model a subclass of the Django User model, I am asked to set a value for user_ptr, a field about which I have been unsuccessful finding any information.

In general, is it unsafe to simply subclass in this fashion? I cannot afford to lose all the user data I already have and start over. Note that the password and email fields are commented out because they clash with Django's version of those fields.

like image 529
Matt Stern Avatar asked Feb 17 '23 21:02

Matt Stern


2 Answers

If upgrading to Django 1.5 is an option, you can simply use your own User model, so long as it supplies all the required fields.

user_ptr is an implicit OneToOne model that associates your object with the class you're deriving from. The easiest way to do this would probably be to create the migration manually in these steps:

  1. Add the user_ptr field WITH null=True

  2. Iterate over all the User objects and create the corresponding auth.User objects. If you are unsure of how to do this, you can read the section on data migrations in the South documentation.

  3. Disallow null user_ptr fields

Another thing you might need to do is implement your own password hasher if the hashing scheme you used isn't compatible with Django's built in methods. This is not very hard to do, and is addressed in another question.

like image 160
Vinay Pai Avatar answered Feb 20 '23 16:02

Vinay Pai


If using Django 1.4, you should create a UserProfile model instead of sub-classing from django.contrib.auth.models.User. Extending Django's User class directly can cause all kinds of trouble with the internal django.auth mechanisms.

You can read more about how to implement user profiles in django at http://www.turnkeylinux.org/blog/django-profile.

Django 1.5 has configurable user model as mentioned in another answer by Vinay Pai.

like image 40
pankaj28843 Avatar answered Feb 20 '23 16:02

pankaj28843