Как можно использовать общее представление update_object в Django для редактирования форм унаследованных моделей?
-
03-07-2019 - |
Вопрос
В Django приведены выдержки из приложения животные вот так:
А животные/models.py с:
from django.db import models
from django.contrib.contenttypes.models import ContentType
class Animal(models.Model):
content_type = models.ForeignKey(ContentType,editable=False,null=True)
name = models.CharField()
class Dog(Animal):
is_lucky = models.BooleanField()
class Cat(Animal):
lives_left = models.IntegerField()
И животные/urls.py:
from django.conf.urls.default import *
from animals.models import Animal, Dog, Cat
dict = { 'model' : Animal }
urlpatterns = (
url(r'^edit/(?P<object_id>\d+)$', 'create_update.update_object', dict),
)
Как можно использовать общие представления для редактирования собак и/или кошек, используя одну и ту же форму?
Т.е.А форма объект, который передается животные/animal_form.html будет Animal и, следовательно, не будет содержать никаких особенностей производных классов Dog и Cat.Как я мог бы заставить Django автоматически передавать форму дочернему классу животное/animals_form.html?
Я, кстати, использую Джангосниппеты #1031 для управления ContentType, поэтому у Animal будет метод с именем as_leaf_class который возвращает производный класс.
Очевидно, что можно создавать формы для каждого производного класса, но это будет довольно много ненужного дублирования (поскольку все шаблоны будут универсальными — по сути, {{ form.as_p }}).
Кстати, лучше всего предположить, что Animal, вероятно, будет одним из нескольких несвязанных базовых классов с одной и той же проблемой, поэтому идеальным решением будет обобщенное решение.
Заранее благодарю за помощь.
Решение
Хорошо, вот что я сделал, и, похоже, это работает и представляет собой разумный дизайн (хотя меня могут поправить!).
В основной библиотеке (например.mysite.core.views.create_update), я написал декоратор:
from django.contrib.contenttypes.models import ContentType
from django.views.generic import create_update
def update_object_as_child(parent_model_class):
"""
Given a base models.Model class, decorate a function to return
create_update.update_object, on the child class.
e.g.
@update_object(Animal)
def update_object(request, object_id):
pass
kwargs should have an object_id defined.
"""
def decorator(function):
def wrapper(request, **kwargs):
# may raise KeyError
id = kwargs['object_id']
parent_obj = parent_model_class.objects.get( pk=id )
# following http://www.djangosnippets.org/snippets/1031/
child_class = parent_obj.content_type.model_class()
kwargs['model'] = child_class
# rely on the generic code for testing/validation/404
return create_update.update_object(request, **kwargs)
return wrapper
return decorator
А в Animals/views.py у меня есть:
from mysite.core.views.create_update import update_object_as_child
@update_object_as_child(Animal)
def edit_animal(request, object_id):
pass
И в животные/urls.py у меня есть:
urlpatterns += patterns('animals.views',
url(r'^edit/(?P<object_id>\d+)$', 'edit_animal', name="edit_animal"),
)
Теперь мне нужна только уникальная функция редактирования для каждого базового класса, которую легко создать с помощью декоратора.
Надеюсь, кто-то найдет это полезным, и я буду рад получить обратную связь.
Другие советы
AFAICT, кошки и собаки находятся в разных таблицах БД, и, возможно, таблицы Animal нет.но вы используете один шаблон URL для всех.где-то нужно выбирать между каждым.
Я бы использовал разные шаблоны URL-адресов для кошек и собак, оба вызывали бы 'create_update.update_object'
;но используя другой dict
для каждого.один с 'model':Dog
и другой с 'model':Cat
или, может быть, вам нужна одна таблица, где каждая запись может быть кошкой или собакой?я не думаю, что для этого можно использовать унаследованные модели.