Django1.5 Custom Users table - python

I'm trying to create a custom auth_users table with Django 1.5 following the intructions here:
https://docs.djangoproject.com/en/1.5/topics/auth/customizing/#auth-custom-user
But the code below doesn't seem to be working even though I have set the new columns it should contain. It still creates the same default table even after dropping the full database and python manage.py syncdb
I have read several documents and that is what I have right now:
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
class User(AbstractBaseUser):
identifier = models.EmailField(max_length=254)
first_name = models.CharField(max_length=254)
last_name = models.CharField(max_length=254)
USERNAME_FIELD = 'identifier'
REQUIRED_FIELDS = ['first_name','last_name']
This models.py is installed in settings.py
settings.py
AUTH_PROFILE_MODEL = 'myaccount.User'
This doesn't make any effect to the table, but it creates a new one called myaccount_user.
What's wrong with that? What should I change in order to modify auth_user table instead of creating a new one?

The error is that should be AUTH_PROFILE_MODEL = 'myaccount.User' instead of AUTH_PROFILE_MODULE = 'myaccount.User'
Also you forgot a bunch of methods in your Model and a USERNAME_FIELD
see a full example of how to build your own CUSTOM USER

Related

Django Model is creating another model after editing it [duplicate]

I have a model with OneToOneFiled named alg_id, and when I go to admin panel and change this filed in existing object, then a new object is created, but I'd like to overwrite same object with different alg_id.
When I change other simple text fileds - all works fine.
If I change alg_id to one, that already exists in Database, then that object gets overwritten - will be better if I'll get a warning here..
How could I achieve that?
ps. this project use 2.2.6 Django version
models.py :
from django.db import models
from django.utils.translation import gettext_lazy as _
class AchievementInfo(models.Model):
GROUPS = (
('Results', 'Results'),
('Service', 'Service'),
('Team', 'Team'),
('Development', 'Development')
)
algorithm_id = models.OneToOneField(
'core.Algorithms',
models.DO_NOTHING,
verbose_name=_('Alg id'),
primary_key=True,
)
role_key = models.CharField(_('Role'), max_length=25)
group = models.CharField(_('Group'), max_length=50, choices=GROUPS)
name = models.CharField(_('Name'), max_length=100)
web_name = models.CharField(_('Shown name'), max_length=75)
class Meta:
db_table = 'achievements_guide'
default_permissions = ()
ordering = ('web_name', 'role_key', 'algorithm_id')
verbose_name = _('Achievement')
verbose_name_plural = _('Achievements')
def __str__(self):
return f'{self.algorithm_id}: {self.name}, {self.web_name}, {self.role_key}'
admin.py:
from django.contrib import admin
from achievements.models import AchievementInfo
#admin.register(AchievementInfo)
class AchiAdmin(admin.ModelAdmin):
list_display = ("web_name", "group", "role_key", "algorithm_id")
list_filter = ("web_name", "role_key")
raw_id_fields = ("algorithm_id", )
Django tracks the object you're trying to edit or add only by a primary_key. If the newly set primary key matches some object in the database, this object will be replaced when saving the newly created object. Similarly, if you change your primary key and save the object, Django will not update the old one, but create the new one (or replace newly matching one, if applicable) instead.
As you are using your OneToOneField as a primary key for your object, what you want to achieve is not possible without a complex, additional logic when saving your object.
Instead, you can just create additional field as your primary key (or let Django do it for you by not using primary_key=True in any of the fields in your model), so Django can properly track by itself which object are you editing.

How to add one custom column in Django built in auth_user table

I'm trying to add one status field in my django auth_user(Built In) table. I'm using the below code.
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import User
class Auth_user(AbstractBaseUser):
status = models.CharField(max_length=12,unique=True)
USERNAME_FIELD = 'status'
An in the settings.py I'm mentioning like this.
AUTH_USER_MODEL = "accounts.Auth_user"
but the status field is not getting added in the table auth_user.Can somebody suggest how to add custom (column)field in Django in built table?
change the name of your class
instead of class Auth_user() you should use class User()
and also dont forget to migrate.
for more information go through this code given below
https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html
You have to create migration (python manage.py makemigrations) and then migrate the db (python manage.py migrate) for changes in models to be reflected in the database.
Extend the model as following -->
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
status = models.CharField(max_length=12,unique=True)
USERNAME_FIELD = 'status'
then create the make migrations file and migrate db

Effecient way to fetch related models count in Django ORM

I'm working on Django 1.10 and PostgreSQL9.6
I have two models in my project: Order and Customer. Also I'm using Django's auth.User to store login credentials.
Here is a code snipped:
from django.contrib.auth.models import User
from django.db import models
class Order(models.Model):
created_by = models.ForeignKey(User, null=True, on_delete=models.SET_NULL, related_name='created_orders')
# ... other fields ...
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
# ... other fields ...
Now, I need to show a table of customers and show a number of orders created by each of them.
The staight forward code is:
for customer in Customer.objects.all():
print(customer.user.created_orders.count())
Now I need to avoid N+1 problem and make Django to fetch all data with constant number of queries.
I've tried to write something like:
query = Customer.objects.select_related('user').annotate(
orders_count=Count('user.created_orders')
)
But this gives me an error like Cannot resolve keyword 'user.created_orders' into field.
Can you help me with this?
You should not use a dot (.) here, but two consecutive underscores (__):
query = Customer.objects.select_related('user').annotate(
orders_count=Count('user__created_orders')
)
Note that you do not need to .select_related('user') in order to annotate a queryset. If you however plan to use the .user later in your logic, it can indeed boost performance.

Django: Add new foreign key to existing model with default value as another foreign key from the same model

I recently started using Django, so please be patient. I have a model with 2 foreign keys
class Application(models.Model):
assessment_owner = models.ForeignKey(User, related_name='assessment_owner')
creator = models.ForeignKey(User, related_name='creator')
I am trying to add new foreign key called tech_lead to the same model, and default value for tech_lead should be assessment_owner. Later on, I can update the value for tech_lead using data load, but initially it should be assessment owner.
With following code snippet, Django asks for a default value while making migrations and assigns the same tech_lead everywhere. I would like to define default value for tech_lead through code, and simple default attribute doesn't work. I have tried using signals pre_save and post_save with no luck.
class Application(models.Model):
assessment_owner = models.ForeignKey(User, related_name='assessment_owner')
creator = models.ForeignKey(User, related_name='creator')
tech_lead = models.ForeignKey(User, related_name='tech_lead')
I am using Django 1.11.3 and postgreSQL.
Migration was successful with one-off default value.
Error Stack -
Env details
error
error
Thanks in advance.
tech_lead = models.ForeignKey(User, related_name='tech_lead')
breaks integrity because your database is already populated with Application instances. If you want to add a not nullable FK to your scheme, you should specify default value. Otherwise, if you can't provide default value, you should consider allowing tech_lead to be NULL, i.e:
tech_lead = models.ForeignKey(User, related_name='tech_lead', null=True)
then using data migration to populate field with values you want:
from django.db import migrations
def populate_tech_lead(apps, schema_editor):
Application = apps.get_model('yourappname', 'Application')
for application in Application.objects.all():
application.tech_lead = application.assessment_owner
application.save()
class Migration(migrations.Migration):
dependencies = [
('yourappname', '0001_initial'),
]
operations = [
migrations.RunPython(populate_tech_lead),
]
and then removing null=True from the field:
tech_lead = models.ForeignKey(User, related_name='tech_lead')
Step 1. add null=True to the tech_lead field as
class Application(models.Model):
assessment_owner = models.ForeignKey(User, related_name='assessment_owner')
creator = models.ForeignKey(User, related_name='creator')
tech_lead = models.ForeignKey(User, related_name='tech_lead', null=True)
Step 2. create migration file by python manage.py makemigrations
Step 3. migrate the db python manage.py migrate
Step 4. open django shell, python manage.py shell
Step 5. run the following script
from your_app.models import Application
from django.db.models.expressions import F
Application.objects.filter(tech_lead__isnull=True).update(tech_lead=F('assessment_owner'))

Django query extended USER table

I have a profile table which have a foreign key of the user.
class Profile(models.Model):
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
image = models.CharField(max_length=100)
user = models.ForeignKey(User)
I also have a COMMENT table which have a foreign key of the user.
class Comment(models.Model):
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
content = models.TextField()
user = models.ForeignKey(User)
I want to query the table COMMENT and also I want to get the image of the user which is in the PROFILE table. How can I query this in most effective way in django?.
thanks
If you are okay with changing ForeignKey to OneToOneField on Profile model then you can do it like,
Comment.objects.all().select_related('user__profile')
The above one selecting additional related-object data when it executes its query. This is a performance booster which results in a single more complex query but means later use of foreign-key relationships won’t require database queries.
Otherwise you can get it this way
for comment in Comment.objects.all():
print comment.user.profile_set.all()[0].image
If you're using Django = <1.4 the following is best practice:
comment = Comment.objects.get(pk=1)
comment.user.get_profile().image
Following the deprecation of native Profile model support (Django 1.5+) the following is still possible:
comment = Comment.objects.get(pk=1)
comment.user.profile.image
Django 1.5+ introduces custom auth models so you can do the following:
comment = Comment.objects.get(pk=1)
comment.user.image
At very least you should change your ForeignKey to a OneToOne relation for the user column on Profile, as Django =< 1.4 expects only one User Profile to be associated with a User.
References:
Django 1.4 get_profile: https://docs.djangoproject.com/en/1.4/topics/auth/#django.contrib.auth.models.User.get_profile
Django 1.5+ extending the user model:
https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#extending-the-existing-user-model

Categories