Django: reference model fields from another model - django

I have two models. What i need is to reference the name and the email field from the Users model to the Customer model fields. Is the following way correct?
class Users(AbstractBaseUser):
name = models.CharField(max_length=200)
email = models.CharField(max_length=200)
from users.models import Users
class Customer(models.Model):
user = models.OneToOneField(
Users, on_delete=models.CASCADE, null=True, blank=True)
name = models.OneToOneField(
Users.name, on_delete=models.CASCADE, null=True, blank=True)
email = models.OneToOneField(
Users.email, on_delete=models.CASCADE, null=True, blank=True)

class Users(AbstractBaseUser):
name = models.CharField(max_length=200)
email = models.CharField(max_length=200)
class Customer(models.Model):
user = models.OneToOneField(
Users, on_delete=models.CASCADE, null=True, blank=True)
That's all. Then you can do for example
Customer.objects.get(pk=1).user.name

Related

Django: Get objects of first model by comparing attribute of second OneToOne related model

I have two models, User and Card. One user has one card. I need to get objects of User if the 'card_written' of Card model is False in a view.
class User(model.Model):
phone = PhoneNumberField(null=False, blank=False, unique=True)
email = models.EmailField(verbose_name="email", max_length=60, unique=True)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class Card(models.Model):
user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
card_number = models.CharField(max_length=200)
card_written = models.BooleanField(default=False, null=False)
card_write_date = models.DateTimeField(null=True, blank=True)
card_delivered = models.BooleanField(default=False, null=False)
You can query on related models quite easily in Django by separating related fields by double underscores.
A query like this should work for you:
User.objects.filter(card__card_written=False)
Here card is the related name since you haven't specified it in the Card model if you want it to be something else you need to specify like so in the Card model:
user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE, related_name='something_else')

Django - how to create a new company and link it to the existing user

Good day all :)
I am new in Django world, Basically I have a three apps: CustomUsers , Company and Team with the following:
First a user creates an 'account' , then user create a new 'Company' and then a new'Team', my question is how to link the current user and the existing company to the new team ?
CustomUSer App:
class CustomUser(AbstractUser):
bio = models.CharField(max_length=300, null=True, blank=True)
image = models.ImageField(upload_to="userimages/", null=True, blank=True)
job_title = models.CharField(max_length=300, null=True, blank=True)
member_of_company = models.ForeignKey("company.Company", null=True, blank=True, on_delete=models.SET_NULL)
and Company App
class Company(models.Model):
title = models.CharField(max_length=200)
logo = models.ImageField(null=True, blank=True,upload_to="logos/")
website= models.CharField(null=True, blank=True, max_length=200)
and finally team app:
class Team(models.Model):
title = models.CharField(max_length=150)
members = models.ManyToManyField("accounts.CustomUser", blank=True, related_name='team_members')
company = models.ForeignKey("company.Company",
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='teams')
my questions are how to link the new "team" with the existing company and user.
Thanks in advance.

Django annotate with 'field' of 'related_name' of 'related_name'

I have three models : Domain Topic Post
Topic has a foreign key to Domain and Post has a foreign key to Topic.
Post has a field updated_on.
I want to annotate last_updated field in Domain queryset which would contain the latest post object from Post .
Edit 1: Added models definition:
class Board(models.Model):
name = models.CharField(max_length=30, unique=True)
description = models.CharField(max_length=50)
creation_time = models.DateTimeField(auto_now_add=True)
class Topic(models.Model):
subject = models.CharField(max_length=300, unique=True)
board = models.ForeignKey(Board, on_delete=models.SET_NULL, related_name='topics', null=True)
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, related_name='topics', null=True)
created_on = models.DateTimeField(auto_now_add=True)
views = models.PositiveIntegerField(default=0)
class Post(models.Model):
message = models.CharField(max_length=5000)
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, related_name='posts', null=True)
created_on = models.DateTimeField(auto_now_add=True)
topic = models.ForeignKey(Topic, on_delete=models.SET_NULL, related_name='posts', null=True)
updated_on = models.DateTimeField(default=timezone.now)

How to create relationships between django models

I have the two models, One is the User model and the other is a Contact model.
The Contact model is as follows:
class Contact(models.Model):
pass
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1, null=True, on_delete=models.CASCADE, verbose_name=_('User'), related_name="user")
contact = models.ForeignKey(settings.AUTH_USER_MODEL, default=1, null=True, on_delete=models.CASCADE, verbose_name=_('Contact'), related_name="contact")
created_at = models.DateTimeField(auto_now=False, auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True, auto_now_add=False)
is_contact = models.BooleanField(default=False)
Basically, what is does is create a contact for a user. Kind of a friend request and accept simple model. So the loggedIn user(request.user) could be either the contact.user or contact.contact.
And the settings.AUTH_USER_MODEL is a CustomUser model:
class CustomUser(AbstractUser):
pass
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)
How can I create a relationship, where I can get a users contact by doing something like this:
// get user contacts user=CustomUser.objects.get(pk=1)
user.contacts.objects.all()
Typically you query reverse relations using the related_name keyword, which is contact_set by default:
user.contact_set.all()
If you want to change the name of this reverse relationship, you need to do so in the Contact model using related_name:
class Contact(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="contacts", ...)
user.contacts.all()

Using two database tables for one control in Django Admin

I am creating a small application to help our Training Department manage their cirriculum using Django. When we talk about students we have two type; Employee and Customer.
Since all of the employees will be in auth_user I would rather not have to populate another table with that data. The behavior that I want is when a Class is displayed in the Django Admin I would like one control to be filled with data from two tables for the student list. Is this even possible in Django. My suspicion is that it is not. This is what I am messing around with:
from django.db import models
from django.contrib.auth.models import User
class Student(models.Model):
cell_phone = models.CharField(max_length=14)
class Meta:
abstract = True
class EmployeeStudent(models.Model, Student):
user = models.OneToOneField(User)
extension = models.CharField(max_length=4, null=True, blank=True, default=None)
class CustomerStudent(models.Model, Student):
first_name = models.CharField(max_length=25)
last_name = models.CharField(max_length=25)
email = models.CharField(max_length=25)
However, just thinking about it does it make more sense to do:
from django.db import models
from django.contrib.auth.models import User
class Student(models.Model):
user = models.ForeignKey(User, null=True, blank=True, default=None)
first_name = models.CharField(max_length=25, null=True, blank=True, default=None)
last_name = models.CharField(max_length=25, null=True, blank=True, default=None)
email = models.CharField(max_length=25, null=True, blank=True, default=None)
extension = models.CharField(max_length=4, null=True, blank=True, default=None)
I cringe at the thought of a blank record.
Any recommendations? Does it make sense to add everything to auth_user and leave the staff flag to false then just use a one to one field to map an auth_user to a Student? I do not really want to do that if I don't have to because I am not going to give anyone else access to the auth_user table so all additions to this table would need to be done by me.
You could try to use model inheritance (i.e User model inheritance : https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-user) for your Student model, or mixing Student(models.Model) with User in your EmployeeStudent and CustomerStudent models :
class Student(models.Model):
cell_phone = models.CharField(max_length=14)
class Meta:
abstract = True
class EmployeeStudent(User, Student):
user = models.OneToOneField(User)
extension = models.CharField(max_length=4, null=True, blank=True, default=None)
class CustomerStudent(User, Student):
first_name = models.CharField(max_length=25)
last_name = models.CharField(max_length=25)
email = models.CharField(max_length=25)
or :
class Student(User):
cell_phone = models.CharField(max_length=14)
class Meta:
abstract = True
class EmployeeStudent(models.Model):
user = models.OneToOneField(Student)
extension = models.CharField(max_length=4, null=True, blank=True, default=None)
class CustomerStudent(models.Model):
first_name = models.CharField(max_length=25)
last_name = models.CharField(max_length=25)
email = models.CharField(max_length=25)
If I understand correctly, you'd then want to display Customers as well as Employees in the same changelist in admin ? Using Student(User) with Employee / Customer as inlines might solve your problem.
Hope this helps,
Regards
This is a fairly common use-case (i.e. different types of userprofiles) in Django. In your case, I think the approach below would suit your scenario:
from django.db import models
from django.contrib.auth.models import User
class Student(models.Model):
STUDENT_TYPES = (
('E', 'EmployeeStudent'),
('C', 'CustomerStudent'),
)
user = models.OneToOneField(User, null=True, blank=True, default=None)
user_type = models.CharField(max_length=1, choices=STUDENT_TYPES)
class EmployeeDetails(models.Model):
student = models.OneToOneField(Student)
extension = models.CharField(max_length=4, null=True, blank=True, default=None)
class StudentDetails(models.Model):
student = models.OneToOneField(Student)
# BTW: all the fields below are redundant since they are already in User
first_name = models.CharField(max_length=25, null=True, blank=True, default=None)
last_name = models.CharField(max_length=25, null=True, blank=True, default=None)
email = models.CharField(max_length=25, null=True, blank=True, default=None)
This way, you can check the student.user_type and infer if you need to get EmployeeDetails or StudentDetails
NOTE:: Even though this is a recommended approach, it is not quite easy to enter data using the default admin interface in this manner. You might want to see how profile inlines are done to show the user profile fields in the admin as well.