gpt4 book ai didi

django-cms - 是否有 django-CMS 插件可以链接到具有 URL 的对象?

转载 作者:行者123 更新时间:2023-12-02 00:18:51 24 4
gpt4 key购买 nike

我正在使用 Django 1.4 和 django-CMS 2.3。

我有几个带有 apphooks 的应用程序,我希望在 django-CMS 中能够引用一个应用程序的对象。

为了建立可持续的链接,我试图找到一个使用 django-CMS 菜单或通用外键的插件。

如果不存在这样的东西,那么最好的通用外键应用程序是什么?我刚刚使用 django.contrib.contenttypes 制作了一个小插件,它将选择限制为具有 get_absolute_url 方法的模型,但这太糟糕了。

谢谢。

最佳答案

我刚刚遇到你的问题。我最近为几个项目实现了类似的东西,这是我根据此处描述的 Adam Alton 的工作所做的:http://adamalton.co.uk/blog/displaying-django-genericforeignkey-as-single-form-field/

不是 CMSPlugin,但是,所以,我知道这并不能直接回答问题,但它是我所拥有的,我希望它可以帮助其他人寻找类似的解决方案。

作为概述,我在我的模型中定义了一个“横幅”类型,它代表我客户网站首页上的横幅。每个横幅都可以链接到其他内容。在这些情况下,链接目标可以是 Django-CMS 页面,或许多其他类型之一。所有方法都定义了 get_absolute_url 方法,尽管我没有使用内省(introspection)来确定这一点,我只是在此处出现的所有类型上实现了 get_absolute_url 。无论如何,这里是:

首先,这是横幅广告的简单模型:

class Banner(models.Model):
short_name = models.CharField(max_length=64, unique=True)
html = models.TextField()
link_text = models.CharField(max_length=128, default='Learn more')
destination_type = models.ForeignKey(ContentType, null=True, blank=True,
limit_choices_to={"model__in": ("Page", "Project", "Person", "Client")}
)
destination_id = models.PositiveIntegerField(null=True, blank=True)
destination = generic.GenericForeignKey('destination_type', 'destination_id')
published = models.BooleanField(blank=True, default=False)

def __unicode__(self):
return self.short_name

这是我的forms.py:

import re
from django.forms import ModelForm, ChoiceField
from cms.models import Page
from django.contrib.contenttypes.models import ContentType

from apps.your_application.models import Project, Person, Client

class BannerAdminForm(ModelForm):
class Meta:
model = Banner
fields = ("short_name", "html", "link_text", "destination", "link_hash", "published",)

# GenericForeignKey form field, will hold combined object_type and object_id
destination = ChoiceField(required=False) # Note the 'required=False' here.

def __init__(self, *args, **kwargs):
super(BannerAdminForm, self).__init__(*args, **kwargs)

# Combine object_type and object_id into a single 'destination' field
# Get all the objects that we want the user to be able to choose from

# Note: The user is going to locate these by name, so we should
# alphabetize all of these

available_objects = list(Page.objects.all().order_by('title_set__title'))
available_objects += list(Project.objects.all().order_by('title'))
available_objects += list(Person.objects.all().order_by('name'))
available_objects += list(Client.objects.all().order_by('name'))

# Now create our list of choices for the <select> field
object_choices = []
object_choices.append(["", "--"])
for obj in available_objects:
type_class = ContentType.objects.get_for_model(obj.__class__)
type_id = type_class.id
obj_id = obj.id
form_value = "type:%s-id:%s" % (type_id, obj_id) # e.g."type:12-id:3"
display_text = "%s : %s" % (str(type_class), str(obj)) # E.g. "Client : Apple, Inc."
object_choices.append([form_value, display_text])

self.fields['destination'].choices = object_choices

# If there is an existing value, pre-select it
if self.instance.destination:
type_class = ContentType.objects.get_for_model(self.instance.destination.__class__)
type_id = type_class.id
obj_id = self.instance.destination.id
current_value = "type:%s-id:%s" % (type_id, obj_id)
self.fields['destination'].initial = current_value

def save(self, *args, **kwargs):
try:
#get object_type and object_id values from combined destination field
object_string = self.cleaned_data['destination']
matches = re.match("type:(\d+)-id:(\d+)", object_string).groups()
object_type_id = matches[0] # get 45 from "type:45-id:38"
object_id = matches[1] # get 38 from "type:45-id:38"
object_type = ContentType.objects.get(id=object_type_id)
self.cleaned_data['destination_type'] = object_type_id
self.cleaned_data['destination_id'] = object_id
self.instance.destination_id = object_id
self.instance.destination_type = object_type
except:
# If anything goes wrong, leave it blank,
# This is also the case for when '--' is chosen
# In the drop-down (tsk, tsk, bad code style =/)
self.cleaned_data['destination_type'] = None
self.cleaned_data['destination_id'] = None
self.instance.destination_id = None
self.instance.destination_type = None

return super(BannerAdminForm, self).save(*args, **kwargs)

然后您可以通过调用获取目标对象的 URL {% if banner.destination %}{{ banner.destination.get_absolute_url }}{% endif %}在你的模板中。

工作良好,在 CMSPlugin 中使用应该不会太难。

This is what it looks like in Django Admin

编辑:实际上,我刚刚实现了与 CMSPlugin 表单完全相同的东西。存在本质上的差异。请记住将表单添加到 cms_plugins.py 文件中的插件类,如下所示:

class CMSBannerPlugin(CMSPluginBase):
form = BannerAdminForm # <==== Don't forget this part
model = Banner
name = _("Banner Plugin")
render_template = "apps/your_application/_banner.html"

def render(self, context, instance, placeholder):
...
return context

plugin_pool.register_plugin(CMSBannerPlugin)

关于django-cms - 是否有 django-CMS 插件可以链接到具有 URL 的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11810862/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com