i have problem when i want extend django user model - django

i build simple django project and i have model class is structure and i want link structure with user django in objective to give multiple access for different structure , the problem that when i make python3 manage.py make migrations all is fine and with migrate also is fine with sqlmigrate is fine but in database i don't find the Utilisateur table
from immob.models import Division
from django.db import models
from django.contrib.auth.models import User
class Utilisateur(models.Model):
user=models.OneToOneField('auth.User', on_delete=models.CASCADE)
Division=models.ForeignKey(Division,on_delete=models.CASCADE)
MacBook-Pro-de-MAC:Invest_App mac$ python3 manage.py sqlmigrate compte 0001
BEGIN;
-- Create model Utilisateur
CREATE TABLE "compte_utilisateur" ("id" serial NOT NULL PRIMARY KEY, "Division_id" integer NOT NULL, "user_id" integer NOT NULL UNIQUE);
ALTER TABLE "compte_utilisateur" ADD CONSTRAINT "compte_utilisateur_Division_id_191feb84_fk_immob_division_id" FOREIGN KEY ("Division_id") REFERENCES "immob_division" ("id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "compte_utilisateur" ADD CONSTRAINT "compte_utilisateur_user_id_9142a9fe_fk_auth_user_id" FOREIGN KEY ("user_id") REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "compte_utilisateur_Division_id_191feb84" ON "compte_utilisateur" ("Division_id");
COMMIT;
but in database i don't find UTilisateur Table ??

from immob.models import Division
from django.db import models
from django.contrib.auth.models import User
class Utilisateur(models.Model):
user=models.OneToOneField('auth.User', on_delete=models.CASCADE)
division=models.ForeignKey(Division, on_delete=models.CASCADE)
try this one. You tried to use "Division" which is a reserved keyword because of your imports. You should never name variables with capital letters though, unless you want to define constants.

Related

Django Auth : How are many-to-many relationship models created?

django.contrib.auth.models have only 3 models, User, Group, Permission, as per the doc and code.
Doc does say groups and permissions are many-to-many relationships.
But when we migrate how come other relations user_group, user_permissions, group_permissions are created?
The tables for ManyToMany relationship are created by lines with models.ManyToManyField string that are in the migration file.
In this case they are created by the initial migration django/contrib/auth/migrations/0001_initial.py. It is very similar to django/contrib/auth/models.py.
The related SQL commands can be read by
$ python manage.py sqlmigrate auth 0001_initial
See the lines:
CREATE TABLE "auth_user_groups"...
CREATE TABLE "auth_group_permissions"...
CREATE TABLE "auth_user_user_permissions"...
Especially interesting two texts are around the words REFERENCES. That are the foreign keys to base tables, e.g.:
... "user_id" integer NOT NULL REFERENCES "auth_user" ("id") ...
EDIT:
You probably know a ManyToMany relationship joined by an explicit intermediate model specified by the parameter through=SomeModel with an extra field.
I explain it in example how you can use a hidden intermediate table in your code.
Imagine that you want to make a note to some permission why you added it to some person.
You can explore the model structure from command line, because in "auth/models.py" you could read only the name "user_parmissions".
>>> User._meta.local_many_to_many
[<django.db.models.fields.related.ManyToManyField: groups>,
<django.db.models.fields.related.ManyToManyField: user_permissions>]
>>> User.user_permissions.through
<class 'django.contrib.auth.models.User_user_permissions'>
>>> User.user_permissions.through._meta.local_fields
[<django.db.models.fields.AutoField: id>,
<django.db.models.fields.related.ForeignKey: user>,
<django.db.models.fields.related.ForeignKey: permission>]
your_app/models.py
from django.contrib.auth.models import User, Group, Permission
from django.db import models
# This line is instead of import, because the implicit intermediate table
# can not be imported.
UserPermission = User.user_permissions.through
class UserPermissionReason(models.Model)
user_permission = models.ForeignKey(UserPermission, ...)
reason = models.CharField(help_text="Why I added that permission", ...)
makemigrations, migrate, shell...
Example: Create a user permission with your note
>>> from your_app.models import UserPermissionReason, UserPermission
>>> from django.contrib.auth.models import User, Group, Permission
>>> permission = Permission.objects.get(name='Can add user',
content_type__app_label='auth')
>>> permission
<Permission: auth | user | Can add user>
>>> user_permission = UserPermission.objects.create(user=me_superuser,
permission=permission)
>>> why = UserPermissionReason.objects.create(
user_permission=user_permission,
reason="Because I can :-)"
)
If you don't need to reference the intermediate table you would use a normal simple some_ruser.user_permissions.add(permission)

IntegrityError after customizing user model

After customizing my user model in Django Oscar, I received the following error message:
IntegrityError at /
insert or update on table "basket_basket" violates foreign key constraint "basket_basket_owner_id_74ddb970811da304_fk_auth_user_id"
DETAIL: Key (owner_id)=(5) is not present in table "auth_user".
To customize my user model, I followed the instructions here.
First, I wrote the following models.py file, located within my project directory at apps/user/models.py.
from django.db import models
from oscar.apps.customer.abstract_models import AbstractUser
from django.contrib.postgres.fields import ArrayField
class User(AbstractUser):
acct_bal = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
purchased_items = ArrayField(models.IntegerField(), default=list)
The idea is that I want the user to have an account balance (which I will use for payment later) as well as a list of product numbers representing items that have already been purchased.
After making models.py, I edited the installed apps as follows:
INSTALLED_APPS = [...
'shopworld.apps.user',
] + get_core_apps()
And then put this at the bottom of my settings.py:
AUTH_USER_MODEL = 'user.User'
I then did ./manage.py migrate, but for some reason I am getting this error message. I also tried dropping the django_admin_log table as suggested here, but it did not work. Any help would be greatly appreciated.
I fixed this - the issue was that I was trying to migrate to a custom user model after already having done migrations with auth_user. This meant that auth_user didn't update correctly. I had to flush and re-sync the database, so that the initial migration captured the custom user model.

rest_framework authtoken migration error

Unable to complete migration for rest_framework.authtoken
Running migrations for authtoken:
- Migrating forwards to 0001_initial.
authtoken:0001_initial
FATAL ERROR - The following SQL query failed: ALTER TABLE "authtoken_token" ADD CONSTRAINT "user_id_refs_id_14b35167" FOREIGN KEY ("user_id") REFERENCES "users_user" ("id") DEFERRABLE INITIALLY DEFERRED;
Error in migration: authtoken:0001_initial
DatabaseError: relation "users_user" does not exist
Using version djangorestframework-2.3.8
Because of the custom user table name the migration isn't happening. Go to the initial migration and specify your user table using db_table in the migration where the code is trying to access your custom table. That should work.
are you using a custom user model?
if this was the case the
migration code for the app implementing the user model should look like:
class Migration(SchemaMigration):
needed_by = (
('oauthtoken', '0001_initial'),
)

Upgrading existing django_comments to Django 1.5

I have a Django 1.4 site that uses the Django comments app. I'm upgrading my dev version to Django 1.5 and extending the User model - I have a Person model which extends AbstractBaseUser, and AUTH_PROFILE_MODULE = 'membership.Person' in my settings.
At the moment the django_comments postgresql database table has a column user_id which references auth_user(id):
"django_comments_user_id_fkey" FOREIGN KEY (user_id) REFERENCES auth_user(id) DEFERRABLE INITIALLY DEFERRED
There's nothing in that column because, so far, there are no user accounts in the system, other than my own admin user. I think I need to update the table to refer to my new Person model (which is stored in the membership_person table). In the future users will be able to create accounts and post logged-in comments.
What ALTER TABLE command should I use to change django_comments to refer to my new Person model? I'll have to do similar to the django_comment_flags table. Is there anything else I should watch out for?
I ended up doing this for the comments table:
ALTER TABLE django_comments DROP CONSTRAINT django_comments_user_id_fkey;
ALTER TABLE django_comments ADD CONSTRAINT django_comments_user_id_fkey FOREIGN KEY (user_id) REFERENCES membership_person(id) DEFERRABLE INITIALLY DEFERRED;
And similar for the comment flags table:
ALTER TABLE django_comment_flags DROP CONSTRAINT django_comment_flags_user_id_fkey;
ALTER TABLE django_comment_flags ADD CONSTRAINT django_comment_flags_user_id_fkey FOREIGN KEY (user_id) REFERENCES membership_person(id) DEFERRABLE INITIALLY DEFERRED;
Hopefully that does the job and doesn't cause any problems. *crosses fingers*

Django: extending User model avoiding DB join

In my Django app, I need to create a User Model with some extra fields. For DB performance, I would like to avoid to make a join everytime I want to access those fields. At DB level I would like to produce an ALTER TABLE on the user table to add those fields, or even a CREATE TABLE with all the fields I need on the app initialization would be fine, since I'm still in development.
I've found two solutions to extend the User Model (reported below) but both are inconsistent with my choice of avoiding JOINs.
models.py (Solution 1)
from django.db import models
class Person(models.Model):
# Aggregate using a OneToOneField on User
user = models.OneToOneField(User)
age = models.PositiveSmallIntegerField()
models.py (Solution 2)
from django.contrib.auth.models import User
class Person(User):
# Inheriting from User
age = models.PositiveSmallIntegerField()
SQL (Solution 1)
/* Aggregate using a OneToOneField on User */
BEGIN;
CREATE TABLE "people_person" (
"id" integer NOT NULL PRIMARY KEY,
"user_id" integer NOT NULL UNIQUE REFERENCES "auth_user" ("id"),
"age" smallint unsigned NOT NULL
);
COMMIT;
SQL (Solution 2)
/* Inheriting from User */
BEGIN;
CREATE TABLE "people_person" (
"user_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "auth_user" ("id"),
"age" smallint unsigned NOT NULL
);
COMMIT;
From django 1.5, it is possible to replace the user model rather than extending it.
https://docs.djangoproject.com/en/dev/releases/1.5/#configurable-user-model
In django 1.4 or older, there the "profile" attribute on the user gets some special caching, which may or may not be good enough for your requirements.