In my Django project I have a model:
class Category(MPTTModel):
name = models.CharField(default='',
max_length=50,
verbose_name='Название')
slug = models.SlugField(default='')
parent = TreeForeignKey('self',
related_name='children',
null=True,
blank=True,
verbose_name='Родительская категория'
)
order = models.PositiveSmallIntegerField(blank=False,
null=False,
default=0,
verbose_name='Порядок')
is_active = models.BooleanField(default=True,
db_index=True,
verbose_name='Отображать на сайте')
class Meta:
verbose_name = 'Категория'
verbose_name_plural = 'категории'
class MPTTMeta:
order_insertion_by = ['order']
If I add the main categories first (one, two, three), and then add subcategories (four in one, five in two, six in three), I would like to see it in the admin panel like this:
-one
--four
-two
--five
-three
--six
But I have this ordering:
-one
-two
-three
--four
--five
--six
What am I doing wrong?
You need to register Category model with MPTTModelAdmin
In your admin.py
from django.contrib import admin
from mptt.admin import MPTTModelAdmin
from .models import Category
admin.site.register(Category, MPTTModelAdmin)
Reference: https://django-mptt.github.io/django-mptt/admin.html
Thanx! It seems that SortableModelAdmin from suit.admin broke an order.
My admin.py was:
from suit.admin import SortableModelAdmin
from mptt.admin import MPTTModelAdmin
from .models import Category, Good
class CategoryAdmin(MPTTModelAdmin, SortableModelAdmin):
mptt_level_indent = 20
list_display = ('name', 'slug', 'is_active', 'order')
list_editable = ('is_active',)
prepopulated_fields = {"slug": ("name",)}
# Specify name of sortable property
sortable = 'order'
admin.site.register(Category, CategoryAdmin)
Related
I got the these two errors below:
<class 'blog.admin.CommentAdmin'>: (admin.E108) The value of
'list_display[4]' refers to 'active', which is not a callable, an
attribute of 'CommentAdmin', or an attribute or method on
'blog.Comment'.
<class 'blog.admin.CommentAdmin'>: (admin.E116) The value of
'list_filter[0]' refers to 'active', which does not refer to a Field.
This is my models.py code:
from django.contrib.auth.models import User
# Create your models here.
STATUS = (
(0,"Draft"),
(1,"Publish")
)
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(User, on_delete= models.CASCADE,related_name='blog_posts')
updatedOn = models.DateTimeField(auto_now= True)
content = models.TextField()
createdOn = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)
class Meta:
ordering = ['-createdOn']
def __str__(self):
return self.title
class Comment(models.Model):
post = models.ForeignKey(
Post, on_delete=models.CASCADE, related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
createdOn = models.DateTimeField(auto_now_add=True)
status = models.BooleanField(default=False)
class Meta:
ordering = ['createdOn']
def __str__(self):
return 'Comment {} by {}'.format(self.body, self.name)
This is my admin.py code:
from django.contrib import admin
from .models import Post, Comment
# Register your models here.
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'slug', 'status','createdOn')
list_filter = ("status", 'createdOn')
search_fields = ['title', 'content']
prepopulated_fields = {'slug': ('title',)}
#admin.register(Comment)
class CommentAdmin(admin.ModelAdmin):
list_display = ('name', 'body', 'post', 'createdOn', 'active')
list_filter = ('active', 'createdOn')
search_fields = ('name', 'email', 'body')
actions = ['approveComments']
def approveComments(self, request, queryset):
queryset.update(active=True)
admin.site.register(Post, PostAdmin)
This is my forms.py code:
from .models import Comment
from django import forms
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('name', 'email', 'body')
Any help is greatly appreciated.
The message is clear 'active' is not a field
class Comment(models.Model):
post = models.ForeignKey(
Post, on_delete=models.CASCADE, related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
createdOn = models.DateTimeField(auto_now_add=True)
status = models.BooleanField(default=False)
your fields are: post, name, email, createdOn, status
Therefore create a field named active or suppress active in list_display &
list_filter
status = models.IntegerField(choices=STATUS, default=0)
should be:
active = models.IntegerField(choices=STATUS, default=0)
I got the same error below:
ERRORS: <class 'store.admin.PersonAdmin'>: (admin.E116) The value of
'list_filter[0]' refers to 'PersonAgeFilter', which does not refer to
a Field.
When assigning the custom filter PersonAgeFilter to list_filter() with parentheses as shown below:
# "store/admin.py"
from django.contrib import admin
from .models import Person
class PersonAgeFilter(admin.SimpleListFilter):
# ...
#admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
list_filter = ("PersonAgeFilter",)
# ↑ Parentheses ↑
So, I removed the parentheses from "PersonAgeFilter" as shown below then the error was solved.
# "store/admin.py"
from django.contrib import admin
from .models import Person
class PersonAgeFilter(admin.SimpleListFilter):
# ...
#admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
list_filter = (PersonAgeFilter,)
# Without parentheses
so I have these two models
class Recipe(models.Model):
short_description = HTMLField(max_length=400)
likes = models.ManyToManyField(User, blank=True, related_name='recipe_likes')
slug = models.SlugField(blank=True, unique=True)
published_date = models.DateTimeField(blank=True, default=datetime.now)
ratings = GenericRelation(Rating, related_query_name='recipes')
class Ingredient(models.Model):
name = models.CharField(max_length=20)
amount = models.FloatField()
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE, related_name='recipe_ingredients')
In the admin panel from the recipes section, if I choose a recipe I want to be able to add ingredients for that recipe, what do I need? I think I don't know the right searchterms to use, hope you understand what I mean.
Thanks for the help.
EDIT
This is the solution:
from django.contrib import admin
from .models import Recipe, Ingredient
class IngredientInline(admin.TabularInline):
model = Ingredient
extra = 3
#admin.register(Recipe)
class RecipeAdmin(admin.ModelAdmin):
list_display = ('title',)
search_fields = ('title', )
inlines = [IngredientInline,]
from django.contrib import admin
from .models import Recipe, Ingredient
class IngredientInline(admin.TabularInline):
model = Ingredient
extra = 3
#admin.register(Recipe)
class RecipeAdmin(admin.ModelAdmin):
list_display = ('title',)
search_fields = ('title', )
inlines = [IngredientInline,]
You'll want to read up on InlineModelAdmins:
https://docs.djangoproject.com/en/3.1/ref/contrib/admin/#inlinemodeladmin-objects
When you register your models with a model admin class, add an inlines list.
The documentation is good on this, so please expand your question if you have more detailed questions!
I have a Django app with the following models.py
from django.db import models
class Order(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
paid = models.BooleanField(default=False)
delivered = models.BooleanField(default=False)
class OrderItem(models.Model):
order = models.ForeignKey(Order,
related_name='items',
on_delete=models.CASCADE)
product = models.ForeignKey(Product,
related_name='order_items',
on_delete=models.CASCADE)
price = models.DecimalField(max_digits=10, decimal_places=2)
And in my admin.py, I have this
from django.contrib import admin
#admin.register(Order)
class OrderAdmin(admin.ModelAdmin):
list_display = ['id', 'first_name', 'last_name', 'email',
'paid', 'delivered']
list_filter = ['paid', 'delivered']
This only shows the Order table.
I would like to join the Order with the OrderItem table and display it in the Django admin. I am not sure this is relevant but for one Order, there could be many OrderItem(s).
As far as I know, you can't show OrderItems in OrderAdmin directly. But you can show Order in OrderItemAdmin, or use InLineModelAdmin to show OrderItems in Order Detail page. Like this:
class OrderItemInline(admin.TabularInline):
model = OrderItem
class OrderAdmin(admin.ModelAdmin):
inlines = [
OrderItemInline,
]
If you still want to display OrderItems (or parts of order item) in admin page, then you can add a method in list_display field, and use that method to fetch OrderItems. Like this:
class OrderAdmin(admin.ModelAdmin):
list_display = (..., 'get_order_items')
def get_order_items(self, obj):
return return ", ".join(obj.items.values_list("pk", flat=True))
get_order_items.short_description = 'Order Items'
I'm pretty new at Django and am stuck trying to implement Django import-export. My three pertinent model are Officer, Incident, and Details. Officer and Incident are in a M2M relationship through Details. I have gotten all of the functionality to work besides importing details. When I try to import via the import button, I get "NOT NULL constraint failed: police_archive_details.incident_id" for each row in the .xls or .csv file I'm importing.
Here's my (current) admin.py
from django.contrib import admin
from import_export import resources, widgets, fields
from import_export.admin import ImportExportModelAdmin, ImportExportActionModelAdmin
from forms import AdminTextForm, OfficerTextForm
from .models import Officer, Incident, Details, SiteText
class FullNameForeignKeyWidget(widgets.ForeignKeyWidget):
def get_queryset(self, value, row):
return self.model.objects.filter(
first_name__iexact=row["first_name"],
last_name__iexact=row["last_name"]
)
class DetailsInlineAdmin (admin.TabularInline):
model = Details
extra = 5
class OfficerResource(resources.ModelResource):
class Meta:
model = Officer
class OfficerAdmin(ImportExportModelAdmin):
list_display = ('first_name', 'last_name', 'badge', 'department')
search_fields = ['first_name', 'last_name']
inlines = [DetailsInlineAdmin]
resource_class = OfficerResource
form=OfficerTextForm
class Media:
js = ('//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js','/static/admin/js/admin/popup.js')
class IncidentResource(resources.ModelResource):
officer = fields.Field(
column_name='officer',
attribute='officer',
widget=widgets.ForeignKeyWidget(Officer, 'badge'))
class Meta:
fields = ('officer',)
model = Incident
class IncidentAdmin(ImportExportModelAdmin):
list_display = ('office','case_number')
search_fields = ['case_number']
inlines = [DetailsInlineAdmin]
resource_class = IncidentResource
class DetailsResource(resources.ModelResource):
officer = fields.Field(
column_name='officer',
attribute='officer',
widget=FullNameForeignKeyWidget(Officer))
incident = fields.Field(
column_name='incident',
attribute='incident',
widget=widgets.ForeignKeyWidget(Incident, 'case_number'))
class Meta:
fields = ('id','incident','officer__last_name','officer__first_name','allegation', 'finding', 'action')
model = Details
class DetailsAdmin(ImportExportModelAdmin):
list_display=('incident','officer', 'allegation', 'finding', 'action')
search_fields = ['officer__last_name', 'incident__case_number']
resource_class = DetailsResource
class SiteTextAdmin(admin.ModelAdmin):
form=AdminTextForm
admin.site.register(Officer, OfficerAdmin)
admin.site.register(Incident, IncidentAdmin)
admin.site.register(Details, DetailsAdmin)
admin.site.register(SiteText, SiteTextAdmin)
And here's models.py
from __future__ import unicode_literals
from django.db import models
from tinymce import models as tinymce_models
class Officer(models.Model):
first_name = models.CharField(max_length=80, blank=True, null=True)
last_name = models.CharField(max_length=80, blank=True, null=True)
badge = models.IntegerField(blank=True, null=True)
department = models.CharField(max_length=50, blank=True, null=True)
model_pic = models.ImageField(upload_to = "police_archive/officer_photos", default= 'noimage', blank=True, null=True)
description = tinymce_models.HTMLField(blank=True, null=True)
def __str__(self):
return self.last_name + ', ' + self.first_name
class Meta():
ordering = ['last_name']
class Incident(models.Model):
officer = models.ManyToManyField(Officer, through='Details')
case_number = models.CharField(max_length=50, blank=True)
OFFICE_CHOICES = (
('CRA', 'Civilian Review Authority'),
('IA', 'Internal Affairs'),
('OPCR', 'Office of Police Conduct Review'),
)
office = models.CharField(max_length=10,
choices=OFFICE_CHOICES,
)
def __str__(self):
return self.case_number
class Meta():
ordering = ['-case_number']
class Details(models.Model):
officer = models.ForeignKey(Officer, on_delete=models.CASCADE, blank=True)
incident = models.ForeignKey(Incident, on_delete=models.CASCADE, blank=True)
allegation = models.CharField(max_length=50, blank=True)
finding = models.CharField(max_length=50, blank=True)
action = models.CharField(max_length=50, blank=True)
def __str__(self):
return self.officer.first_name + ' '+ self.officer.last_name+ ', ' + self.incident.case_number
class Meta():
verbose_name_plural = "details"
ordering = ['incident__case_number']
class SiteText(models.Model):
content1 = tinymce_models.HTMLField()
content2 = models.TextField(max_length=500, blank=True)
OK, I spent all day debugging yesterday and got everything working properly. Here's my admin.py now, models.py is unchanged. I forget exactly which change solved the original error I posted about.
from django.contrib import admin
from import_export import resources, widgets, fields
from import_export.admin import ImportExportModelAdmin, ImportExportActionModelAdmin
from forms import AdminTextForm, OfficerTextForm
from .models import Officer, Incident, Details, SiteText
class DetailsInlineAdmin (admin.TabularInline):
model = Details
extra = 5
class OfficerResource(resources.ModelResource):
class Meta:
model = Officer
class OfficerAdmin(ImportExportModelAdmin):
list_display = ('first_name', 'last_name', 'badge', 'department')
search_fields = ['first_name', 'last_name']
inlines = [DetailsInlineAdmin]
resource_class = OfficerResource
form=OfficerTextForm
class Media:
js = ('//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js','/static/admin/js/admin/popup.js')
class IncidentResource(resources.ModelResource):
class Meta:
fields = ('officer','case_number', 'office')
model = Incident
import_id_fields = ['case_number']
class IncidentAdmin(ImportExportModelAdmin):
list_display = ('office','case_number')
search_fields = ['case_number']
inlines = [DetailsInlineAdmin]
resource_class = IncidentResource
class DetailsResource(resources.ModelResource):
class BadgeForeignKeyWidget(widgets.ForeignKeyWidget):
def get_queryset(self, value, row):
return self.model.objects.filter(
badge__iexact=row["badge"]
)
officer = fields.Field(
column_name='officer',
attribute='officer',
widget=BadgeForeignKeyWidget(Officer, 'last_name'))
incident = fields.Field(
column_name='incident',
attribute='incident',
widget=widgets.ForeignKeyWidget(Incident, 'case_number'))
class Meta:
fields = ('id','officer','incident', 'allegation', 'finding', 'action')
model = Details
class DetailsAdmin(ImportExportModelAdmin):
list_display=('incident','officer', 'allegation', 'finding', 'action')
search_fields = ['officer__last_name', 'incident__case_number']
resource_class = DetailsResource
class SiteTextAdmin(admin.ModelAdmin):
form=AdminTextForm
admin.site.register(Officer, OfficerAdmin)
admin.site.register(Incident, IncidentAdmin)
admin.site.register(Details, DetailsAdmin)
admin.site.register(SiteText, SiteTextAdmin)
Another note is that you need to put an 'id' column in your spreadsheet. I was able to leave mine blank and then Django would generate an id to use as a primary key.
There is a class named Employees in models.py
class Employees(models.Model):
employee_id = models.CharField(verbose_name = _("Employee ID"), max_length=20, primary_key=True)
employee_name = models.CharField(verbose_name = _("Employee Name"), max_length=20)
department = models.CharField(verbose_name = _("Department"), max_length=100)
post = models.CharField(verbose_name = _("Post"), max_length=100)
Then I wrote some code in admin.py
class EmployeesAdmin(admin.ModelAdmin):
list_display = ('employee_id', 'employee_name', 'department', 'post')
According to the tutorial, there should be four fields in the Employee branch. But in my situation, there is only one field named Employees, just like I didn't add EmployeesAdmin class in admin.py. What's wrong with it? Did I miss something?
admin.py:
from django.contrib import admin
from .models import Employees, Purchase, ProductsOut
# Register your models here.
admin.site.register(Employees)
admin.site.register(Purchase)
admin.site.register(ProductsOut)
Register your admin in admin.site like:-
admin.site.register(ModelName, AdminName)
Try the following after declaring your EmployeesAdmin class in admin.py:
admin.site.register(Employees, EmployeesAdmin)