Hi i have user model consist of several fields, in that payment_type is one field which return integer value , so based on that value i need to show some string sentence.
class Users(models.Model):
payment_type=models.IntegerField()
in my admin i need to make condition to display. I am new to django so support
For choices, you can use get_FOO_display in admin list_display or write your own customized method to get more control of what get displayed in admin panel
#admin.register(User)
class UserAdmin(BaseUserAdmin):
list_display = ('get_payment_type_display', )
# or you can write your own method
#admin.register(User)
class UserAdmin(BaseUserAdmin):
list_display = ('get_payment_type', ) # method
# call get_<field>_display
def get_payment_type(self, obj):
return obj.get_payment_type_display()
get_payment_type.short_description = 'Payment Type'
Related
I am working on a Django project and I want to fetch data from particular table and show it in the admin side.
I am having a Company model which I have registered in admin using admin.site.register(Company, Company_Admin). Now I want to just get all the companies after querying them from the table and just show the result in the admin site.
class Company(models.Model):
name = models.CharField(default=None,max_length=200)
description = models.TextField(default=None)
url = models.CharField(max_length=200)
published = models.BooleanField()
createdOn = models.DateTimeField(default=datetime.utcnow)
updatedOn = models.DateTimeField(default=datetime.utcnow)
keywords = models.ManyToManyField(Keyword)
def __unicode__(self):
return self.text
class CompanyAdmin(admin.ModelAdmin):
list_display = ['name', 'url', 'description', 'published', 'createdOn', 'updatedOn']
list_filter = ['name']
search_fields = ['name']
filter_horizontal = ('keywords', )
admin.site.register(Company, CompanyAdmin)
Now I want to create an option in admin panel that will show me all the companies that are published, that is, do not even show the non-published companies.
According to the docs on ModelAdmin.list_filter, you can try adding the field name to that attribute. This should give you a new filter option in the right sidebar of the change view.
class CompanyAdmin(admin.ModelAdmin):
...
list_filter = ['name', 'published']
...
If, however, you want to hide all non-published instances completely from the admin (I don't know if that is the case, I don't fully understand you question), then you can modify the ModelAdmin.get_queryset() method.
class CompanyAdmin(admin.ModelAdmin):
...
def get_queryset(self, request):
return super().get_queryset(request).filter(published=True)
...
Try to add list_filter in CompanyAdmin on 'published':
list_filter = ['name','published']
So, You can find one pane at right side, in which you can just filter out as you want.
(I'm considering that you're not overriding default admin template.)
I'm trying to sort a Django Admin list page by a specific value in the objects' related foreign key set.
Specifically, in the below code, I want the ContentAdmin view to show a list of all content objects sorted by the "Twitter Score" (The Score object with name "Twitter").
In the django app I have the following models:
class Content(models.Model):
body = models.CharField(max_length=564)
title = models.CharField(max_length=64)
class Score(models.Model):
name = models.CharField(max_length=64)
score = models.IntegerField()
content = models.ForeignKey('Content')
And in the admin.py I have the following:
class ContentAdmin(admin.ModelAdmin):
list_display = ('title', 'show_twitter_score',)
def show_twitter_score(self, obj):
twitter_score = obj.score_set.get(name='Twitter')
return 'Twitter: ' + str(twitter_score.score)
GOAL: The admin panel for ContentAdmin displays the content objects ordered by "Twitter" scores
Thanks everyone!
I solved this by extending the get_queryset method of the ContentAdmin class. After that, it was just a matter of getting the right ORM query
def get_queryset(self, request):
qs = super(ContentAdmin, self).get_queryset(request)
return qs.filter(score__name='Twitter').order_by('-score__score')
For Django 1.5 and earlier, the method was queryset.
def queryset(self, request):
qs = super(ContentAdmin, self).queryset(request)
return qs.filter(score__name='Twitter').order_by('-score__score')
If I understand correctly, you can try this from ModelAdmin.list_display in Django's documentation:
Usually, elements of list_display that aren't actual database fields can't be used in sorting (because Django does all the sorting at the database level).
However, if an element of list_display represents a certain database field, you can indicate this fact by setting the admin_order_field attribute of the item.
For example:
class Person(models.Model):
first_name = models.CharField(max_length=50)
color_code = models.CharField(max_length=6)
def colored_first_name(self):
return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name)
colored_first_name.allow_tags = True
colored_first_name.admin_order_field = 'first_name'
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'colored_first_name')
The above will tell Django to order by the first_name field when trying to sort by colored_first_name in the admin.
You can try this workaround in your code for the sorting.
Since django admin uses the db to sort you cant sort on the function you are showing in the list.
What you can do is to add the column you want to show to the queryset that django admin is using to list your models, this way you can have sorting.
To add the column you need you have to use the queryset extra method.
This should do the trick :)
Content.objects.all().extra(select={'twitter_score': 'SELECT score from content_score WHERE content_score.id = content_content.id'})
BONUS ROUND:
Content.objects.all().extra(select={'twitter_score': 'SELECT 'Twitter score:' || score from content_score WHERE content_score.id = content_content.id'})
I have model which among other fields contains price property which is calculated dynamically. I want to display this property in model admin page. So I've created custom ModelForm:
class ShipmentForm(forms.ModelForm):
price = forms.IntegerField()
class Meta:
model = models.Shipment
fields = [
'title',
'price',
]
However I can't get price value in that form.
Here's how I change form in admin panel:
class ShipmentAdmin(admin.ModelAdmin):
form = ShipmentForm
See ModelAdmin.readonly_fields (Django 1.10 docs link).
A read-only field can not only display data from a model’s field, it can also display the output of a model’s method or a method of the ModelAdmin class itself.
This means that you can do:
class ShipmentAdmin(admin.ModelAdmin):
readonly_fields = ('price', 'something_else')
def something_else(self, instance):
# calculate something else here
Where price is a model method, and something_else is a ModelAdmin method.
I have the following models:
class UserProfile(models.Model):
user = models.OneToOneField(User)
class Property(models.Model):
user = models.ForeignKey(User)
I would like to create a TabularInline displaying every Property connected to a particular UserProfile on its Django admin page. The problem here is, of course, that Property does not have a ForeignKey directly to UserProfile, so I cannot simply write
class PropertyTabularInline(admin.TabularInline):
model = Property
class UserProfileAdmin(admin.ModelAdmin):
inlines = (PropertyTabularInline,)
How can I easily do what I want?
You can overwrite the User admin page to display both the Profile and the Property models.
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from myapp.models import *
class ProfileInline(admin.TabularInline):
model = Profile
class PropertyInline(admin.TabularInline):
model = Property
class UserAdmin(UserAdmin):
inlines = (ProfileInline, PropertyInline,)
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
You can also remove any unwanted/unused User properties from being displayed (e.g. Groups or Permissions)
more here: https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#extending-the-existing-user-model
and here:
https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#a-full-example
class PropertyTabularInline(admin.TabularInline):
model = Property
def formfield_for_dbfield(self, field, **kwargs):
if field.name == 'user':
# implement your method to get userprofile object from request here.
user_profile = self.get_object(kwargs['request'], UserProfile)
kwargs["queryset"] = Property.objects.filter(user=user_profile)
return super(PropertyInLine, self).formfield_for_dbfield(field, **kwargs)
once this is done, you can add this inline to user UserProfileAdmin like:
class UserProfileAdmin(admin.ModelAdmin):
inlines = (PropertyTabularInline,)
Haven't tested it, but that should work.
It is achievable by making one change in your models.
Instead of creating OneToOne relationship from UserProfile to User, subclass User creating UserProfile. Code should look like that:
class UserProfile(User):
# some other fields, no relation to User model
class Property(models.Model):
user = models.ForeignKey(User)
That will result in creating UserProfile model that have hidden OneToOne relation to User model, it won't duplicate user model.
After doing that change, your code will work. There are some changes under the hood, like UserProfile no longer have it's own ID, you can access fields from User inside UserProfile and it's hard to swap User model using settings.AUTH_USER_MODEL (that will require creating some custom function returning proper type and changing migration by hand) but if this is not a problem for you, it may be good solution.
I am trying to redefine my admin page for the auth.User model.
Everything is working properly, except for one thing. Check the code below:
from django.contrib import admin
from django.contrib.auth.models import User
from access.models import UserProfile
class UserProfileInline(admin.StackedInline):
model = UserProfile
class UserAdmim(admin.ModelAdmin):
inlines = [UserProfileInline,]
list_display = ['id', 'username', 'get_full_name', 'email']
admin.site.unregister(User)
admin.site.register(User, UserAdmim)
As you can see, one of the fields I want to be displayed in the model page listing -- defined by list_display -- is get_full_name. The problem is that the column label in the admin is displayed as Get full name.
My question is simple: can I override this? If so, how?
Thanks for your help.
Set an attribute in your function called short_description to your desired label in your model definition.
# note, this must be done in the class definition;
# not User.get_full_name.short_description
get_full_name.short_description = 'my label'
Alternatively, if you don't want to pollute your model with admin specific code, you can set list_display to a method on the ModelAdmin which takes one argument: the instance. You'll also have to set readonly_fields so that the admin doesn't try to look up this field in your model. I prefix admin fields with _ to differentiate.
class MyAdmin(...):
list_display = ('_my_field',)
readonly_fields = ('_my_field', )
def _my_field(self, obj):
return obj.get_full_name()
_my_field.short_description = 'my custom label'
Update:
Note that this will break default admin ordering. Your admin will no longer sort fields by clicking the label. To enable this functionality again, define an admin_order_field.
def _date_created(self, obj):
return obj.date_created.strftime('%m/%d/%Y')
_date_created.short_description = "Date Created"
_date_created.admin_order_field = 'date_created'
Update 2:
I've written an admin method decorator that simplifies this process, because once I started using highly descriptive verbose method names, setting attributes on the function became massively repetitive and cluttering.
def admin_method_attributes(**outer_kwargs):
""" Wrap an admin method with passed arguments as attributes and values.
DRY way of extremely common admin manipulation such as setting short_description, allow_tags, etc.
"""
def method_decorator(func):
for kw, arg in outer_kwargs.items():
setattr(func, kw, arg)
return func
return method_decorator
# usage
class ModelAdmin(admin.ModelAdmin):
#admin_method_attributes(short_description='Some Short Description', allow_tags=True)
def my_admin_method(self, obj):
return '''<em>obj.id</em>'''