django google calendar API and south freeze issue - django

I'm trying to use the Google API django client lib. In order to store the credentials for each user of my web app, a Credentials model is set up:
from oauth2client.django_orm import CredentialsField
class CredentialsModel(models.Model):
id = models.ForeignKey(User, primary_key=True)
credential = CredentialsField()
However upon trying to add this model with a South migration, I get:
Cannot freeze field 'google.credentialsmodel.credential'
(this field has class oauth2client.django_orm.CredentialsField)
South cannot introspect some fields; this is probably because they are custom
fields. If they worked in 0.6 or below, this is because we have removed the
models parser (it often broke things).
To fix this, read http://south.aeracode.org/wiki/MyFieldsDontWork
I read the linked document, but I'm not much clearer on how to fix this. How do I write introspection rules? or how do I fix this to simply add the model with this funky field?

You need to add these lines before your model declaration:
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^oauth2client\.django_orm\.CredentialsField"])
That will allow South to know about the oauth2client.django_orm.CredentialField and to use the introspection rules defined by its parent class.

Related

Moving multiple models from one django app to another

I'm building a project using django v2.0.2 that consists of 3 apps with 24 models. One of the apps has 14 models. Having so many models in one app is becoming complicated, and I'd like to create a new app and move few models to this app.
I found an answer explaining how this can be done using south. I've been using django core migrations and since south is deprecated, I don't want to switch to south at this point.
The models I want to move are quite complex - they have ForeignKey fields, ManyToMany fields, etc. I need a workflow showing how I can move these models using django core migrations.
That shouldn't be too difficult to do. The main issue you run into is that Django automatically derives the name of the database table from the name of your model class and the app that contains it.
That means unless you're explicitly setting the db_table property in the model meta, the names of all the tables corresponding to your models are auto generated based on app/model name combo.
So if you have a Post model in a Blog app, the auto generated table name of that Post model is blog_post. And if you decide to move Post model to the Article app, Django will be looking for a table named article_post and won't be able to associate your model with the correct table.
To solve this issue, you need to explicitly set the db_table property on each of the models. The db_table name value will have to correspond to the current app/model combo. So in the case of Post model mentioned above, you would set db_table to blog_post. Once you set the db_table property, you can move the model to any other apps.
class Post(models.Model):
title = models.CharField(max_length=120)
class Meta:
db_table = 'blog_post'
Once you move all the models around, login to django admin to verify that your data is still accessible through the newly moved models.
When you run makemigrations for the first time after moving the models,
Django migrations will create migration files that deletes the moved models in their old app and recreate them in their new app. Do not apply these migrations and instead run migrate --fake which will record the migrations as having been executed without making any of the database changes. After that, your migration files and your database structure will be synced.

Using existing NDB on Google App Engine after converting from Webapp2 to Django

I am in the process of converting a Webapp2 app to Django on Google App Engine. Everything is relatively straightforward, and the models have been converted from the webapp models to the django equivalents.
However, I feel this may be have been glossed over in the posts from the app engine team Refering This... Do I need to perform a data migration in order to re-use existing data, or can I simply use the existing NDB models somehow? (If so, what configurations are needed? I can't seem to figure this out).
there is no concept of a data migration in schemaless databases.
A migration that you think of is really creation or alteration of a database schema i.e the DB needs to have a schema only then would the idea of a migration make sense.
After looking into this a little further, I noticed that by default GAE would create db_tables with the default names as <app_label>_<model_name> (i.e. coreapp_GuestBook).
As a result, if you specify the model meta options in Django, matching the converted apps name with the original apps name, you will be able to access the same models with Django. Note that the field values may be inaccessible or possible corrupted if you did not do the conversion of webapp fields to the appropriate Django fields one for one.
See reference: https://cloud.google.com/appengine/articles/django-nonrel
For example, in my case, the Article app would be retrieved by specifying:
class Article(models.Model):
title = models.CharField(max_length=255)
class Meta:
db_table = 'Article'
verbose_name = 'Article'
verbose_name_plural = 'Articles'

Django - Removing username from user model

In order to create a new user model in Django 1.5.x, there are two approaches:
Inherit AbstractUser class which is the default user model you get, this way you can extend it with any attributes you want. However, if you want to remove any field, it's technically possible but not recommended; even if it can be done, it is against OOP principles, I believe. So if you would like to alter the current user model, there is the second approach.
Inherit AbstractBaseUser, which by looking at the code provides very basic functionality. You will miss all the goodness of permissions, profile retrieval and absolute url construction, unless you copy it from the default Django user model.
The above is my understanding of the situation. Correct me if I'm wrong, but doesn't this mean that if I want to simply remove the username field out of the model since I won't need it at all, I have to copy paste the model code provided in the framework and inherit from AbstractBaseUser and PermissionsMixin? For such a simple thing, this approach doesn't look very pretty to me, and it looks a bit odd since I'm quite certain the custom user model was introduced largely because of the popular use case of email field as the user identifier instead of username.
Your thoughts (and corrections) please.
If You look at the source code of the django.contrib.auth.models file then you will see that definition of the AbstractUser class is rather short and starts like this:
class AbstractUser(AbstractBaseUser, PermissionsMixin):
...
It inherits from the AbstractBaseUser and PermissionMixin. You could define your custom model and also inherit it from the mentioned classes to get permissions support. If you want all other model fields then yes, you will need to copy them, but it's also an opportunity to customize things to match your needs.
Rather than using mixins and other applications which solve the problem,
The best way to tackle the problem of not wanting a username is to replace the username with the email address entered by the user.
What u need to do is,
go to the django source code which is usually situated in the python path.
usually in the site-packeges of the python folder,
go to django folder, and into contrib folder, and into auth folder, open the models.py file which contains the definition of the User model.
On Virtualenv -> <virtualenv_name>/lib/python2.7/site-packages/django
In the models.py of auth app
Go to -> AbstractUser class
replace the regex in "validators.RegexValidator" with this:
r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$"
replace only the regex part inside the "validators.RegexValidator"
and in the same class, alter the username field's max_length to 254
I didnt have the reputation to post image of the code, if anybody wants a screenshot of how it looks after altering the code, ping me.
Thats it!
now go back to your app and then you can replace the username field with the email of any type in this world.
The final step :
Go to your application where you are using the User model, meaning anywhere
python manage.py syncdb
python manage.py makemigrations
python manage.py migrate
if you don't see the auth model migrating then do,
python manage.py migrate auth
Now all you need to do is just replace the username with the email, during registration you can do somewhat like:
user = User.objects.create_user('email here', 'again email here', 'password here')
The best part about this is you dont have to change your authentication backend, as the email is itself the username and you can just label the username field as email.

Adding fields to user's personal info in Django admin page

I just started a Django project (there are no apps in it). I activated the admin in settings file and can access the Django administration page. There is a column in Django page to add users; while adding users I get only three fields under personnal info, but I need to store some more information about users. I Googled around and found that I can use user profiles to accomplish this. I tried, but I am having problems.
My aim is to add three more fields to the user table:
role
contact number
other
I need details like: which function I need to write and where to do this.
I found this, but I do not know where I need to write these steps. I would greatly appreciate a more clear explanation of this.
Django User Profiles is what you need. The blog you linked to has clear steps on how to do it. You can check out the Django documentation. http://www.turnkeylinux.org/blog/django-profile also provides a good explanation.
Basically you need to create a new model with User as ForeignKey and define the model in the settings.py as AUTH_PROFILE_MODULE = "django_app.your_profile_modelname". Create the profile and save it just like any other model, and access it using user.get_profile()
Adding a couple of things in response to your questions below:
First, do not create apps as a directory. Use startapp <appname> [destination] as described here. That will create the app directory.
Second, you have to add the app to INSTALLED_APPS in the project's settings file, do a syncdb. Basically, follow the steps in Django tutorial on writing your first app.
Third, UserProfile is a separate model. It is not an extension of User. It is associated with the User just because you added User as the ForeignKey.
Fourth, to be able to see the user profile model in admin, you do exactly what you would do to add any other model to admin page. Create a file names admin.py under your app with:
from django.contrib import admin
from myproject.app.models import UserProfile
admin.site.register(UserProfile)
There are three key concepts to understand:
There is no built in "profile" system in Django, beyond the limited auth app which is really geared just to user login. You are expected to roll your own.
There is nothing magical about a profile record in itslef, it is just like any other record that takes User as a foreign key (or, more properly, a one-to-one field as per the docs). You create it by creating a custom django app (traditionally called profiles) and a model for that app (traditionally called UserProfile, since Profile is not allowed as a model name).
The only thing that sets UserProfile aparts as a model is that you specify it as the AUTH_PROFILE_MODULE which means that it is accessible when called .get_profile() on a User record. That's it. If you set up the UserProfile like so:
def UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
other fields
then you can also access the profile as user.profile rather than user.get_profile() which some people prefer.
Again, nothing magical about the profile model -- it is just a model record like any other model record.
If you want to be able to edit additional fields within the user form that's more complicated; easiest way is probable unregister User and then register it again using your custom ModelAdmin and form class but judging by your question you're probably not at that level yet.

Django custom User model authentication

Since i'm not using the Auth User from Django, I have my own model CustomUser and I want make authentication on site through this model (CustomUser does not inherit from User model and not related to it at all).
class CustomUser(models.Model):
password = models.CharField(max_length = 40)
email = models.EmailField(max_length = 72, unique = True)
#stuff...
I checked https://docs.djangoproject.com/en/dev/topics/auth/#writing-an-authentication-backend and the main thing I don't understand is:
from django.contrib.auth.models import User
Do I need to import Django User if I want to use my CustomUser?
I can't find a good tutorial which explains how you can use Django without standard Auth User.
*edit:
I know I can extend with User. But I just don't want that. The question is not: what is the best way to use User and store additional information etc etc. I appreciate it though.
BUT how I can use a Custom User without using Auth User. Even if I don't have a reason to. *
If it is possible I want to know how.
The whole Django auth system is tightly coupled with django.contrib.auth.models.User, so you should use it in the backend. Quoting Django docs
For now, the best way to deal with this is to create a Django User object for each user that exists for your backend
But the main question here is: what is so special about your CustomUser that you can't implement with normal User model (may be extended)? In 99% of cases using User is the best way.
Check out this post.
Most of the Django projects I’ve worked on need to store information about each user in addition to the standard name and email address held by the contrib.auth.models.User model.
If you’re using trunk as of revision 7477 (26th April 2008), your model classes can inherit from an existing model class. Additional fields are stored in a separate table which is linked to the table of the base model. When you retrieve your model, the query uses a join to get the fields from it and the base model.
http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/
And this post.
Copy the auth application over into your own project and modify it to your needs. This avoids some of the maintenance troubles, but removes the utility of Django bundling an auth system in the first place. It can also cause compatibility problems with other applications which expect the User model to be in django.contrib.auth.
http://www.b-list.org/weblog/2006/jun/06/django-tips-extending-user-model/
Perhaps this answers your question:
From 'https://docs.djangoproject.com/en/1.6/topics/auth/customizing/#substituting-a-custom-user-model':
Substituting a custom User model
New in Django 1.5.
Some kinds of projects may have authentication requirements for which Django’s built-in User model is not always appropriate. For instance, on some sites it makes more sense to use an email address as your identification token instead of a username.
Django allows you to override the default User model by providing a value for the AUTH_USER_MODEL setting that references a custom model:
AUTH_USER_MODEL = 'myapp.MyUser'
This dotted pair describes the name of the Django app (which must be in your INSTALLED_APPS), and the name of the Django model that you wish to use as your User model.
Of course there are some requisite warnings to consider (available at the above link), but this is looking like a good answer to your question: https://docs.djangoproject.com/en/1.6/ref/settings/#auth-user-model
There are also some custom model compliance expectations to consider (too many to list here): https://docs.djangoproject.com/en/1.6/topics/auth/customizing/#specifying-a-custom-user-model
Unless there can be more than one value for AUTH_USER_MODEL (I doubt that is sane), then I think I will need to build my own custom authentication backend: https://docs.djangoproject.com/en/1.6/topics/auth/customizing/#writing-an-authentication-backend
I hope this helps any other lost souls out there that need distinct User and Device authentication schemes (perhaps because of some pre-existing spec that makes messy what could be soooo easy).
Cheers!