I am trying to create a query using django models. I have 4 models. The functionality is to display all a person's facebook friends that are not already friends and do not have a friend request waiting.
CustomUserFriends
id,
from_customuser_id,
to_customuser_id,
FacebookProfile
id,
facebook_id,
custom_user_id
CustomUser
id,
name,
FriendRequests
id,
requester (user_id of the person requesting),
requestee (user_id of the person requested),
Now I have a list of facebook ids as a variable example
facebook_ids = [12123,45433,455664,44445]
Essentially the query im trying to create through django models is select all customusers that have a facebook id in the facebookprofile table but do not have the relationship of being a friend with the user already or have a pending friend request.
A friend is defined as having 2 records in the CustomUserFriends table, example
a friend relationship is
CustomUsers
id
1
2
CustomUserFriends
id from_custom_user_id to_custom_user_id
1 1 2
2 2 1
So, I wasn't entirely sure what you were trying to accomplish here. It was a toss up between getting all non-friends for a particular user or having a particular user and trying to find all of his friends who weren't friends with each other. I decided I'd do both and let you decide which one you wanted.
First, there are two functions. One is the main function we'll be using, the other is just for displaying the info.
def get_non_friends_for_user(u, friend_ids_filter=[]):
# Search the friends lists
friend_ids = list(CustomUserFriends.objects.filter(
from_customuser_id=u.pk).values_list('to_customuser_id', flat=True))
friend_ids += list(CustomUserFriends.objects.filter(
to_customuser_id=u.pk).values_list('from_customuser_id', flat=True))
# Search the requests lists
friend_ids += list(FriendRequests.objects.filter(
requester=u.pk).values_list('requestee', flat=True))
friend_ids += list(FriendRequests.objects.filter(
requestee=u.pk).values_list('requester', flat=True))
non_friends = CustomUser.objects.exclude(id__in=friend_ids)
if friend_ids_filter:
non_friends = non_friends.filter(id__in=friend_ids_filter)
return non_friends
def display_user_info(cu, non_friends):
print
print cuf.name
for non_friend in non_friends:
print '\t', non_friend.name
Now, to get all people who are not friends of a particular user we just use that function
# Get all non-friends for custom_user
# Note that custom_user should be defined before as a CustomUsers object
non_friends = get_non_friends_for_user(custom_user)
display_user_info(custom_user, non_friends)
To get the list of a user's friends that aren't friends with another of the user's friends, we can do this:
# Again, custom_user must already be defined as a CustomUsers object
custom_user_non_friends = {}
custom_user_friends = CustomUserFriends.objects.filter(
from_customuser_id=custom_user.pk)
friend_ids = list(custom_user_friends.values_list('to_customuser_id', flat=True))
for cuf in custom_user_friends:
cu = cuf.to_customuser_id
# Add the queryset to the dictionary
custom_user_non_friends[cu] = get_non_friends_for_user(cu, friend_ids)
for cu, non_friends in custom_user_non_friends.items():
display_user_info(cu, non_friends)
And that should do it. I haven't tested any of this and it's all pretty much coming off the top of my head, so there may be some bugs. If it doesn't work for you or it's not what you were looking for, just post a comment and I'll see what I can do.
Related
I have two Django models as follows:
class Event(models.Model):
name = models.CharField()
class EventPerson(models.Model):
event = models.ForeignKey('Event',on_delete='CASCADE',related_name='event_persons')
person_name = models.CharField()
If an Event exists in the database, it will have exactly two EventPerson objects that are related to it.
What I want to do is to determine if there exists an Event with a given name AND that have a given set of two people (EventPersons) in that event. Is this possible to do in a single Django query?
I know I could write python code like this to check, but I'm hoping for something more efficient:
def event_exists(eventname,person1name,person2name):
foundit=False
for evt in Event.objects.filter(name=eventname):
evtperson_names = [obj.person_name in evt.event_persons.all()]
if len(evtperson_names) == 2 and person1name in evtperson_names and person2name in evtperson_names:
foundit=True
break
return foundit
Or would it be better to refactor the models so that Event has person1name and person2name as its own fields like this:
class Event(models.Model):
name = models.CharField()
person1name = models.CharField()
person2name = models.CharField()
The problem with this is that there is no natural ordering for person1 and person2, ie if the persons are "Bob" and "Sally" then we could have person1name="Bob" and person2name="Sally" or we could have person1name="Sally" and person2name="Bob".
Suggestions?
You can query for EventPerson objects where the event name is as given instead, use the values_list to extract the person_name field, and convert the returning list of values to a set for an unordered comparison:
def event_exists(eventname, person1name, person2name):
return set(EventPerson.objects.filter(event__name=eventname).values_list(
'person_name', flat=True)) == {person1name, person2name}
I modified #blhsing answer slightly adding a filter on names.
def event_exists(eventname, person1name, person2name):
event_people = EventPerson.objects.select_related('event').filter(person_name__in=[person1name, person2name], event__name=eventname)
return set(event_people.values_list('person_name', flat=True)) person1name, person2name}
I would suggest passing EventPerson objects or theird ids to this function instead of just names, would make filtering easier (you wouldn't need a set and filter straight by ids) and more efficient (by using db indices ... or you would have to index person_name as well)
My concept is that I have 5 different access level on Odoo.
I want to check if login user is in list (list is created by an automated action), if yes show the fields else hide them.
My code:
list_of_users= []
if record.user_id.partner_id.id: #level 1 user add on list
list_of_users.append(record.user_id.partner_id.id)
if record.user_id.sale_team_id.user_id.partner_id.id: #level 2 user add on list
list_of_users.append(record.user_id.sale_team_id.user_id.partner_id.id)
if record.user_id.sale_team_id.regional_manager_id.partner_id.id: #level 3 user add on list
list_of_users.append(record.user_id.sale_team_id.regional_manager_id.partner_id.id)
user_ids = record.env['res.users'].search([])
flag = record.env['res.users'].search([('groups_id','ilike','L4')])
for user_ids in flag: #level 4 and 5 users add on list
user_record = record.env['res.users'].browse(user_ids)
list_of_users.append(user_ids.partner_id.id)
record.update({'x_partner_follower_custom': [(6, 0, list_of_users)]})
On view i use attrs="{'invisible': [('x_partner_follower_custom', '=', False)]}" inside on fields i want to show/hide
x_partner_follower_custom: many2many res.partner field
Output Sample:
As you can see im return users back to view, but it seems the attrs is not properly set. Any idea how to fix it?
First of all the field should not be stored and it must be computed every time because it depends on the value of the current logged user, remove store:
#api.depends('x_partner_follower_custom')
def user_exist(self):
for rec in self:
if rec.x_partner_follower_custom and self.env.user.partner_id.id in rec.x_partner_follower_custom.ids:
rec.your_boolean_field_name = True
else:
rec.your_boolean_field_name = False
So the field depends on x_partner_follower_custom and the current logged user it should not be stored.
EDITS
Everything is explained in the Form view and how to make the code works like it was created in the code:
I manage it to find solution, a couple days ago: #Fotic
for record in self:
if record['x_partner_follower_custom'] and self.env.user.partner_id.id in record['x_partner_follower_custom'].ids:
record['x_partner_is_follower_custom'] = True
else:
record['x_partner_is_follower_custom'] = False
I list the debts of my customers from the "debts" table with the following code.
However, I would like to see the name and surname of the customer with the same ID number from the "Customer" table.
I get the person I specified with the following code but; I cannot print to "Debts.objects.values (" customer ")".
Is there an easy way to do this?
Thanks for your help.
class CustomerDetailDebtListAPIView(ListAPIView):
serializer_class = DebtCreateSerializer
def get(self, request):
# get customer , customerKey
obj_customer = Customer.objects.get(customer=85)
field_object_customer = Customer._meta.get_field('customer')
# field_value_customer = getattr(obj_customer, field_object_customer.attname)
print(obj_customer)
result = Debt.objects.values('customer') \
.annotate(totalDebt=Sum('totalDebt'), receivedAmount=Sum('receivedAmount')) \
.order_by('customer')
return Response(result)
I am supposing that customer is a foreign key. You can access fields of your related tables using __ operators. This is shown in below code
Debt.objects.all().annotate(totalDebt=Sum('totalDebt'), receivedAmount=Sum('receivedAmount')).order_by('customer').values('customer__surname')
or
from django.db.models import F
Debt.objects.all().annotate(totalDebt=Sum('totalDebt'), receivedAmount=Sum('receivedAmount'), surname=F('customer__surname')).order_by('customer').values('surname')
I have a Django model called Attendance that has the clock in and clock in times of an employee along with the status of that entry, to see whether it's authorized or not. I then, am making another model called Payroll. I want this to check inside the Attendance entries to see all the Authorized entries and then do some action on them. How do I check all the status fields for all the entries in Attendance?
EDIT: Updated to better elaborate my question.
To better elaborate my question, this is how I've setup my Attendance model:
class CWorkAttendance(models.Model):
AUTO_ATT = "AU"
MANUAL_ATT = "MA"
WORK_ENTRY_TYPES = (
(AUTO_ATT, "Auto-Attendance"),
(MANUAL_ATT, "Manual-Attendance"),
)
AUTHORIZED = "AU"
UNAUTHORIZED = "UA"
WORK_ENTRY_STATUSES = (
(AUTHORIZED, "Athorized"),
(UNAUTHORIZED, "Un-Authorized"),
)
#Thank you motatoes
def face_locations_in(self, instance):
now = datetime.datetime.now()
return "attendance/{}/{}/in".format(instance.work_employee, now.strftime("%Y/%m/%d"))
def face_locations_out(self, instance):
now = datetime.datetime.now()
return "attendance/{}/{}/out".format(instance.work_employee, now.strftime("%Y/%m/%d"))
work_employee = models.ForeignKey('CEmployees', on_delete=models.CASCADE,)
work_start_time = models.DateTimeField()
work_end_time = models.DateTimeField(null=True)
work_duration = models.IntegerField(null=True)
work_entry_type = models.CharField(max_length=2,choices=WORK_ENTRY_TYPES)
work_entry_status = models.CharField(max_length=2, choices=WORK_ENTRY_STATUSES, default=WORK_ENTRY_STATUSES[1][0])
employee_face_captured_in = models.ImageField(upload_to=face_locations_in,)#////////
employee_face_captured_out = models.ImageField(upload_to=face_locations_out,)
If you look closely at the work_entry_status, it's a choice CharField that will contain the status of the entry (UNAUTHORIZED by default).
I want to create a Payroll model that will check for all the rows in the CWorkAttendance model and check their work_entry_status fields to see if they are Authorized, which is what I want to learn how to do.
If those fields are authorized, I want the grab the row's work_employee, work_duration and also some details from the original CEmployees row for the employee.
This is what I want my Payslip/Payroll model to look like:
class Payslip(models.Model):
GENERATED = "GEN"
CONFIRMED = "CON"
PAYSLIP_STATUS = (
(GENERATED, "Generated-UNSAVED"),
(CONFIRMED, "Confirmed-SAVED"),
)
payslip_number = models.IntegerField()#MM/YY/AUTO_GENERATED_NUMBER(AUTO_INCREMENT)
payslip_employee = models.ForeignKey('CEmployees', on_delete=models.CASCADE,)#Choose the employee from the master table CEmployees
payslip_generation_date = models.DateTimeField(default=datetime.datetime.now())#Date of the payroll generation
payslip_total_hours = models.IntegerField()#Total hours that the employee worked
payslip_from_date = models.DateField()"""The date from when the payslip will be made. The payslip will be manual for now, so generate it after choosing a a date to generate from."""
payslip_total_basic_seconds = models.IntegerField()#Total seconds the employee worked
payslip_total_ot_seconds = models.IntegerField()#Total overtime seconds the employee worked
payslip_basic_hourly_rate = models.IntegerField()#The basic hourly rate of the employee mentioned here. Take from the master employees table.
payslip_basic_ot_rate = models.IntegerField()#Taking the basic overtime rate from the master table
payslip_total_amount = models.FloatField()#The total amount of the payslip
payslip_entry_status = models.CharField(max_length=3, default=GENERATED)#The status of the pay slip.
Thanks,
Not sure if I understand your requirements well, so let me know if I misunderstood.
# `employee` is the work_employee in question
# if you don't want to filter by employee, remove `work_employee=employee`
attendances = CWorkAttendance.objects.filter(work_entry_status=CWorkAttendance.AUTHORIZED, work_employee=employee)
for attendances in attendances:
# do things with this attendance record
attendance.work_duration
attendance.employee
# ....
Update
Since you would like to do it manually, I would suggest having a separate view to generate the Payslip. The important thing is to know the date_from and the date_to for this payslip. I imagine that it is the managers who would have access to this view, so you would need the proper access controls set for it. I also think you need to have a payslip_to_date even if you are going to generate it until the current date, which will be useful for record keeping. I assume you have that column in the code below.
views.py:
from django.views import View
class GeneratePayslip(View):
"""
make sure you have the right access controls set to this view
"""
def post(self, request, **kwargs):
employee_id = kwags.POST.get("employee_id")
date_from = kwargs.POST.get("from_date")
date_to = kwargs.POST.get("to_date")
# we fetch all the objects within range
attendances = CWorkAttendance.objects.filter( \
work_entry_status=CWorkAttendance.AUTHORIZED, \
work_employee_id=employee_id, \
work_start_time__gte=date_from, \
work_end_time__lte=date_to \
)
hours = 0
for attendance in attendances:
# perform calculations to compute total sum and rate
pass
# create the payslip object here ..
# redirect to a success page and return
If you wanted to do it automatically later on, you may want to generate payslips automatically, once a month. For that you could use something like Celery to have periodic tasks that run in the background, for each employee. If this is the case you could move the above code to a file such as utils.py. you can create a method which takes employee_id, from_date, to_date, and then generate the payslip object, returning the payslip_id to the calling method
I am trying to return a list/filter of users in my Employees table that have a nested relationship to the user. For example, I have employees tied to their manager, and I want to be able to query for all the employees under that manager (this includes any employees under any other managers that are under the main manager). So, if user Bob has 2 direct reports, Sally and Brian. And Brian has 2 direct reports, and Sally has 3 direct reports. I want Bob to be able to see all 7 employees. Right now, the only way I could get it to work was through a horrible sequence, as displayed below..I'm hoping their is an easier/more efficient way.
manager = Employees.objects.filter(manager_id=request.user.id).values('manager')
employee_ids = list(Employees.objects.filter(manager=manager.first()['manager']).values_list('employee', flat=True))
employees = [User.objects.get(id=i).username for i in employee_ids]
grandchildren = []
for i in employees:
user_id = User.objects.get(username=i).id
child = list(Employees.objects.filter(manager=user_id).values_list('employee', flat=True))
grandchildren.append(child)
children = list(chain.from_iterable(grandchildren))
for i in children:
user_id = User.objects.get(id=i).id
child = list(Employees.objects.filter(manager=user_id).values_list('employee', flat=True))
grandchildren.append(child)
grandchildren = list(chain.from_iterable(grandchildren))
for i in grandchildren:
employees.append(User.objects.get(id=i).username)
employees = list(set(employees))
Sorry, but your code looks really horrible. First of all, I mean too many DB queries (most of them are very non-optimized or not even needed).
According to your description, I suggest to try something like this:
manager_id = request.user.id
children_ids = list(
Employees.objects.filter(manager_id=manager_id).values_list('employee', flat=True)
)
grandchildren_ids = list(
Employees.objects.filter(manager_id__in=children_ids).values_list('employee', flat=True)
)
# If you want to go deeper, do this in a loop and stop once an empty list of IDs is fetched
# (which means that there are no descendants anymore)
# Combine all IDs and finally fetch the actual users
# (do it only once, and fetch all the users in a single query, not one by one)
employees_ids = children_ids + grandchildren_ids
employees = User.objects.filter(id__in=employees_ids)
P.S.: is this a joke user_id = User.objects.get(id=i).id? :)