Created m2m fields values are assigned to all existing users - django

I try to create a user profile with a many to many relation.
Those are my models:
class Job(models.Model):
CARRYING = 'carrying'
CARRYING_FOR_MOVE_TOOLS = 'carrying_for_move_tools'
CHOICES = [
(CARRYING, 'yyyyyyyyy'),
(CARRYING_FOR_MOVE_TOOLS, 'xxxxxxxxxx'),
]
job = models.CharField(max_length=1000,
choices=CHOICES,
primary_key=True,
default='',
unique=True)
display_sort_key = models.FloatField(default=0.)
def __str__(self):
return self.get_job_display()
def get_slug_prefix(self):
return self.SLUG_PREFIX[self.job]
class Userprofile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
email = models.EmailField(max_length=70)
jobs = models.ManyToManyField(Job)
def __str__(self):
return self.email
When i create Jobs in the admnin panel or send the jobs via the client interface (Angular), all created jobs are assigned to all existing userprofiles.
How can i create a Jobs in Django admin panel without those jobs are assign to the all existing userprofiles?
or
How can i assign in Django Admin panel the Jobs-data send from Angular only to the userprofile of the logged user ?

Related

Why does Django not find a field added to the AbstractBaseUser

I've inherited from the AbstractBaseUser as follows:
class User(AbstractBaseUser):
"""
Main User model, inherits from AbstractBaseUser
"""
# Meta
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
username = models.CharField(max_length=40, unique=True) # equals to email
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
employee_of = models.OneToOneField(Customer, on_delete=models.SET_NULL, null=True)
So each User is linked to one and only one Customer.
Now within a view I want to access the instance of the current logged in user within the request object and get the employee_of value to get a queryset that contains all users of that customer.
def render_employees(request):
"""
Renders the employees page of the dashboard
:param request:
:return:
"""
# Return the value for the current site for css specific classes
dashboard_site = 'employees'
# Query the employees
qs_employees = User.objects.filter(employee_of=request.user.employee_of) # doesn't find field
...
However the filter doesn't work because request.user.employ_of doesn't seem to return anything. My IDE even suggests e.g. username, date_joined etc. but not employee_of.
Why's that?
class Customer(models.Model):
"""
A table that stores static data about a customer, usually a legal company
"""
legal_name = models.CharField(max_length=50)
street = models.CharField(max_length=30)
street_number = models.CharField(max_length=3)
def __str__(self):
return self.legal_name
Update:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from applications.customer.models import Customer
from django.conf import settings
BaseUser = settings.AUTH_USER_MODEL
class User(AbstractBaseUser):
"""
Main User model, inherits from AbstractBaseUser
"""
# Relations
user = models.OneToOneField(BaseUser, related_name='user_profile', on_delete=models.CASCADE, null=True) # link to default user model
employee_of = models.OneToOneField(Customer, on_delete=models.SET_NULL, null=True, blank=True)
I linked the user to the default user model via Django admin. However in the view im still not able to access employee_of within request.user
It seems that request.user is a different model. It's User model from django.contrib.auth. https://docs.djangoproject.com/en/4.0/ref/contrib/auth/#django.contrib.auth.models.User.
What you can do about it?
In our app we have UserProfile model that have OnetoOne relation to django User.
You can then store employee_of value there.
class UserProfile(AbstractBaseUser):
user = models.OnetoOneField("auth.User", related_name="user_profile", on_delete=models.CASCADE)
employee_of = models.OneToOneField(Customer, on_delete=models.SET_NULL, null=True)
and then access request.user employees using something like
request.user.user_profile.employee_of

If/when statement in django models to create another model field

I'm trying to create a model field that is a result of another model field. I am unable to articulate this properly, but I will try anyway.
I have employees who include everyone in the office, then I have a role for them too.
All the staff are Engineers, and a few of the Engineers are also Managers. so when creating an Employee, I have to select if they are just an Engineer or a Manager.
if the role is a Manager, then I want to create a model field as
manager = models.Charfield(???????????)
from django.db import models
class Roles(models.Model):
role = models.CharField(max_length=22)
def __str__(self):
return self.role
class Engineers(models.Model):
region = (
('SS', 'South-South'), ('SW', 'South-West'), ('SE', 'South-East'),
('NE', 'North-East'), ('NW', 'North-West'), ('NC', 'North-Central'),
)
firstname = models.CharField(max_length=20)
lastname = models.CharField(max_length=20)
email = models.EmailField(max_length=50)
username = models.CharField(max_length=20, unique=True)
phone = models.CharField(max_length=11)
position = models.ForeignKey(Roles, on_delete=models.DO_NOTHING, max_length=20)
workarea = models.CharField(max_length=20, choices=region)
manager = models.(if role selected = Manager), then the Employee name should be here
def __str__(self):
return self.firstname + ' ' + self.lastname
I'd appreciate any help or redirection to any resources that can help or any different way of doing this.
the manager field should be a dropdown of the list of existing employees with the Manager status.

Django - Creating a row in onther table before creating user

I have user, userprofile and company tables.
I want to create a record in company table and then assign the id of the newly created company in the userprofile foreign key before creating the user. I think it can be done using pre_save signal but I am unable to figure how. Please help.
Here's some details as AMG asked:
I have django's builtin user model
a userprofile model
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='profile_pics/default.jpeg', upload_to='profile_pics')
bio = models.TextField(blank=True, verbose_name='Biography')
company_name = models.ForeignKey(Company, on_delete=models.CASCADE)
a company model
class Company(models.Model):
name = models.TextField(blank=True, verbose_name="Company Name")
nof = models.IntegerField(verbose_name="No. of Employees")
All three are related user and userprofile has one to one relationship, and userprofile and company has many to one relationship.
I want Company record to be created first and than that new record's reference needs to be put into userprofile.
I think I have made it clear now.
Exactly, you can use pre_save for this. You can just put this in models.py below your defined models.
from django.db.models.signals import pre_save
#receiver(pre_save, sender=Profile) # register your model to the signal pre_save
def my_callback(sender, instance, *args, **kwargs):
if not instance.company_name: # check if instance has a value for company_name
company = Company.objects.create(
name='Test',
nof=1
)
instance.company_name = company
OR
Create a default value through a function.
class Company(models.Model):
name = models.TextField(blank=True, null=True, verbose_name="Company Name") # set blank=true and null=true so you can save an empty instance
nof = models.IntegerField(blank=True, null=True, verbose_name="No. of Employees")
def profile_company_default():
return Company.objects.create()
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='profile_pics/default.jpeg', upload_to='profile_pics')
bio = models.TextField(blank=True, verbose_name='Biography')
company_name = models.ForeignKey(Company, on_delete=models.CASCADE, default=profile_company_default) # add function as default value
EDIT
To edit company after save.
profile = Profile.objects.create(key="value")
profile.company.name = "Company Name"
profile.company.nof = 5
profile.save()

Django admin precompile a field with current logged in user in add form

In my django app i have a model like thisone:
class temp_case(models.Model):
id = models.AutoField(primary_key=True)
main_id = models.ForeignKey(temp_main, related_name="tm_tc", on_delete=models.CASCADE, verbose_name="Main Template")
descr = models.CharField(max_length=200, verbose_name="Case description")
dt = models.DateTimeField(auto_now=True, verbose_name="Created")
owner = models.ForeignKey('auth.User', related_name='tcase_owner', on_delete=models.CASCADE, verbose_name="API Owner")
well, when i go in my admin interface ad add a row, i would that field owner (models.ForeignKey('auth.User', related_name='tcase_owner', on_delete=models.CASCADE, verbose_name="API Owner") would automatically default populated with the current logged in user instead select it manually every time.
I have to manage my admin.py file? or directly into model?
so many thanks in advance
Overwrite ModelAdmin.get_changeform_initial_data:
#admin.py
class TempCaseAdmin(models.ModelAdmin):
def get_changeform_initial_data(self, request):
return {'owner': request.user}
admin.site.register(temp_case, TempCaseAdmin)

How to change a field that automatically affect other records in Django

How to change a field in a specific record that automatically affect the same field on other records?
Consider the following model:
class AccountUser(models.Model):
ADMIN='A'
USER='U'
USER_PROFILES = (
(ADMIN, 'Admin'),
(USER, 'User'),
)
account = models.ForeignKey(Account, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
profile = models.CharField(max_length=1,choices=USER_PROFILES,default=USER)
current_account = models.BooleanField(default=True)
def __str__(self):
return format('{} ({})'.format(self.account.name, self.user.username))
This is a many-to-many relation between users and accounts, so users can be in many accounts but every user can have one and only one current account. Then, everytime a new record is created or updated with current_account = True, any other records from the same user should be updated with current_account = False.
I've saw a similar question in Actions triggered by field change in Django, but it is for changes in the same record.
I think that you can achieve this with post_save signals. I hope i understood the logic you mean, but you can simply refactor the post_save staticmethod to achieve your objective.
from django.db.models.signals import post_save
class AccountUser(models.Model):
ADMIN='A'
USER='U'
USER_PROFILES = (
(ADMIN, 'Admin'),
(USER, 'User'),
)
account = models.ForeignKey(Account, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
profile = models.CharField(max_length=1,choices=USER_PROFILES,default=USER)
current_account = models.BooleanField(default=True)
#staticmethod
def post_save(sender, instance):
records = AccountUser.objects.filter(user = instance.user)
for record in records:
record.current_account = True
record.save()
def __str__(self):
return format('{} ({})'.format(self.account.name, self.user.username))
post_save.connect(AccountUser.post_save, sender=AccountUser)