How to query reverse foreign key in django? - django

I am trying to filter queryset for a reverse foreign key.
Here are my two models:-
class BranchModel(basemodel.BaseModel):
company = models.ForeignKey(CompanyModel, on_delete=models.PROTECT)
name = models.CharField(max_length=30, default="Head Office")
user = models.ForeignKey(User, on_delete=models.PROTECT, related_name='branch_owner')
class User(AbstractUser):
id = models.UUIDField(
primary_key=True, default=uuid.uuid4, editable=False
)
objects = UserManager()
I want to get all the users of a branch.
I tried to use this queryset:-
User.objects.filter(branchmodel__user=self.request.user)
but it is giving me empty result.
how can i modify this?

I assume you want all branches of user as per your model setup. Below code will gives you all branches of request.user
user=self.request.user
prtnt(user) # to check user in terminal
userbranches=user.branch_owner.all()

Related

Django model order the queryset based on booleanfield True/False that related with User FK profile

I have two django models as follows:
The first one is a user profile, which has a FK to User model:
class Profile(models.Model):
PRF_user = models.OneToOneField(User, related_name='related_PRF_user', on_delete=models.CASCADE)
PRF_Priority_Support = models.BooleanField(default=False)
and the second is ticket model which has a FK to User model:
class ticket(models.Model):
ticket_status_options = [
('open', 'open'),
('wait_customer_reply', 'wait_customer_reply'),
('replied_by_staff', 'replied_by_staff'),
('replied_by_customer', 'replied_by_customer'),
('solved', 'solved'),
]
TKT_USER = models.ForeignKey(User, related_name='TKT_USER', on_delete=models.CASCADE)
TKT_DEB = models.ForeignKey('Site_departments', related_name='related_ticket_department', on_delete=models.CASCADE)
TKT_SUB = models.CharField(max_length=50, db_index=True, verbose_name="ticket subject")
TKT_BOD = models.TextField(verbose_name="ticket body")
TKT_image_attachment = models.ImageField(upload_to='TKT_img_attachment', blank=True, null=True , default=None)
TKT_CREATED_DATE = models.DateTimeField(auto_now_add=True)
TKT_UPDATED_DATE = models.DateTimeField(auto_now=True)
I want to sort the tickets based on user profile Priority_Support:
If the user profile PRF_Priority_Support is True, I want to sort it first inside my views QuerySet, otherwise (if PRF_Priority_Support is False) I want to sort it normally.
How can I do this?
You should name your model starting with a capital letter.
And for ordering the tickets, you can use something like this:
' queryset_list = ticket.objects.order_by('-TKT_USER__related_PRF_user__PRF_Priority_Support')
In filtering, when you want to span relationships, you use double underscore __ .
More on this here:
https://docs.djangoproject.com/en/3.1/topics/db/queries/#lookups-that-span-relationships
Another way is adding ordering to your model's Meta class.
For Example:
MyModel(models.Model):
class Meta:
ordering = ('-my_boolean_field ',)
Hi you should filter as follow:
Model.objects.filter(field=True) or False depending on what you need
Regards

Filtering Django query filtering

I'm doing some querying currently and I was wondering if I would be able to query something from these 3 models where the return would give me all the projects the users are working on. I know about the basic filtering however thats not really enough in this case, how would one go about querying through 2 foreign keys.
class User(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
email = models.EmailField()
class ProjectUser(models.Model):
project = models.ForeignKey("Project", on_delete=models.CASCADE)
user = models.ForeignKey("User", on_delete=models.CASCADE)
is_lead = models.BooleanField(default=False)
class Meta:
unique_together = (("project", "user"),)
class Project(models.Model):
name = models.CharField(max_length=255)
client = models.CharField(max_length=255)
complete = models.BooleanField(default=False)
You can obtain the Projects a user is working on with:
Project.objects.filter(
projectuser__user=user
)
The double underscores are used to look "through" relations. Furthermore the default related_query_name=… parameter [Django-doc] is, if not specified, the name of the model in lowercase.

Django model unique=True not throwing any error which used in atomic transaction

Scenario:
I am trying to create/insert data to Django model (POSTGRES database) employee and profile.
When I insert duplicate records (i.e. with duplicate work_email and duplicate employee_id) I am expecting a database error in an atomic transaction.
However, the below code doesn't throw any error, but when I see the database table no duplicate is created.
Dropped a database and created a new DB and new migrations to make sure there is no problem with the sync. However, the result is the same with no errors.
Any help is appreciated. Thanks
class Employee(models.Model):
"""
Employee table containing all the employee information.
"""
profile = models.OneToOneField(Profile, on_delete=models.CASCADE)
id = models.CharField(max_length=50, unique=True, blank=False, default=uuid.uuid4, editable=False, db_index=True)
employee_id = models.CharField(
max_length=100,
blank=False,
unique=True,
primary_key=True,
error_messages={'employee_id': "A user with employee id already exists."}
)
class Profile(AbstractUser):
"""
Enhancing user model with additional fields. This is in relation with a table ProfileExtras.
Extras can be utilised to add any fields to further enhance Profile with key value pair.
"""
email = None
date_of_birth = models.DateField(blank=False)
work_email = models.EmailField(
max_length=50,
blank=False,
unique=True,
db_index=True,
error_messages={'work_email': "A user with work email already exists."}
)
def create_employee(app_context, data_dict):
try:
with transaction.atomic():
employee_model = models.Employee()
profile_model = models.Profile()
# Data insertion logic
# e.g. setattr(employee_model, "first_name", "xxxxxx")
employee_model.profile = profile_model
profile_model.save()
employee_model.save()
except Exception as e:
log.error(e)
raise e
Found the solution. I was testing with Django test. It is found that data is not retained between each test, hence the duplicate error is not raised.

Best practices for extending Custom User Model in django

I have a Custom User model in my app
class User(AbstractBaseUser, PermissionsMixin):
uuid = models.UUIDField(default=uuid.uuid4, unique=True)
email = models.EmailField(_('email address'), db_index=True, unique=True)
and this AUTH_USER_MODEL = 'users.User' in my settings file.
Now I want to create a model on the top of this custom user model(User), lets call it Agent, this model will have three columns:
user_uuid #Foreign Key Refernce(OnetoOne) to the Custom User Model
uuid # unique identifier for Agent model
scope # CharField specific to Agent model
What is the best way to do that?
While there is no best practice, it all depends on what you are doing, the most likely to work method is a type field specifying Agent and a one-to-one table (docs) for extra fields.
It'll be up to you to create the records as-needed. There isn't anything special about what you are doing just because it is a user.
class AgentDetails(Model):
user = OneToOneField(User, primary_key=True, on_delete=CASCADE)
...
A more complete user model would look something like this:
class User(AbstractBaseUser, PermissionsMixin):
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = ["name"]
email = EmailField(unique=True, db_index=True)
name = CharField(max_length=100)
type = ChoiceField(choices=[('user','User'),('agent','Agent')])
is_staff = models.BooleanField(default=False, help_text='If the user can log into this admin site.')
is_active = models.BooleanField(default=True, help_text='If the user is active, instead of deleting')
created_at = models.DateTimeField('Date Joined', default=timezone.now)
objects = MyUserManager() #
In addition, you are probably going to need to add:
Custom admin page
Custom UserManager
You can derive one table from an abstract base, but this will generate 1 table for each user type which will not work with the standard authentication. For info, see Django's Model Inheritance.
class User(Model):
email = EmailField()
class Meta:
abstract = True
class Agent(User): # generates table 1
extra_field = CharField()
class Standard(User): # generates table 2
extra_field = CharField()
If the user model you have given is complete, then I don't think it will work with the default django infrastructure. From your question its not clear if you need help on that.

Table Master and details with same foreign django

I am trying to create two models in django, Reservation and DetailsReservation, i need that models has a same userReservation .Example if i create a Reservation with id: 1 and User: 4, when create a Details with Reservation 1, should copy user in userbyReserva
class Reservation(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
userReservation = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
class DetailsReservation(models.Model):
Reservation = models.ForeignKey(Reservation, blank=False, on_delete=models.CASCADE, null=True)
userbyReserva = #same user that do reservate
You can access the user through the Reservation using a method as property. This is the easiest way to do that.
Some notes about the code:
always use a lower case name for the fields and without the camelNaming.
Avoid plurals on the models' name.
I would avoid using default=1 in a ForeignKey. Better raise an error if the relation is not set. (What happen if the User=1 is deleted?)
Do not copy the data if not necessary, you can use properties to access related field. The user is available only if a reservation is related to the DetailReservation object; detail_reservation.user will return None if the reservation is not set.
I don't understand why you created the reservation relation optional from DetailReservation.
Have a look
class Reservation(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(User, on_delete=models.CASCADE, )
class DetailReservation(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
reservation = models.ForeignKey(Reservation, blank=False, related_name='details',
on_delete=models.CASCADE, null=True)
#property
def user(self):
return reservation.user if reservation else return None