How to assign a user to a model in my database - python

from django.db import models
from datetime import datetime
from django.contrib.auth import get_user_model
User = get_user_model()
class Blog(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
headline = models.CharField(max_length=250)
content = models.CharField(max_length=2050)
time_created = models.DateTimeField(default=datetime.now, blank=True)
def __str__(self):
return self.user.username
every time I migrate this
"(venv) PS C:\Users\user\Desktop\APPS\web_app_project> python manage.py makemigrations"
I always get this message:
"It is impossible to add a non-nullable field 'user' to blog without specifying a default. This is because the database needs something to populate existing rows.
Please select a fix:
Provide a one-off default now (will be set on all existing rows with a null value for this column)
Quit and manually define a default value in models.py.
Select an option:"
How do I go about this

Because you've added the non-nullable field user to Blog Django needs to add a user to all instances of blogs in the database, both new ones and existing. If you've created a blog instance in the database, what should Django do with its new user column? That's what it is asking you.
Only if there is no data in the database or you are completely OK with losing data, you can migrate your app to zero with python manage.py migrate <your app name> zero (You might want to reverse to migration besides zero. You can read more about reverse migrations). This will effectively undo all of your migrations for that app. You can then delete the existing migrations for that app and run makemigrations again. Django will no longer complain about the non-nullable field user, as this results in a migration that creates a Blog table with a user field, instead of a migration that attempts to add a user field to an existing Blog table. Once again, do not do this unless you are OK with losing data. This should never be done if your app is already running in production, but it is OK if you have never deployed the app and have no "real" data, and you are still in the initial development phase. Also, make sure you have a backup of deleted migrations in case you need to add them back.
As others have suggested, you can create a default user model that is used as the one-time default to add users to Blogs. For example (in Django shell)
from django.contrib.auth import get_user_model
User = get_user_model()
user = User(username='default_blog_user')
user.set_unusable_password() # Nobody should be able to log in as this user
user.save()
print(user.id) # keep this ID
Then, in the migration, you can use whatever that user.id value was as the one-time-default. But this once again assumes that you haven't deployed to production, as the one-time-default and the IDs in development and production may not match.
If you have already deployed to production, I think the only thing you can do is make the user field nullable for the sake of your migration, but assert that it is not null in your programming logic. For example, by adding a validator to the field.
Side note: instead of running get_user_model in your models module, you should do this:
from django.conf import settings
class Blog(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
# etc.
When you define a foreign key or many-to-many relations to the user model, you should specify the custom model using the AUTH_USER_MODEL setting.
source

You could probably get away with adding the user manually by using the python shell• python manage.py shell then import the required models.
Read more from a similar question here:
How to use the python shell
https://stackoverflow.com/a/5150535/15383032

Maybe add a UUID to your User Model and make the fields that require a user in other models a CharField that stores the Users UUID.

Related

Add onetoone field to all users, django

In the middle of the project, I was faced with the fact that I needed to expand my user model. Since it is very problematic to create a custom model at the moment, I decided to use the onetoone field and everything is successful, but there is a question. I would like to add a relationship to my user model proxy for existing users and set permissions for them. How can I do that? I need to set start value for all users
class UserPermission(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
start = models.BooleanField(default=True)
professional = models.BooleanField()
team = models.BooleanField()
last_update = models.DateTimeField()
If you can do this from your shell, then follow only step 2. If you want to do it from a migrations file, follow steps 1-3. (From the shell is easier).
In your terminal: run python manage.py make migrations app_name --empty
Add a function in your new migrations file that does the work you want to do for existing users.
def add_perms(apps, schema_editor):
UserPermissions.objects.bulk_create([UserPermissions(user_id=user_id) for user_id in User.objects.values_list("id", flat=True)], ignore_conflicts=True)
If you're doing this from your shell, you don't need the function itself. Just what it runs. UserPermissions(user_id=user_id) is just a base and you should add the defaults alongside that user_id part.
In the operations list, write:
operations = [
migrations.RunPython(add_perms)
]

Django add two fields to user profile

I am trying to add two additional profile fields and have the native authentication work like normal.
I am trying to fallow the documentation here
and the SO here
In my settings file
#settings.py
AUTH_USER_MODEL = 'users.User'
in my users.user model
#users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
foo = models.CharField(max_length=32, default='Blue')
bar = models.CharField(max_length=32, default='Blue')
print "user.user"
i have created 3 superusers non can log into admin. i have tried syncing the DB after adding a user. i have tried restating the dev server between adding a user.
the only time i see the output of print "user.user" is when i run the createsuperuser command.
i think i cant log in because the user is not really being created. it runs my User class and then skips actually creating the user. but i am kinda new to this so i could be way off and way out of my league.
why cant i log in and how do i add the two fields?
Have you read the warning in Django's documentation?
Changing AUTH_USER_MODEL has a big effect on your database structure. It changes the tables that are available, and it will affect the construction of foreign keys and many-to-many relationships. If you intend to set AUTH_USER_MODEL, you should set it before running manage.py syncdb for the first time.
If you have an existing project and you want to migrate to using a custom User model, you may need to look into using a migration tool like South to ease the transition.
Given this warning, are you working on a fresh database, or are you migrating using South? If you have an existing database and made these changes, then simply running syncdb will most likely no be sufficient.
If this is a development server without any important data, I would recreate your database, and then run ./manage.py syncdb. If you are using a SQLite database, then you can simply copy it to somewhere else (if you would like to keep the data), and run syncdb again to create a new database.
Here is the relevant documentation.
It would also be helpful to know exactly what error you are receiving. Do you attempt to login and admin tells you that your user/pass combination is not correct, or is there an actual error thrown? Your question doesn't quite make this clear.

Creating a profile model with both an InlineAdmin and a post_save signal in Django

I created a 'profile' model (with a 1-to-1 relationship to the User model) as described on Extending the existing user model. The profile model has an optional many-to-one relationship to another model:
class Profile(models.Model):
user = models.OneToOneField(User, primary_key=True)
account = models.ForeignKey(Account, blank=True, null=True, on_delete=models.SET_NULL)
As documented there, I also created an inline admin:
class ProfileInline(admin.StackedInline):
model = Profile
can_delete = False
verbose_name_plural = 'profiles'
# UserAdmin and unregister()/register() calls omitted, they are straight copies from the Django docs
Now if I don't select an account in the admin when creating the user, the profile model won't be created. So I connect to the post_save signal, again just following the documentation:
#receiver(post_save, sender=User)
def create_profile_for_new_user(sender, created, instance, **kwargs):
if created:
profile = Profile(user=instance)
profile.save()
This works fine as long as I do not select an account in the admin, but if I do, I'll get an IntegrityError exception, telling me that duplicate key value violates unique constraint "app_profile_user_id_key" DETAIL: Key (user_id)=(15) already exists.
Apparently, the inline admin tries to creates the profile instance itself, but my post_save signal handler has already created it at that time.
How do I fix this problem, while keeping all of the following requirements?
No matter how the new user is created, there will always be a profile model linking to it as well afterwards.
If the user selects an account in the admin during user creation, this account will be set on the new profile model afterwards. If not, the field is null.
Environment: Django 1.5, Python 2.7
Related questions:
Creating a extended user profile (similar symptoms, but the cause turned out to be a different one)
The problem can be avoided by setting primary_key=True on the OneToOneField pointing at the User model, as you have figured out yourself.
The reason that this works seems to be rather simple.
When you try to create a model instance and set the pk manually before saving it, Django will try to find a record in the database with that pk and update it rather than blindly attempting to create a new one. If none exists, it creates the new record as expected.
When you set the OneToOneField as the primary key and Django Admin sets that field to the related User model's ID, that means the pk is already set and Django will attempt to find an existing record first.
This is what happens with the OneToOneField set as primary key:
Django Admin creates the new User instance, with no id.
Django Admin saves the User instance.
Because the pk (in this case id) is not set, Django attempts to create a new record.
The new record's id is set automatically by the database.
The post_save hook creates a new Profile instance for that User instance.
Django Admin creates the new Profile instance, with its user set to the user's id.
Django Admin saves the Profile instance.
Because the pk (in this case user) is already set, Django attempts to fetch an existing record with that pk.
Django finds the existing record and updates it.
If you don't set the primary key explicitly, Django instead adds a field that uses the database's auto_increment functionality: the database sets the pk to the next largest value that doesn't exist. This means the field will actually be left blank unless you set it manually and Django will therefore always attempt to insert a new record, resulting in a conflict with the uniqueness-constraint on the OneToOneField.
This is what causes the original problem:
Django Admin creates the new User instance, with no id.
Django Admin saves the User instance, the post_save hook creating a new Profile instance as before.
Django Admin creates the new Profile instance, with no id (the automatically added pk field).
Django Admin saves the Profile instance.
Because the pk (in this case id) is not set, Django attempts to create a new record.
The database reports a violation of the table's uniqueness-constraint on the user field.
Django throws an Exception. You will not go to space today.
It seems like setting primary_key=True on the OneToOneField connecting the profile model to the User model fixes this issue. However, I don't think I understand all the implications of that and why it helps.
I'll leave this here as a hint, but if that's the best solution and someone could come up with a well-written explanation, I'd upvote/accept that and possibly delete mine.

get user profile in django

hello i'm new in python and django
I need a view that get current user profile I know I shoud use get_profile from User but I don't know how to use it . i read the django document and It didn't help me.
this is what I found from doc:
from django.contrib.auth.models import User
profile=request.user.get_profile()
Django's documentation says it all, specifically the part Storing additional information about users. First you need to define a model somewhere in your models.py with fields for the additional information of the user:
models.py
from django.contrib.auth.models import User
class UserProfile(models.Model):
# This field is required.
user = models.OneToOneField(User)
# Other fields here
accepted_eula = models.BooleanField()
favorite_animal = models.CharField(max_length=20, default="Dragons.")
Then, you need to indicate that this model (UserProfile) is the user profile by setting AUTH_PROFILE_MODULE inside your settings.py:
settings.py
...
AUTH_PROFILE_MODULE = 'accounts.UserProfile'
...
You need to replace accounts with the name of your app. Finally, you want to create a profile every time a User instance is created by registering a post_save handler, this way every time you create a user Django will create his profile too:
models.py
from django.contrib.auth.models import User
class UserProfile(models.Model):
# This field is required.
user = models.OneToOneField(User)
# Other fields here
accepted_eula = models.BooleanField()
favorite_animal = models.CharField(max_length=20, default="Dragons.")
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
Accessing the Profile
To access the current user's profile in your view, just use the User instance provided by the request, and call get_profile on it:
def your_view(request):
profile = request.user.get_profile()
...
# Your code
Basically django User models will provide access only for the fields ( firstname,lastname,email,password,is_staff,is_active,last_login).
However if we want to add any extra fields to this model, say we need to add a new column named dateofbirth for every user, then we need to add a column named DOB into User model. But this is not possible as we aren't able to edit django User models.
To achieve this either
1.We can have a separate new table with email id & DOB column, such that a column in User model is mapped with a column in the new table. But this will create a new db instance for every db request. Say if u want to find the DOB of a customer,
First we need to fetch the value of mapped id of a customer from the
User table.
WIth the above value, get DOB from the new table.
In the second method,
Instead of using django User model, use your own customize model with all the fields needed. However if any updation related to security or some enhancement made to django User model we can't use it directly. We need to do more code changes at our end( wherever we use our customize models.) This will be a bit pain for a developer to identify the code & make changes.
To overcome the above issues, django introduce django profile which is very simple and more flexible. The advantages are
Updation/enhancement to the User model can be applied without modifying the code much
No need of creating new db instance to fetch the extra values.
Since the field has onetoone mapping deletion of data from one table will delete others also.
More secure, since we use django models ( no sql injection)
How to Use this:
In settings.py create a variable AUTH_PROFILE_MODULE = "appname.profiletable"
In models.py, create a new table with the fields needed and make sure that the id in User model is onetoone mapped with new table.
create a signal which inserts a row into the new table whenever a new entry is added into User model.
The value in the new table can be accessed using User object itself.
Say, we created a new table extrauser which has DOB, emailid. To find the DOB of a customer, use
a=User.objects.get(email='x#x.xom')
a.get_profile().DOB will give the dateofbirth value from extrauser table.
Hope the above details make you clear in understanding django profile. Incase of any help further, let me know. I have used django profile in my project.
Old question but I thought anyone seeing it today may benefit from this:
Django 1.5 adds the ability to - easily - extend the User model. This may be preferable as you now only got one object to deal with rather than two! Seems the more modern way.
https://hurricanelabs.com/blog/django-user-models/
You need to specify which class is your "Profile" by setting AUTH_PROFILE_MODULE = 'accounts.UserProfile' (for example)
https://docs.djangoproject.com/en/1.4/topics/auth/

Do I need to create a separate class in my models.py when using the django.contrib.auth.models import user?

The import statement import the needed parts. but is the "user" class already made when you put that into your installed apps? or do you still need to clarify in models.py in order to make the table in the db? or can someone expand on how to use django users and sessions? I'm looking over the django docs right now and they all just go over how to use the thing once. they never put the code in a syntax where users are going to be the ones using the code through a browser and not you through a python shell.
All installed apps can contribute to the database schema. django.contrib.auth.models contributes, among others, the auth_user table behind the django.contrib.auth.models.User model, therefore you do not have to worry about recreating it unless you have a specific reason to do so.
There's a number of things going on here. As you're aware, Django comes with a number of "contrib" packages that can be used in your app. You "activate" these by putting them into your INSTALLED_APPS.
When you run python manage.py syncdb, Django parse the models.py files of every app in INSTALLED_APPS and creates the associated tables in your database. So, once you have added django.contrib.auth to your INSTALLED_APPS and ran syncdb, the tables for User and Group are there and ready to be used.
Now, if you want to use these models in your other apps, you can import them, as you mention, with something like from django.contrib.auth.models import User. You can then do something like create a ForeignKey, OneToOneField or ManyToManyField on one of your models to the User model. When you do this, no tables are created (with the exception of ManyToManyField; more on that in a bit). The same table is always used for User, just as for any of your own models that you might create relationships between.
ManyToManyFields are slightly different in that an intermediary table is created (often called a "join table") that links both sides of the relationship together. However, this is purely for the purposes of that one particular relationship -- nothing about the actual User table is different or changed in any way.
The point is that one table is created for User and this same table is used to store all Users no matter what context they were created in. You can import User into any and all of your apps, create as many and as varied relationships as you like and nothing really changes as far as User is concerned.
If the table name or something else does not fit in your needs you can always just extend the User model.
from django.contrib.auth.models import User
class Employee(User):
...
Any class extending Model class in models.py contributes to database schema. That means, django search your (and also django core) model.py files and looks for any class that extends Model like:
some models.py
class SomeModel(Model):
...
...
class Otherthing(Model):
...
that is also applies for django core code files. Since all Database tables named using application label and model name, database ables created by django also have that...
For example,
from django.contrib.auth.models import User
If you track file hierarchy django -> contrib -> auth and open models.py file, you will see related model. Ther are also other Model classes in here, like Permission and Group models.
Since these models are under auth application, database tables are auth_user, auth_perission and auth_group
When you run manage.py syncdb command for the first time, django will create these tables...

Categories

Resources