My models look like this:
class UserDevice(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=False)
device = models.ForeignKey(Device, on_delete=models.PROTECT, null=False)
activation_date = models.DateTimeField(default=timezone.now, null=False)
friendly_name = models.CharField(max_length=20, null=True, blank=True)
is_owner = models.BooleanField(null=False, default=False)
is_admin = models.BooleanField(null=False, default=True)
is_alerts_enabled = models.BooleanField(null=False, default=True)
timeStamp = models.DateTimeField(auto_now = True, null=False)
class UserProfile(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=False)
token = models.TextField(null=False, blank=True)
first_name = models.TextField(null=True, blank=True)
last_name = models.TextField(null=True, blank=True)
timeStamp = models.DateTimeField(auto_now = True, null=False)
I need to get device, user, is_alerts_enabled, is_admin, is_owner from UserDevice and first_name, last_name, token from userProfile. This is what I have so far and it gives me what I need from userdevice but I can't figure out how to add the userprofile stuff.
nonOwners = UserDevice.objects.filter(device=device, is_owner=False)
if nonOwners is None:
return errormsg('non nonOwners found for this device')
nonOwnersArray=[]
for nonOwner in nonOwners:
nonOwner_data = model_to_dict(nonOwner,
fieldlist=(
'device.serial',
'user.email',
'is_alerts_enabled',
'is_admin',
'is_owner',
),
rename={
'device.serial': 'serial',
'user.email': 'email'})
nonOwnersArray.append(nonOwner_data)
Any help would be greatly appreciated. Thanks!
The best way to get a dictionary of values is to use values().
UserDevice.objects.filter(device=device, is_owner=False).values('device', 'user', 'is_alerts_enabled', 'is_admin', 'is_owner')
The above line will give you the relevant fields of the UserDevice model as dictionary values.
If you add a foreign key to UserDevice (here I have changed the user field):
class UserDevice(models.Model):
user = models.ForeignKey(UserProfile, on_delete=models.PROTECT, null=False)
device = models.ForeignKey(Device, on_delete=models.PROTECT, null=False)
activation_date = models.DateTimeField(default=timezone.now, null=False)
friendly_name = models.CharField(max_length=20, null=True, blank=True)
is_owner = models.BooleanField(null=False, default=False)
is_admin = models.BooleanField(null=False, default=True)
is_alerts_enabled = models.BooleanField(null=False, default=True)
timeStamp = models.DateTimeField(auto_now = True, null=False)
You may do this:
UserDevice.objects.select_related('user').filter(device=device, is_owner=False).values('device', 'user', 'is_alerts_enabled', 'is_admin', 'is_owner', 'user__first_name', 'user__last_name', 'user__token')
I have used select_related() to avoid hitting the database unnecessarily.
Related
I get such an error while migrating to a database:
return Database.Cursor.execute(self, query)
django.db.utils.OperationalError: foreign key mismatch - "user_auth_customer"
referencing "user_auth_profile"
I have checked Foreign_Keys of my models and they look good.
I have no idea why I receive that error :(
Please, help me out here.
class Customer(AbstractUser):
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = UserManager()
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
profile = models.OneToOneField("Profile", related_name="user_profile",
on_delete=models.CASCADE, null=True)
first_name = models.CharField(max_length=50, null=True, blank=True)
last_name = models.CharField(max_length=50, null=True, blank=True)
username = models.CharField(max_length=30, null=True, blank=True)
phone = models.CharField(max_length=10, default='', null=True, blank=True)
email = models.EmailField(validators=[validators.EmailValidator()],
unique=True)
password = models.CharField(max_length=100, null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True)
#staticmethod
def get_customer_by_email(email):
try:
return Customer.objects.get(email=email)
except:
return False
def isExists(self):
if Customer.objects.filter(email=self.email):
return True
return False
class Meta:
verbose_name = 'Customer'
verbose_name_plural = 'Customers'
class Profile(models.Model):
first_name = models.CharField(max_length=50, null=True, blank=True)
last_name = models.CharField(max_length=50, null=True, blank=True)
phone = models.CharField(max_length=10, default='', null=True, blank=True)
email = models.EmailField(primary_key=True, unique=True, validators=[validators.EmailValidator()])
password = models.CharField(max_length=100, null=True, blank=True)
# Add a photo field
owner = models.OneToOneField(Customer, related_name='profile_owner',
on_delete=models.SET_NULL, null=True)
username = models.CharField(max_length=30, null=True, blank=True,
validators=[UnicodeUsernameValidator()])
date_created = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'Profile'
verbose_name_plural = 'Profiles'
if you need any else details, I can provide you with those in the comments.
You can't have both ways OneToOneField. Choose one way.
If you delete Customer's profile field, then still you will have possibility to call relation with:
customer = Customer.objects.get(id=1)
customer.profile # that will call Customer's related Profile object
Assuming, that you will change related_name='profile_owner' to simpler related_name='profile'.
Read more about OneToOneRelationships.
Default User Model:
class User(AbstractBaseUser, PermissionsMixin):
avatar = models.ImageField(upload_to='user/avatar', null=True, blank=True)
date_joined = models.DateField(auto_now_add=True)
username = models.EmailField(unique=True, null=False, blank=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_employer = models.BooleanField(default=False)
is_employee = models.BooleanField(default=False)
object = managers.UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = []
class Meta:
verbose_name = 'User'
verbose_name_plural = 'Users'
Employer model:
class Employer(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True)
name = models.CharField(max_length=256, blank=False, null=False)
address = models.CharField(max_length=256, blank=False, null=False)
fax = models.DecimalField(max_digits=11, decimal_places=2, blank=True, null=True)
email = models.EmailField(unique=True, blank=False, null=False)
economic_code = models.DecimalField(max_digits=20, decimal_places=2, blank=True, null=True)
national_id = models.DecimalField(max_digits=20, decimal_places=2, blank=True, null=True)
Employee model:
class Employee(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True)
employer = models.ForeignKey(Employer, null=False, blank=False, on_delete=models.CASCADE)
first_name = models.CharField(max_length=50, null=False, blank=False)
last_name = models.CharField(max_length=100, null=False, blank=False)
national_id = models.PositiveIntegerField(null=False, blank=False)
date_of_birth = models.DateField(blank=False, null=False)
post = models.CharField(max_length=100, null=True, blank=True)
mobile = models.DecimalField(max_digits=11, decimal_places=2, null=False, blank=False)
personnel_code = models.PositiveIntegerField(null=True, blank=True)
eligible_leave = models.FloatField(default=0, blank=False, null=False)
sick_leave_per_month = models.FloatField(default=0, null=False, blank=False)
rfid_card_code = models.CharField(max_length=256, blank=False, null=False)
I want the employer to be authenticated by email and the employee by national code (username filed). How?
you need a custom authentication backend. let's name it backends.py
from django.contrib.auth.backends import ModelBackend
class EmployeeAuthentication(ModelBackend):
"""
Employee Backend
Allows a user to sign in using national_id and password.
"""
def authenticate(self, request, **kwargs):
national_id = kwargs.get('username')
password = kwargs.get('password')
try:
employee = Employee.objects.get(national_id=national_id)
if employee.user.check_password(password) is True:
return employee.user
except Employee.DoesNotExist:
pass
class EmployerAuthentication(ModelBackend):
"""
Employer Backend
Allows a user to sign in using email and password.
"""
def authenticate(self, request, **kwargs):
email = kwargs.get('username')
password = kwargs.get('password')
try:
employer = Employer.objects.get(email=email)
if employer.user.check_password(password) is True:
return employer.user
except Employer.DoesNotExist:
pass
and in settings.py
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'app.backends.EmployerAuthentication',
'app.backends.EmployeeAuthentication',
]
I have a CustomUser model, and a Blog model.
CustomUser model:
class CustomUser(AbstractUser):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=20, default="", blank=True)
last_name = models.CharField(max_length=20, default="", blank=True)
address = models.CharField(max_length=150, default="", blank=True)
city = models.CharField(max_length=20, default="", blank=True)
zip_code = models.CharField(max_length=20, default="", blank=True)
country = models.CharField( max_length=50, default="", blank=True, choices=settings.COUNTRIES_LIST)
about_me = models.TextField(max_length=225, default="", blank=True)
photo_url = models.TextField(null=True)
is_active = models.BooleanField(default=True) # can login
Blog model:
class Blog(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1, null=True, verbose_name=_('user'), related_name="%(class)s_blogs", on_delete=models.SET_NULL)
blog_id = models.CharField(max_length=150, null=False, default=get_id, unique=True, editable=False)
blog_title = models.CharField(max_length=150, null=False)
blog_description = models.TextField(max_length=300, null=True, blank=True)
created_at = models.DateTimeField(auto_now=False, auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True, auto_now_add=False)
blog = FroalaField()
dynamic_link = models.CharField(max_length=225, null=False, default="")
blog_type = models.CharField( max_length=50, null=False, choices=BLOGSTYPE_LIST)
blog_status = models.CharField(max_length=150, null=False, default="unapproved")
is_active = models.BooleanField(default=False)
is_featured = models.BooleanField(default=False)
My understanding is that I could use the related_name to get all blogs by a user.
>>> from users.models import CustomerUser
>>> user = CustomUser.objects.get(pk=1)
>>> user.blog_blogs.all()
<BlogQuerySet []>
As you must have seen, this turns to always return but an empty queryset, even though there are blog entries by that user.
So is it am not understanding here?
Thank you.
I am new to Django and I need data from two models and would like to do it with one query. Here is what I have in sql that gives me exactly what I need. Can someone please show me how to do it in Django.
select api_userprofile.last_name, api_userprofile.first_name,
api_userdevice.is_admin,
api_userdevice.is_alerts_enabled,api_userdevice.is_owner from
api_userprofile
join api_userdevice on api_userdevice.user_id=api_userprofile.user_id
where api_userdevice.user_id=10 and api_userdevice.device_id=29
These are my 2 models:
class UserDevice(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=False)
device = models.ForeignKey(Device, on_delete=models.PROTECT, null=False)
activation_date = models.DateTimeField(default=timezone.now, null=False)
friendly_name = models.CharField(max_length=20, null=True, blank=True)
is_owner = models.BooleanField(null=False, default=False)
is_admin = models.BooleanField(null=False, default=True)
is_alerts_enabled = models.BooleanField(null=False, default=True)
class UserProfile(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=False)
token = models.TextField(null=False, blank=True)
first_name = models.TextField(null=True, blank=True)
last_name = models.TextField(null=True, blank=True)
Any help would be greatly appreciated.
There is easy way to do that:
User.objects.filter(userdevice__id=29, id=10).values('userdevice__is_owner', 'userdevice__is_admin', 'userdevice__is_alerts_enabled', 'userprofile__first_name', 'userprofile__last_name')
I am new to django and need to do a query. I can do in sql but I can't seem to figure it out in django. Here it is in SQL. Can someone tell me how to do it in django.
select token from api_userprofile
join api_userdevice on api_userdevice.user_id=api_userprofile.user_id
join api_device on api_device.id=api_userdevice.device_id
where api_device.serial=3
My models look like this:
class UserDevice(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=False)
device = models.ForeignKey(Device, on_delete=models.PROTECT, null=False)
activation_date = models.DateTimeField(default=timezone.now, null=False)
friendly_name = models.CharField(max_length=20, null=True, blank=True)
is_owner = models.BooleanField(null=False, default=False)
is_admin = models.BooleanField(null=False, default=True)
class Device(models.Model):
serial = models.CharField(max_length=16, null=False, unique=True)
publickey = models.CharField(max_length=44, null=False)
class UserProfile(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.PROTECT, null=False)
token = models.TextField(null=False, blank=True)
if i understand correctly, you can try:
users_pks = UserDevice.objects.filter(device__serial=3).values_list('user__pk')
qs = UserProfile.objects.filter(user__pk__in=users_pks).values('token')
for check sql query, you can print:
print (qs.query)