Django display list of ForeingKey relationship - django

I'm using django 2 and python 3.
In my model I have Users that can own a list of Applications. Applications can have only one Owner.
I used a ForeingKey like so:
class User(AbstractUser):
# nothing interresting for this question here
pass
class StoreApplication(models.Model):
owner = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="applications"
)
Now I would like to list the User's applications in the User's admin page, like a list of application names, just readonly stuff. Not in the list view, in the edit view.
I'm aware of InlineModelAdmin and it does not seem to resolve my issue, as it includes the whole Application forms for each of the user's application.
If I try to reference the field as "applications" in my user admin:
class UserAdmin(admin.ModelAdmin):
list_display = ("username", )
fieldsets = (
("Général", {
"fields": ("username", "applications", )
}),
)
An error occurs:
Unknown field(s) (applications) specified for User. Check fields/fieldsets/exclude attributes of class UserAdmin.

You could add a method to the UserAdmin that returns all the applications as a comma separated list. I'm going to assume there is a CharField on the StoreApplication model that names the object (name)
def get_applications(self, obj):
return ', '.join([app.name for app in obj.applications])
# set the short_description to how you want that field displayed in admin
get_applications.short_description = 'Applications'
Then just add get_applications to fields and readonly_fields

Related

Django admin shows all the records in the table in a many to many relationship, instead of related fields

So in this project there organizations. Each user can be a manager in multiple organizations. Each user can also be a member of multiple organizations.
When I go to the "user page" in django admin (e.g. I click to users and than click to that user), I expect to see a list of organizations that user is a manager, and another list of organizations that user is a member.
Instead, for any user, I see a list of ALL the organizations in both the managership and membership list, as in the image below. E.g. the list is not filtered by their user id.
What I am doing wrong? How can I fix this? Thanks.
My UserAdmin is like:
#admin.register(User)
class UserAdmin(auth_admin.UserAdmin):
form = UserChangeForm
add_form = UserCreationForm
fieldsets = (
...
(_("Managerships"), {"fields": ("managerships", )}),
(_("Memberships"), {"fields": ("memberships", )}),
)
list_display = ["username", "name", "is_superuser"]
search_fields = ["name"]
My user model is like this:
class User(AbstractUser):
...
managerships = models.ManyToManyField(Organization, related_name='managerships',blank=True)
memberships = models.ManyToManyField(Organization, related_name='memberships',blank=True)
...
And Organization model is like:
class Organization(models.Model):
name = models.CharField(max_length=200)
...
That's just a way Django admin displays m2m fields by default. You see the whole Organization table, and you are able to select which Organizations User belongs to by selecting the rows while holding Control/Command (as written below the box).
However, it may be inconvenient to use multiple-select boxes. There is an option filter_horizontal which provides alternative UX (there is also a filter_vertical). Docs
#admin.register(User)
class UserAdmin(auth_admin.UserAdmin):
...
filter_horizontal = ('managerships', 'memberships')
You'll still see the whole Organization table on the left, and the selected Organizations will be shown on the right.

Getting all registered users from Django's inbuilt user model into a class within admin.py

I am fairly new to Django and can just about articulate what I am trying to do, so I apologise if the title isn't accurate.
I am using this survey app - https://github.com/Pierre-Sassoulas/django-survey
Within admin.py, I have the following two classes:
class SurveyAdmin(admin.ModelAdmin):
list_display = ('name', 'is_published', 'need_logged_user', 'template')
list_filter = ('is_published', 'need_logged_user')
inlines = [CategoryInline, QuestionInline]
actions = [make_published]
class ResponseAdmin(admin.ModelAdmin):
list_display = ('interview_uuid', 'survey', 'created', 'user')
list_filter = ('survey', 'created')
date_hierarchy = 'created'
inlines = [
AnswerTextInline, AnswerRadioInline, AnswerSelectInline,
AnswerSelectMultipleInline, AnswerIntegerInline
]
# specifies the order as well as which fields to act on
readonly_fields = (
'survey', 'created', 'updated', 'interview_uuid', 'user'
)
These create the pages for "Responses" and "Surveys" in the Admin page.
Admin area with Response and Survey links / their outputs
I can list the usernames of each user that submitted a Response to the Survey (using TabularInLine and model.response), but what I want to do is list all of the users that exist (so that I can add a timestamp of when they submitted their Response to the Survey/Filter by Response date/etc.).
What I've tried since is importing User from contrib.auth.models and creating a new UserAdmin class (so that I can at least list all users, and move on from there).
from django.contrib.auth.models import User
...
admin.site.unregister(User)
...
class UserAdmin(admin.ModelAdmin):
list_display = ('username',)
...
admin.site.register(User, UserAdmin)
I don't get any errors, but it's not displaying the UserAdmin class in the Admin page.
How can I list all of the registered users into the Admin page (in order to later add the timestamp of when a Response was submitted, if one was submitted)?
I'm using Django 1.11 if that's relevant.
I think you should have a list of all the user in the admin with the code you gave. Maybe you don't have any users in database ? I can't see the exact problem right now.
But without modifying the app, you should be able to see when a "Response" has been submitted or updated with the created or updated attribute of the Response class :
For example if you want to list the user and date of submission of a survey contained in the survey variable:
for response in survey.reponses:
print(response.user, "answered at", response.created)
If you want to loop on all users and see if the survey has been answered:
for user in User.objects.all():
response = Reponse.objects.filter(survey=survey, user=user)
if response:
print(user, "answered at", response.created)
else:
print(user, "never answered")
I hope this help.

Django 1.11 admin form add search box to oneToOne field

I have a user, admin and employee models, both employee and admin are related to the user model with a oneToOne field what i would like to do is in the admin form i have one field "user"
instead of having a drop down field with all users i would like to have a search box so that when i search for a specific user i find him and choose him to be an admin.
how?
i also tried to add user's fields to admin's form but i couldn't
i tried the inline thing, the parent_link in the admin's model... but i couldn't find a solution
Now i would like to minimise the search through the long users list by adding a search box to the field
I have solved this type of problem using django-ajax-selects package. Hope this will help you.
app/admin.py:
from ajax_select import register, LookupChannel
#register('users')
class UsersLookup(LookupChannel):
model = User
def get_query(self, q, request):
return self.model.objects.filter(username__icontains=q)
class EmployeeAdminForm(forms.ModelForm):
user = AutoCompleteSelectField('users', required=False,
help_text=None)
class Meta:
model = Employee
fields = '__all__'
settings.py
AJAX_LOOKUP_CHANNELS = {
'users' : {'model': 'auth.user', 'search_field': 'username'},
}
Use django's raw_id_fields. With that you can declare a foreign key object searchable.

Django - Display User Email in User Profile Admin

This may be a very simple question, but I haven't been able to find it in SO.
I created a User Profile Model for additional user info via OnetoOneField. Now for the Admin of the User Profile Model, I want to display the email field found in the User model. I tried:
# models.py
def email(self):
return self.user.email
# admin.py
fieldsets = [
('', {'fields': [
...
'email',
...
]})
]
list_display = (
...
'email',
...
)
This worked for the list_display section, but for fieldsets, the following error popped up:
Unknown field(s) (email) specified for UserProfile. Check fields/fieldsets/exclude attributes of class UserProfileAdmin.
Is there a way to work around this? Thank you in advance!
From the documentation:
fields can contain values defined in readonly_fields to be displayed
as read-only.
If you add the name of a callable to fields, the same rule applies as
with the fields option: the callable must be listed in
readonly_fields.
So you need to add:
readonly_fields = ('email',)
to your model admin class, and then it will be available in the fieldset.
Put this
def email(self, obj):
return obj.user.email
in your admin class of userprofile and you will be able to use it in fieldsets.

list_display in admin behave nothing

This is my github repo Inout. I am learning django and i worked Very very simple django registration & login system.
My question is:
How to list all the usernames in admin using list_display. But nothing display in admin panel. May i know why ?
Inside my working code:
# models.py
username = models.OneToOneField(User)
first_name = models.CharField(max_length=100)
# admin.py
class SignupAdmin(admin.ModelAdmin):
list_display = ['username']
admin.site.register(Signup, SignupAdmin)
Information for you Reference :
if i am using list_filter in admin i can see all the username in the filter panel
Then if i am accessing this page http://127.0.0.1:8000/admin/system/signup/
Select signup to change
0 signups
And also if i am accessing this page http://127.0.0.1:8000/admin/frontend/profile/add/ i can see the drop down of username shows all the username i registered before.
What i missing ? or can somebody clone my repo and see yourself.
Are you sure it's not working correctly? list_display is supposed to take a tuple/list of fields and then display those fields as columns of the main table like in the picture shown below taken from the django admin documentation, where each entry in the main table has a username, email address, first name, last name, staff status. This would be created by
list_display = ['username', 'email', 'first_name', 'last_name', 'is_staff']
in a ModelAdmin for the built in User model (taken from django.contrib.auth.models). The side-column on the right side (with the label "Filter") is populated only when you define fields under list_filter.
Note if you only defined one field, and your model has a __unicode__ function that returns the username, you will not see a significant difference with just adding list_display = ('username',). I suggest you try list_display = ('username', 'first_name',). In this case, for every SignUp you will see two columns in the main table -- one with the username and one with the first_name.
EDIT
You have two errors.
First, you don't seem to have created any SignUp objects anywhere. Before the admin change list will display any entries, you must create some entries.
Second, your __unicode__ method of your SignUp model refers to non-existent fields (self.user is never defined -- in your SignUp class you used username = models.OneToOneField(User)
, hence you refer to it as username) and furthermore it doesn't return a unicode string as required.
Try:
def __unicode__(self):
if self.username:
return unicode(self.username)
then create some SignUp and then it will work. Again, the list_display part was working perfectly.