2013-06-08 2 views
0

Я написал карусельный плагин для Django-CMS, который отображает скриншоты. Базовая модель имеет некоторые параметры карусельного связаны (высота, анимации стиль и т.д.), а также ForeignKey к ScreenshotGroup:Как адаптировать Django ForeignKey к многоразовому приложению?

class ScreenshotGroup(models.Model): 
    name = models.CharField(max_length=60) 
    screenshots = models.ManyToManyField(Screenshot, through="ScreenshotGroupMember") 

class Screenshot(models.Model): 
    name = models.CharField(max_length=60) 
    desc = models.TextField(_("description"), blank=True) 
    img = models.ImageField(upload_to='img/') 

class CarouselPluginModel(CMSPlugin): 
    group = models.ForeignKey(ScreenshotGroup) 
    height = models.IntegerField() 
    ... 

Метод вид карусели содержит:

context['item_list'] = instance.group.screenshots.all() 

(На самом деле, поскольку я использую Django-CMS, это в cms_plugins.pyrender методе, а не view метода)

шаблон относится к полям скриншота с помощью:.

{% for item in item_list %} 
    {{ item.name }} 
    {{ item.desc }} 
    ...{{ item.img }}... 
{% endfor %} 

Мой вопрос: Я хочу обобщить свой плагин для карусели, чтобы повторно использовать его в других проектах, так что это не зависит от модели Screenshot. Я могу заменить содержимое цикла шаблона for на include, чтобы каждый проект мог указать, как отображать элемент в карусели. Но как я могу обобщить CarouselPluginModelForeignKey?

В любом конкретном приложении мне нужен только один тип модели (ScreenshotGroup в моем примере). Я не хочу, чтобы консоль администратора позволяла включать любые другие модели.

Спасибо!

ответ

2

Основываясь на общей идее иностранного ключа, предложенной karthikr, вот полное решение, которое я принял. Остальные части головоломок являются:

  • используя запись в settings.py ограничить, какие модели разрешены в этом общих внешнем ключе;
  • нюхание для поля многих-ко-многим выбранной модели;
  • используя {% include "carousel_item.html" %} в шаблон, чтобы обобщить отображение товара. Я поставлю реализацию по умолчанию в приложении, но таким образом конечный пользователь не должен соответствовать полям, которые я предварительно определяю.

В models.py:

from django.contrib.contenttypes.models import ContentType 
from django.contrib.contenttypes import generic 
from django.conf import settings 

allowed_models = getattr(settings, 'ALLOWED_MODELS_IN_CAROUSEL', []) 
# must be a list of dictionaries with keys: app_label and model, e.g: 
# ALLOWED_MODELS_IN_CAROUSEL=[{'app_label':'myapp', 'model':'screenshotgroup'},] 

fk_models = None 
if allowed_models: 
    # don't like this repetition - how can I improve this? 
    fk_models = models.Q(app_label = allowed_models[0]['app_label'].lower(), 
         model = allowed_models[0]['model'].lower()) 
    for m in allowed_models[1:]: 
     fk_models = fk_models | models.Q(app_label = m['app_label'].lower(), 
             model = m['model'].lower()) 

class CarouselPluginModel(CMSPlugin): 
    content_type = models.ForeignKey(ContentType, limit_choices_to = fk_models) 
    object_id = models.PositiveIntegerField() 
    content_group = generic.GenericForeignKey('content_type', 'object_id') 
    ... 

мнение нужно найти ManyToManyField в выбранной модели, например:

if instance.content_group and instance.content_group._meta.many_to_many: 
    m2m_fieldname = instance.content_group._meta.many_to_many[0].name 
    context['item_list'] = getattr(instance.content_group, m2m_fieldname).all() 

Шаблон может выглядеть следующим образом:

{% for item in item_list %} 
    {% include "carousel_item.html" %} 
{% endfor %} 

И, наконец, я включу рекомендацию что модель, которую вы используете, включает ее описание id, так как административной панели необходимо будет выбрать ее по идентификатору, например:

class ScreenshotGroup(models.Model): 
    name = models.CharField(max_length=60) 
    screenshots = models.ManyToManyField(Screenshot, through="ScreenshotGroupMember") 
    def __unicode__(self): 
     return u"{0} (id {1})".format(self.name, self.id) 

 Смежные вопросы

  • Нет связанных вопросов^_^