Error in Inherit BaseUser in Django 1.7b4 - python

I'm trying to add a custom field to already existed django's User model.
I want all fields of default User model(including password hashing functionality) + a custom field has_car, so I did ...
class MyUser(AbstractBaseUser):
has_car = models.BooleanField(default=False)
and register in admin panel admin.site.register(MyUser)
when I try to add open this model in admin panel I get this error.
OperationalError at /admin/myapp/myuser/
(1054, "Unknown column 'myapp_myuser.id' in 'field list'")
I'm not sure if its a mysqldb error or what?
I know I can use OneToOne or ForeignKey field but I simply want to extend User model.
again, It django==1.7b4 + Mysql

If you're just looking to add custom fields to the standard User model, your user model should inherit from AbstractUser instead of from AbstractBaseUser.
Don't forget to set:
AUTH_USER_MODEL = 'myapp.MyUser'
https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-django-s-default-user

Related

Password is displayed as text in the admin panel (not hashed)

There is a CustomUser model inherited from AbstractUser. When registering a model in the admin panel, the password is displayed as text, that is, the type of this field is text, not password. I know that this problem can be solved if, together with the model, the ModelAdmin class is registered, in my case it will be CustomUserAdmin inherited from UserAdmin from django.contrib.auth.admin, and the password will be displayed correctly, but then the fields from CustomUser will not be displayed (as if the CustomUser model is registered, but only the fields of the User model will be displayed, when using a class inherited from the above-mentioned UserAdmin). What to do with this, please tell me!
you need to import django's function "make_password" if you need make a password:
from django.contrib.auth.hashers import make_password
and when you save the password in the db, do the following:
password=make_password(form.cleaned_data['password']),
django has already declared field for password user, you dont need to declared it again in the model that inherits AbstractUser.

How to run custom model validations for M2M in clean() when adding a new model instance

I have a model in Django with a ManyToManyField relationship to another model. Something that looks like this:
class MyModel(models.Model):
id = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4)
models = models.ManyToManyField(
OtherModel,
related_name='my_models',
)
In my clean() method, I have a bunch of custom validation rules that are run in the model fields. Some of them actually run in the ManyToManyField. All validations work fine when creating model instances with an uploader tool that parses data from a csv into a model instance or when saving an existing model in the Admin.
However, I want to be able to add model instances directly in the Admin but because of the ManyToMany relationship, which I found out that is not set until after the save() method, some validations throw a ValueError: "<MyModel: Some Model>" needs to have a value for field "id" before this many-to-many relationship can be used. ([ref][1])
Then, what I did is a very ugly hack to to the validation in the clean() method to bypass it by catching the ValueError:
def _some_validation(self):
try:
if self.my_models.count() == 0:
raise ValidationError("This is an error message thrown by ...")
except ValueError as e:
print(e)
Then it works fine to add a model instance via Admin, however, it doesn't run the validation on the ManyToMany field, allowing for inconsistent data.
Is there a way that I can re-run the clean() method after the M2M relationship is set when creating a new model instance via the add_form in the admin?
Note: I am not using custom forms as I found no need since the Django's default generated add form in the Admin satisfies my needs.
[1]: https://docs.djangoproject.com/en/3.1/topics/db/examples/many_to_many/
You can try to listen to the m2m_changed signal
def my_models_changed(sender, **kwargs):
# Do something
pass
m2m_changed.connect(my_models_changed, sender=MyModel.my_models.through)
https://docs.djangoproject.com/en/3.1/ref/models/relations/#django.db.models.fields.related.RelatedManager.add
https://docs.djangoproject.com/en/3.1/ref/signals/#django.db.models.signals.m2m_changed

Storing new field to Django Admin "user" section from registration form

I have managed to add an additional field to the Registration form, "where did you hear about us?".
But I am not sure which files to edit in order to store the data from this field along with the users info.
i.e. When logging into the Admin section and go to "users" and view a users info I would like to see this field there.
Simplest way would be to store additional data in a UserProfile model about the user, e.g.
from django.contrib.auth.models import User
class UserProfile(models.Model):
# This field is required.
user = models.OneToOneField(User)
# Other fields here
where_heard_about_us = models.TextField()
You can then register the object as an inline object in your Django Admin

Django AbstractUser Inheritence Error

I'm still pretty new to Django, and have been having a problem defining my own user model that inherits from the Abstract User in Django. However, I have users already in the databse (with only usernames and passwords) and when I try to migrate the changes, I get the error that the email field is required and doesn't have a default value.
What confuses me is that I looked it up in the docs, and at https://docs.djangoproject.com/en/1.7/ref/contrib/auth/ the email field is clearly listed as optional. Furthermore, when I try to override the email field I get an error that my field clashes with the existing one.
Why is it giving me this error, and how do I fix it?
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserProfile(AbstractUser):
additionalFields = models.IntegerField(default=0)
def __unicode__(self):
return self.username
EmailField is a text field in the database, and 'empty' text fields are saved as an empty string (''). They are not empty (NULL) on a database level, and the column is defined as NOT NULL. What you need to do is set a default of '', then the migration will work.

Extending Django Auth User model

admin.py
class NetUserInline(admin.StackedInline):
model = NetUser
class UserProfileAdmin(UserAdmin):
inlines = [NetUserInline, ]
admin.site.register(User, UserProfileAdmin)
models.py
class NetUser(AbstractUser):
Net_30 = models.BooleanField(default=False)
site.register(NetUser)
im getting error like this.
django.core.management.base.CommandError: One or more models did not validate:
accounts.netuser: Accessor for m2m field 'groups' clashes with related m2m field 'Group.user_set'. Add a related_name argument to the definition for 'groups'.
accounts.netuser: Accessor for m2m field 'user_permissions' clashes with related m2m field 'Permission.user_set'. Add a related_name argument to the definition for 'user_permissions'.
auth.user: Accessor for m2m field 'groups' clashes with related m2m field 'Group.user_set'. Add a related_name argument to the definition for 'groups'.
auth.user: Accessor for m2m field 'user_permissions' clashes with related m2m field 'Permission.user_set'. Add a related_name argument to the definition for 'user_permissions'.
The Django User model is automatically part of any Django project. That is to say that the User model will create all database tables that are part of it at the same time you run syncdb. You have subclassed AbstractUser for your NetUser class, meaning that all the fields that are part of AbstractUser are part of NetUser as well. So, right now your database has tables such as this...
User
username
password
email
...
NetUser
username
password
email
...
net_30
As part of Django's user administration, database tables are created that manage what groups/permissions users have within your application(s). Right now it appears that this system is attempting to connect to both the standard User model and your NetUser model. I'd assume this is because by subclassing AbstractUser Django attempts to create all relations to that user model. At the same time, if you haven't specified that you are using a custom user model then Django will be attempting to do the same to the standard user model.
The documentation states you must specify what you are using for a user model if not the default by adding AUTH_USER_MODEL = 'Accounts.NetUser' to your settings.py file. This tells your Django project that you are using a custom User model and not connect to the standard User model. Right now both are happening.
Furthermore, you should change admin.site.register(User, UserProfileAdmin) to admin.site.register(NetUser, UserProfileAdmin) so that your Admin backend is looking at your custom User model and not the standard Django User model.
You probably forgot to set AUTH_USER_MODEL in settings.py
AUTH_USER_MODEL = 'myapp.NetUser'
docs: substituting-a-custom-user-model
PS: However using some kind of profile imho is generally less painful )

Categories