I am trying to build my first django app using the most common posts as a test. Unfortunately the server keeps returning errors such as Postmodel admin not defined. I have tried migrating the new changes but this doesnt work, as well as modifying the views, but it seems i need to explicitly define this model. Could someone point me in the right direction
Heres how my admin.py looks like
from django.contrib import admin
# Register your models here.
from .models import posts
import views
admin.autodiscover()
class PostsModelAdmin(admin.ModelAdmin):
list_display = ('title', 'updated', 'timestamp')
list_display_links = ('updated')
list_editable = ('title')
list_filter = ('updated', 'timestamp')
search_fields = ("title", 'content')
class Meta:
model = posts
admin.site.register(posts)
admin.site.register(PostModelAdmin)
Try this...
from .models import posts
from django.contrib import admin
class PostsModelAdmin(admin.ModelAdmin):
list_display = ('title', 'updated', 'timestamp')
list_display_links = ('updated')
list_editable = ('title')
list_filter = ('updated', 'timestamp')
search_fields = ("title", 'content')
class Meta:
model = posts
admin.site.register(posts, PostsModelAdmin)
The register method takes a model and a class. Your error is because you're just passing the class, which is never allowed unless it's passed after the model.
Also you had a typo in your code. You're missing an s when registering it at the bottom.
Related
How can I show besides the columns username, email, first name, last name, staff user a 5th column with the users ID. I think I have to write some code into admin.py like:
class CustomUserAdmin(UserAdmin):
readonly_fields = ('id',)
admin.site.register(CustomUserAdmin)
You should take advantage of ModelAdmin.list_display, docs here --> https://docs.djangoproject.com/en/2.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display
class CustomUserAdmin(UserAdmin):
list_display = ('username', 'email', 'first_name', 'last_name', 'id')
readonly_fields = ('id',)
admin.site.register(User, CustomUserAdmin)
In case you incur in an AlreadyRegistered error, you should add the following prior to your admin.site.register line
admin.site.unregister(User)
class UserAdmin(admin.ModelAdmin):
list_display = ['first_name', 'last_name',....., 'user_id']
class Meta:
model = User
admin.site.register(User, UserAdmin)
Add user_id field in your list display it will show.
A little late to the party but I would like to contribute.
When I tiried the accepted solution, I realized that some functionality is lost with the User admin page (Maybe other functionalities added later on). Here is the solution for whom do not want to loose other functionalities:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
admin.site.unregister(User)
# Register your models here.
#admin.register(User)
class CustomUserAdmin(UserAdmin):
readonly_fields = ("id",)
def __init__(self, model, admin_site):
super().__init__(model, admin_site)
self.list_display = ("id",) + self.list_display
I used the default UserAdmin class and inherited from it. Than adding "id" field to the super's list_display field solved it elegantly.
Note that solution can be improved by using AUTH_USER_MODEL if you are using custom user class.
I have a DecimalField in my model that I'd like to show up in the admin interface with a unit to the right of the field, like so:
I think if I add help_text to the field, that will show up below the field. Is there a way to specify it to show up to the right?
You can handle it with help_text from the forms, overwrite your field in the form, such as the css.
from django.db import models
from django.contrib import admin
from django import forms
from your.models import Post
class PostForm(forms.ModelForm):
ethanol = forms.FloatField(
label='This is Ethanol',
max_value=10,
min_value=0,
widget=forms.NumberInput(
attrs={
'class': 'whatever',
'style': 'position:relative'
}
),
help_text='<span style="position:absolute;right:0">g/mL</span>'
)
class Meta:
model = Post
fields = '__all__'
class PostAdmin(admin.ModelAdmin):
form = PostForm
list_display = ['ethanol', 'id']
admin.site.register(Post, PostAdmin)
I am following the Django Poll tutorial, I just changed the models a little: https://docs.djangoproject.com/en/1.5/intro/tutorial02/
I am wondering why my alarm does not show in the admin interface when I add/edit/change a pill. The admin only shows to edit the name, not the related alarm object.
It should display inline, according to the tutorial.
admin.py:
from django.contrib import admin
from pills.models import Alarm,Pill
class AlarmInline(admin.TabularInline):
model = Alarm
extra = 3
class PillAdmin(admin.ModelAdmin):
fieldsets = [
('Drug information', {'fields': ['name']}),
]
inlines = [AlarmInline]
list_display = ('name')
admin.site.register(Pill, PillAdmin)
models.py
from django.db import models
class Pill(models.Model):
name = models.CharField(max_length=200)
def __unicode__(self):
return self.name
class Alarm(models.Model):
pill = models.ForeignKey(Pill)
time = models.DateTimeField('Alarm time')
def __unicode__(self):
return self.time.strftime('%c')
All my models validate. I tried rebuilding the database etc...
Any ideas?
If you've correctly reproduced your code above, the problem is your indentation.
It should be:
class PillAdmin(admin.ModelAdmin):
fieldsets = [
('Drug information', {'fields': ['name']}),
]
inlines = [AlarmInline]
list_display = ('name')
inlines is an attribute of the admin class - it and list_display need to be part of the class definition, not statements at the module level.
For simplicity, let say that I have model Product and model Parameters. By default, in model Product I want these settings:
class ProductAdmin(ModelAdmin):
list_display = ('name', 'brand', 'sort', 'specific', 'link_to_frontend', 'category_names', 'ean', 'created', 'creator')
list_filter = ('category', 'creator')
search_fields = ('name', 'brand__name', 'sort', 'specific', 'category__name', 'ean')
In Parameters add/edit, I have added Product as raw_id_fields. As I have lot of columns inside default Product list, I would like to do different settings if popup:
class ProductAdmin(ModelAdmin):
list_display = ('name', 'brand', 'sort', 'specific', 'category_names')
list_filter = ()
search_fields = ('name', 'brand__name', 'sort', 'specific', 'category__name')
Any help appreciated.
Finally, found the solution. I have created an universal own ModelAdmin class, in universal app's admin.py file:
from django.contrib import admin
from django.contrib.admin.views.main import IS_POPUP_VAR
class YourModelAdmin(admin.ModelAdmin):
popup_list_display = ()
popup_list_filter = ()
def get_list_display(self, request):
if IS_POPUP_VAR in request.GET and self.popup_list_display: # return list_display if not set
return self.popup_list_display
else:
return self.list_display
def get_list_filter(self, request):
if IS_POPUP_VAR in request.GET: # return empty tuple if not set
return self.popup_list_filter
else:
return self.list_filter
And from app's admin, I'm calling:
from django.contrib import admin
from [your-uni-app].admin import YourModelAdmin # not necessary if in same file
class ProductAdmin(YourModelAdmin): # e.g.
list_display = ('name', 'category', 'properties',)
popup_list_display = ('name', 'category',)
# same settings for list_filter and popup_list_filter
admin.register(Product, ProductAdmin)
This solution is also open to conditional list_display based on some user-role (e.g.) or manipulation with list_display before returning (add any column automatically to all lists). Same for list_filter and any function from django.contrib.admin.ModelAdmin (or BaseModelAdmin) if overriden.
Overwrite search_fields means to create override of django.contrib.admin.ModelAdmin.chagnelist_view function. For me, it became unnecessary as I need same searching in both, normal and popup view. However, only negative of no ability to overwrite is that you can search by field which is not visible, which seems to be not so big problem...
Hope this will help to anybody.
My site makes use of Django's User Authentication User model and a custom UserProfile model to store some additional data (birthday, etc.). Is there a way to create a view in Django admin that weaves together fields from both the User and UserProfile models?
I suspect that this code snippet is not even close, but maybe it will help illustrate what I'm trying to do:
from django.contrib import admin
from django.contrib.auth.models import User
from userprofile.models import UserProfile
class UserProfileAdmin(admin.ModelAdmin):
list_display = ('name', 'gender', 'User.email') #user.email creates the error - tried some variations here, but no luck.
admin.site.register(UserProfile, UserProfileAdmin)
Error message:
ImproperlyConfigured: UserProfileAdmin.list_display[2], 'User.email' is not a callable or an attribute of 'UserProfileAdmin' or found in the model 'UserProfile'.
Ultimately, I'm trying to create an admin view that has first & last name from UserProfile and email from User.
for displaying user email you need to have a method on UserProfile or UserProfileAdmin that returns the email
on UserProfile
def user_email(self):
return self.user.email
or on UserProfileAdmin
def user_email(self, instance):
return instance.user.email
then change your list_display to
list_display = ('name', 'gender', 'user_email')
Related docs: ModelAdmin.list_display
You could try using InlineModelAdmin to display both User and UserPofile forms in a admin view.
To display user profile information in change list you can create a new method that delegates the values from UserProfile to User model.
For example this should work more or less :)
from django.contrib import admin
from django.contrib.auth.models import User
from my_models import UserProfile
class UserProfileInline(admin.StackedInline):
model = UserProfile
fk_name = 'user'
class UserAdmin(admin.ModelAdmin):
list_display = ['get_userprofile_name', 'email']
list_select_related = True
inlines = [
UserProfileInline,
]
def get_userprofile_name(self, instance):
# instance is User instance
return instance.get_profile().name
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Using Ashoks top answer i made snippet that simplifies this process for large number of fields
class ColumnViewer(object):
pass
column_list = ('name', 'surname', )
for col in column_list:
setattr(ColumnViewer, col, lambda s,i : getattr(i, col))
#admin.register(UserProfile)
class UserProfileAdmin(admin.ModelAdmin, ColumnViewer):
list_display = column_list