How to make custom search functions - django

How can i make a custom search function in django admin. I want to search all fields of the database tables and to find and retrieve the matches.
Is it possible?

Lets take an example of custom User models with below fields,
app_name/models.py
from django.contrib.auth.models import AbstractBaseUser
class User(AbstractBaseUser):
first_name = models.CharField(max_length=50)
middle_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField(max_length=100)
username = models.CharField(max_length=100)
Now the admin for this models would be,
app_name/admin.py
from django.contrib import admin
from app_name.models import User
class UserAdmin(admin.ModelAdmin):
search_fields = User._meta.get_all_field_names()
admin.site.register(User, UserAdmin)
User._meta.get_all_field_names() will return you a list of all the fields of User model.

Related

Why does Django not find a field added to the AbstractBaseUser

I've inherited from the AbstractBaseUser as follows:
class User(AbstractBaseUser):
"""
Main User model, inherits from AbstractBaseUser
"""
# Meta
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
username = models.CharField(max_length=40, unique=True) # equals to email
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
employee_of = models.OneToOneField(Customer, on_delete=models.SET_NULL, null=True)
So each User is linked to one and only one Customer.
Now within a view I want to access the instance of the current logged in user within the request object and get the employee_of value to get a queryset that contains all users of that customer.
def render_employees(request):
"""
Renders the employees page of the dashboard
:param request:
:return:
"""
# Return the value for the current site for css specific classes
dashboard_site = 'employees'
# Query the employees
qs_employees = User.objects.filter(employee_of=request.user.employee_of) # doesn't find field
...
However the filter doesn't work because request.user.employ_of doesn't seem to return anything. My IDE even suggests e.g. username, date_joined etc. but not employee_of.
Why's that?
class Customer(models.Model):
"""
A table that stores static data about a customer, usually a legal company
"""
legal_name = models.CharField(max_length=50)
street = models.CharField(max_length=30)
street_number = models.CharField(max_length=3)
def __str__(self):
return self.legal_name
Update:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from applications.customer.models import Customer
from django.conf import settings
BaseUser = settings.AUTH_USER_MODEL
class User(AbstractBaseUser):
"""
Main User model, inherits from AbstractBaseUser
"""
# Relations
user = models.OneToOneField(BaseUser, related_name='user_profile', on_delete=models.CASCADE, null=True) # link to default user model
employee_of = models.OneToOneField(Customer, on_delete=models.SET_NULL, null=True, blank=True)
I linked the user to the default user model via Django admin. However in the view im still not able to access employee_of within request.user
It seems that request.user is a different model. It's User model from django.contrib.auth. https://docs.djangoproject.com/en/4.0/ref/contrib/auth/#django.contrib.auth.models.User.
What you can do about it?
In our app we have UserProfile model that have OnetoOne relation to django User.
You can then store employee_of value there.
class UserProfile(AbstractBaseUser):
user = models.OnetoOneField("auth.User", related_name="user_profile", on_delete=models.CASCADE)
employee_of = models.OneToOneField(Customer, on_delete=models.SET_NULL, null=True)
and then access request.user employees using something like
request.user.user_profile.employee_of

Django: I dont know want is the wrong with my code

So I was trying to add an imagefield in my model using the UserModel, so I made this models
from django.contrib.auth.models import User
from django.db import models
class ProfileImage(models.Model):
user = models.OneToOneField(User,
on_delete=models.CASCADE,
editable=False)
avatar = models.ImageField()
def user_avatar(self):
return self.profileimage.avatar
User.add_to_class('user_avatar', user_avatar)
And I made an admin to see the imagefield in the users,
admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
# Register your models here.
UserAdmin.fieldsets += ('Custom fields set', {'fields': ('user_avatar',)}),
I dont kno what is wrong with my code, when I open a user to see the image field and , does anyone know what is the problem?
In admin fields and fieldsets expects you to list actual columns in the database. user_avatar is a function you've written so you can't list it as a field on the User model because it doesn't exist in that table.
Make a more generic model for all types of user information, not just an image, like this;
class Profile(models.Model):
"""
Profile model
"""
user = models.OneToOneField(
verbose_name=_('User'),
to=settings.AUTH_USER_MODEL,
related_name='profile',
on_delete=models.CASCADE
)
avatar = models.ImageField()
Then you can access the avatar with request.user.profile.avatar or in your admin register your Profile model as an inline to the User;
from django.contrib import admin
from django.contrib.auth import get_user_model
from myapp.accounts.models import Profile
User = get_user_model()
class ProfileInline(admin.StackedInline):
model = Profile
max_num = 1
can_delete = False
class MyUserAdmin(admin.UserAdmin):
inlines = [ProfileInline]
# unregister old user admin
admin.site.unregister(User)
# register new user admin that includes a UserProfile
admin.site.register(User, MyUserAdmin)

User Model Customisation in Django

I want to edit the User Model in admin.py but I am not able to figure out how can I do this?
Here is the Image of Admin Panel of User Model
Can someone please help me? I want to add some customized fields in the User model.
You can do that by extending AbstractUser from django.
# models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import gettext_lazy as _
class User(AbstractUser):
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
email = models.EmailField(
_('email address'),
unique=True,
blank=True
)
cellphone = models.CharField(
_('cell phone'),
max_length=20,
null=True, blank=True
)
Then you also need to specify this Custom user model in your settings. Specify path to the user model you've just created. <app_name>.<ModelClassName>
# settings.py
AUTH_USER_MODEL = 'users.User'
Lastly, your admin must also inherit from Django default UserAdmin, if you want to save your time from all the hassle of creating some methods they have already created. Now you can edit user admin the way you want by also getting advantage of all the
existing admin features.
# admin.py
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin as OrigUserAdmin
User = get_user_model()
#admin.register(User)
class UserAdmin(OrigUserAdmin):
list_display = (
'id', 'first_name', 'last_name', 'username', 'email', 'is_active'
)
use 'AbstractUser' model to Extend pre define user model in Django.
then we cam easily add some field or add more information in usermodel.
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
Then we have to update our settings.py defining the AUTH_USER_MODEL property.
AUTH_USER_MODEL = 'core.User'
follow this link for more information:-https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html

create a user in Django 2.1 that is associated with an existing model

In my models.py file I have the following code ->
from django.db import models
class Blogger(models.Model):
username = models.CharField(max_length=20)
email = models.EmailField()
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
password = models.CharField(max_length=30, default='')
I want to associate the Blogger model with a User and create the User upon form submission. Here is the forms.py file ->
from django import forms
from blog.models import Blogger
class BloggerForm(models.ModelForm):
class Meta:
model = Blogger
fields = ['username', 'email', 'first_name', 'last_name', 'password']
And here is the views.py ->
class BlogView(FormView):
template_name = 'blogform.html'
form_class = BloggerForm
success_url = 'blog/'
How do I create a new user on the submission of this form ?
All fields in blogger already exists in User model, actually you don't need this Blogger model at all, just use the User model directly.
There's a couple ways you can do this but basically the general 2 answers are:
Toss/copy Django's user model and make your own (hard)
Extend the user model by making a new model, and relating it to the user model (easy)
I usually choose option #2 because then you don't have to reconfig the auth system. This is a good tutorial on how to do it: simpleisbetterthancomplex

Django User model fields at AdminModel

My purpose is to see at the admin site only user name, email and phone number.
I've create UserProfile by extending User model:
model.py
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
name = models.CharField(max_length=50, null=True,blank=True)
address = models.CharField(max_length=50, null=True,blank=True)
phone = models.CharField(max_length=20, null=True,blank=True)
country = models.CharField(max_length=20, null=True,blank=True)
state = models.CharField(max_length=20, null=True,blank=True)
zip = models.CharField(max_length=10, null=True,blank=True)
code = models.CharField(max_length=40, null=True)
def user_email(self):
return self.user.email
admin.py
from myApp.models import UserProfile
from django.contrib import admin
class UserProfileAdmin(admin.ModelAdmin):
fields = ('name','phone',)
list_display = ('name','user_email',)
admin.site.register(UserProfile, UserProfileAdmin)
so on the list_display it works, I can see only the columns I've chosen, but when I add 'user_email' ( fields = ('name','user_email', 'phone',) )to fields I get when I try to go to admin site:
'UserProfileAdmin.fields' refers to field 'user_email' that is missing from the form.
Fields on a related model use two underscores. Dunno if it'll work in the admin though.
list_display = ('name','user__email',)
Just because I recently used it and you maybe want this, too: If you wan't to add an inline admin to the "User" admin page in Django you can do this (at least in Django 1.3) by doing:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from models import UserProfile
class UserProfileInlineAdmin(admin.StackedInline):
model = UserProfile
class MyUserAdmin(UserAdmin):
inlines = [ UserProfileInlineAdmin ]
admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)
You can't put editable fields from a related model into an admin form, without using inlines. You can show the field as a readonly value: just add it to readonly_fields.