2015-10-20 4 views
1

Я обновляю приложение django от 1.4 до 1.8 и ударил небольшую проблему с администратором django.Django admin form и inlined model со значением по умолчанию

Мои модели выглядят как этот

def new_key(): 
    return binascii.b2a_hex(os.urandom(20)) 

class ApiKey(models.Model): 
    customer = models.ForeignKey(UserProfile) 
    key = models.CharField(max_length=40, default=new_key) 

И admin.py является

class ApiKeyInline(admin.StackedInline): 
    model = ApiKey 
    extra = 0 

class UserProfileAdmin(admin.ModelAdmin): 
    inlines = [ApiKeyInline] 

admin.site.register(UserProfile, UserProfileAdmin) 

При использовании администратор страницы апи ключ некорректной заполняется случайным значением. Однако при сохранении UserProfile он не сохраняется, как будто ничего не было добавлено. Если я вручную изменю один летер в автогенерированном ключе, то сработает правильно. Мне кажется, что это проблема с джанго, обнаруживающим изменение или что-то в этом роде.

Любые предложения? Код работал в 1.4.

ответ

1

Краткое расследование ведет меня к save_new_objects от class BaseModelFormSet, расположенной по адресу django/forms/models.py. Он имеет следующую проверку: if not form.has_changed()

Выглядит многообещающе, да? Теперь мы хотим «улучшить» этот метод. Когда начать? Ну ... Inlines наследует от InlineModelAdmin, который имеет метод get_formset. Так что ...

class ApiKeyInline(admin.StackedInline): 
    model = ApiKey 
    extra = 0 

    def get_formset(self, *args, **kwargs): 
     formset = super(EmailInlineAdmin, self).get_formset(*args, **kwargs) 
     # at this point, formset is a generated class called like "ApiKeyFormSet" 
     # as it is a regular python objects, no one stops us from playing with it 
     formset.save_new_objects = ApiKeyInline.my_own_save_new_objects_method 
     return formset 

    def my_own_save_new_objects_method(self, commit=True): 
     # here should be something like 
     # django/forms/models.py BaseModelFormSet.save_new_objects 
     return self.new_objects 

Содержимое my_own_save_new_objects_method вы должны изменить себя. Оригинальный метод, опять же, находится в dist-packages/django/forms/models.py, либо назовите его через супер, либо напишите что-то полностью ваше, так или иначе пропустите чек.

Также, возможно, это ужасное и сложное решение. У меня такое чувство, что должен быть лучший. В примере, не устанавливая default=new_key в вашей модели, но устанавливая значение по умолчанию для поля формы, например.

3

Существует решение в одном из старых нитей: How to force-save an "empty"/unchanged django admin inline?

Вы должны отметить свой инлайн форму, как всегда изменяется.

from django.forms import ModelForm 
from .models import UserProfile 

class AlwaysChangedModelForm(ModelForm): 
    def has_changed(self): 
     """ Should returns True if data differs from initial. 
      By always returning true even unchanged inlines will get validated and saved.""" 
     return True 

#An inline model 
class ApiKey(admin.StackedInline): 
    model = ApiKey 
    extra = 0 
    form = AlwaysChangedModelForm 
Смежные вопросы