How to hide some Usergroups from Django Admin in ManytoMany field - django

I have the following model:
class Task(models.Model):
site=models.OneToOneField(Site,on_delete=models.CASCADE,default=1)
executor=models.ManyToManyField(People)
It is related to the following model:
class People(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,
unique=True)
phone_number = models.CharField(max_length=200, blank=True,
null=True)
#department = models.CharField(max_length=200, blank=True, null=True)
title = models.CharField(max_length=200, choices= titles, blank=True,
null=True)
What I want is that in DjangoAdmin in the field executor only people__title='titleone' was displayed. So that the executor search field would not be overload with other people who cannot ever be related to the Tsk since I have them in the same database.

You can override get_queryset() in admin.py file and can restrict queryset to include only that query which contain people__title='titleone'.

Related

Django: reference model fields from another model

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

Django admin - Filter foreignKey in an Inline

I have these models:
class Country(models.Model):
name = models.CharField(unique=True, max_length=50)
class Person(models.Model):
name = models.CharField(max_length=50, blank=True, null=True)
country = models.ForeignKey(Country, models.DO_NOTHING, db_column='countries', blank=True, null=True)
class Organization(models.Model):
name = models.CharField(max_length=50, blank=True, null=True)
class Membership(models.Model):
person= models.ForeignKey(Person, models.DO_NOTHING, db_column='people', blank=True, null=True)
organization= models.ForeignKey(Organization, models.DO_NOTHING, db_column='organizations', blank=True, null=True)
There are a high number of people (over 1000) that can be members of several organizations.
I have a view in the admin page as follows
class MembershipInline(admin.StackedInline ):
model = Membership
extra = 1
class OrganizationAdmin(admin.ModelAdmin):
inlines = [MembershipInline]
admin.site.register(Organization,OrganizationAdmin)
Therefore I can manage any organization and see the people that belongs to it. I can also add new people to the organization.
The problem is that the number of people is too high and the list shows too many of them. Is there any way to filter this StackedInline?
For example placing another field in the Inline where a country can be chosen to filter the people that can be added, or a search field to filter the person's name.
Thanks in advance!
Finally got to work using the option "autocomplete_fields "
class PersonAdmin(admin.ModelAdmin):
search_fields = ['country__name','name']
admin.site.register(Person,PersonAdmin)
class MembershipInline(admin.StackedInline ):
model = Membership
extra = 1
autocomplete_fields = ['person',]
How it looks

Filter data in a model with list of ids filtered from the related model

I've 3 models which are related weirdly though it is a one-to-many relationship (between 2 models). Now I've no option to change the model structure but to work with it however it is.
Models
class Note(models.Model):
user_owner = models.ForeignKey('User',blank=True, null=True,related_name='note_owner')
message = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
... ... ...
class SalesLead(models.Model):
user_owner = models.ForeignKey(User, models.DO_NOTHING, blank=True, null=True)
status = models.ForeignKey(LeadStatus, models.DO_NOTHING, blank=True, null=True)
name = models.CharField(max_length=255)
first_name = models.CharField(max_length=255, blank=True, null=True)
middle_name = models.CharField(max_length=255, blank=True, null=True)
last_name = models.CharField(max_length=255, blank=True, null=True)
... ... ...
class LeadNoteRelation(models.Model):
note = models.ForeignKey(Note, models.DO_NOTHING, primary_key=True, related_name = "lead_note")
lead = models.ForeignKey('SalesLead', models.DO_NOTHING)
class Meta:
unique_together = (('note', 'lead'),)
I'm trying to write a function-based view which takes the SalesLead id and User id as inputs. The response should include all Notes related to this lead id and user_owner as the input User id
I tried:
LeadNoteRelation.objects.filter(lead__id = INPUT ID).select_related()
But this did not give me the desired result. Kindly help me with this one. Thanks in advance.
You can filter with:
Note.objects.filter(
leadnoterelation__lead_id=lead_id,
user_owner_id=user_owner_id
).distinct()
Where you replace lead_id and user_owner_id with the primary keys of the lead and user respectively. The .distinct() [Django-doc] can be used to avoid fetching the same Note multiple times per lead_id that matches.

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.