Django管理与CMS模板开发全解析
立即解锁
发布时间: 2025-08-22 01:25:46 阅读量: 1 订阅数: 2 


Django Web开发实战秘籍
### Django管理与CMS模板开发全解析
#### 一、开发变更列表过滤器
在管理系统中,若希望管理员能依据日期、关系或字段选项对变更列表进行过滤,可使用管理模型的`list_filter`属性,同时也能创建自定义过滤器。下面以按产品附带照片数量筛选产品为例进行说明。
##### 1. 准备工作
从之前创建的`products`应用开始。
##### 2. 操作步骤
- **创建`PhotoFilter`类**:在`admin.py`文件中创建一个继承自`SimpleListFilter`的`PhotoFilter`类。
```python
#products/admin.py
# -*- coding: UTF-8 -*-
# ... all previous imports go here ...
from django.db import models
class PhotoFilter(admin.SimpleListFilter):
# 人类可读的标题,将显示在管理侧边栏过滤器选项上方
title = _("photos")
# 用于URL查询的过滤器参数
parameter_name = "photos"
def lookups(self, request, model_admin):
"""
返回一个元组列表。每个元组的第一个元素是将出现在URL查询中的选项编码值,
第二个元素是将出现在右侧边栏中的选项的人类可读名称。
"""
return (
("0", _("Has no photos")),
("1", _("Has one photo")),
("2+", _("Has more than one photo")),
)
def queryset(self, request, queryset):
"""
根据查询字符串中提供的值返回过滤后的查询集,可通过`self.value()`获取该值。
"""
if self.value() == "0":
return queryset.annotate(
num_photos=models.Count("productphoto")
).filter(num_photos=0)
if self.value() == "1":
return queryset.annotate(
num_photos=models.Count("productphoto")
).filter(num_photos=1)
if self.value() == "2+":
return queryset.annotate(
num_photos=models.Count("productphoto")
).filter(num_photos__gte=2)
```
- **添加列表过滤器到`ProductAdmin`**:
```python
class ProductAdmin(admin.ModelAdmin):
# ...
list_filter = [PhotoFilter]
```
##### 3. 工作原理
新创建的列表过滤器将显示在产品列表的侧边栏。`PhotoFilter`类有可翻译的标题和查询参数名作为属性,还有两个方法:`lookups`定义过滤器的选项,`queryset`定义选择特定值时如何过滤对象的查询集。在`lookups`方法中定义了三个选项,在`queryset`方法中使用`annotate`方法选择每个产品的照片数量,并根据所选选项进行过滤。更多关于聚合函数(如`annotate`)的信息,可参考官方Django文档:[https://docs.djangoproject.com/en/1.6/topics/db/aggregation/](https://docs.djangoproject.com/en/1.6/topics/db/aggregation/)
#### 二、交换外部应用的管理设置
Django应用和第三方应用都有各自的管理设置,但可以关闭这些设置并使用自定义的更好的管理设置。以下以交换`django.contrib.auth`应用的管理设置为例。
##### 1. 准备工作
创建一个名为`custom_admin`的应用,其中`models.py`文件为空,并将该应用添加到`settings.py`的`INSTALLED_APPS`中。
##### 2. 操作步骤
在`custom_admin`应用的新`admin.py`文件中插入以下内容:
```python
#custom_admin/admin.py
# -*- coding: UTF-8 -*-
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin, GroupAdmin
from django.contrib.auth.models import User, Group
from django.utils.translation import ugettext_lazy as _
class UserAdminExtended(UserAdmin):
list_display = ("username", "email", "first_name", "last_name",
"is_active", "is_staff", "date_joined", "last_login")
list_filter = ("is_active", "is_staff", "is_superuser",
"date_joined", "last_login")
ordering = ("last_name", "first_name", "username")
save_on_top = True
class GroupAdminExtended(GroupAdmin):
list_display = ("__unicode__", "display_users")
save_on_top = True
def display_users(self, obj):
links = []
for user in obj.user_set.all():
links.append(
"""<a href="/admin/auth/user/%d/" target="_blank">%s
</a>""" % (
user.id,
(u"%s %s" % (user.first_name, user.last_name)).strip() or user.username,
)
)
return u"<br />".join(links)
display_users.allow_tags = True
display_users.short_description = _("Users")
admin.site.unregister(User)
admin.site.unregister(Group)
admin.site.register(User, UserAdminExtended)
admin.site.register(Group, GroupAdminExtended)
```
##### 3. 工作原理
创建了两个模型管理类`UserAdminExtended`和`GroupAdminExtended`,分别继承自`UserAdmin`和`GroupAdmin`类,并覆盖了一些属性。然后注销了`User`和`Group`模型的现有管理类,注册了新的修改后的类。修改后的用户管理设置在列表视图中显示的字段比默认设置更多,还添加了额外的过滤器和排序选项,并在编辑表单顶部显示提交按钮。在新的组管理设置的变更列表中,会显示分配到特定组的用户。
#### 三、在变更表单中插入地图
接下来将创建`locations`应用和`Location`模型,并覆盖变更表单模板以添加谷歌地图,方便管理员查找并标记位置的地理坐标。
##### 1. 准备工作
创建`locations`应用并将其添加到`INSTALLED_APPS`中。在`models.py`中创建`Location`模型。
```python
#locations/models.py
# -*- coding: UTF-8 -*-
from django.db import models
from django.utils.translation import ugettext_lazy as _
COUNTRY_CHOICES = (
("UK", _("United Kingdom")),
("DE", _("Germany")),
("FR", _("France")),
("LT", _("Lithuania")),
)
class Location(models.Model):
title = models.CharField(_("title"), max_length=255, unique=True)
description = models.TextField(_("description"), blank=True)
street_address = models.CharField(_("street address"),
max_length=255, blank=True)
street_address2 = models.CharField(_("street address (2nd line)"),
max_length=255, blank=True)
postal_code = models.CharField(_("postal code"), max_length=10,
blank=True)
city = models.CharField(_("city"), max_length=255, blank=True)
country = models.CharField(_("country"), max_length=2, blank=True,
choices=COUNTRY_CHOICES)
latitude = models.FloatField(_("latitude"), blank=True, null=True,
help_text=_("Latitude (Lat.) is the angle between any point "
"and the equator "
"(north pole is at 90; south pole is at -90)."))
longitude = models.FloatField(_("longitude"), blank=True,
null=True,
help_text=_("Longitude (Long.) is the angle east or west of "
"an arbitrary point on Earth from Greenwich (UK), "
"which is the international zero-longitude point "
"(longitude=0 degrees). "
"The anti-meridian of Greenwich is both 180 "
"(direction to east) and -180 (direction to west)."))
class Meta:
verbose_name = _("Location")
verbose_name_plural = _("Locations")
def __unicode__(self):
return self.title
```
##### 2. 操作步骤
- **分组字段到字段集**:在`admin.py`中对字段进行分组。
```python
#locations/admin.py
# -*- coding: UTF-8 -*-
from django.utils.translation import ugettext_lazy as _
from django.contrib import admin
from models import Location
class LocationAdmin(admin.ModelAdmin):
save_on_top = True
list_displ
```
0
0
复制全文
相关推荐










