2013-09-03 2 views
1

Поскольку нам нужны наши ModelChoiceFields, чтобы иметь разные (не __unicode__) ярлыки на основе того, где они используются, я подумал, что было бы разумной идеей переопределить ModelChoiceField и заставить его принять дополнительный параметр, который будет вместо label_from_instance. Я мог бы сделать подкласс для каждого экземпляра, который нам нужен, но это не совсем СУХОЙ, не так ли?Переопределение модели Django ModelChoiceField

Мой новый ModelChoiceField:

import django.forms 


class ModelChoiceField(django.forms.ModelChoiceField): 
    """Subclasses Django's ModelChoiceField and adds one parameter, `obj_label`. 
    This should be a callable with one argument (the current object) which 
    returns a string to use as the label of that object or instance.""" 

    def __init__(self, obj_label=None, *args, **kwargs): 
     super(django.forms.ModelChoiceField, self).__init__(*args, **kwargs) 
     self.obj_label = obj_label 

    def label_from_instance(self, obj): 
     if self.obj_label: 
      return self.label(obj) 
     return super(django.forms.ModelChoiceField, self).label_from_instance(obj) 

кажется простым и достаточно легко. Меня интересует только аргумент obj_label и передайте все остальное в функцию __init__ ModelChoiceField. Или так я думал. Python теперь жалуется на __init__ получать аргументы неожиданного ключевого слова ... Я звоню это так: nationality = ModelChoiceField(queryset=Country.objects.all(), obj_label=lambda x: x.name(), empty_label=None), и ошибка:

Traceback: 
File "/home/patrick/spng/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response 
    103.      resolver_match = resolver.resolve(request.path_info) 
File "/home/patrick/spng/lib/python2.7/site-packages/django/core/urlresolvers.py" in resolve 
    321.      sub_match = pattern.resolve(new_path) 
File "/home/patrick/spng/lib/python2.7/site-packages/django/core/urlresolvers.py" in resolve 
    321.      sub_match = pattern.resolve(new_path) 
File "/home/patrick/spng/lib/python2.7/site-packages/django/core/urlresolvers.py" in resolve 
    223.    return ResolverMatch(self.callback, args, kwargs, self.name) 
File "/home/patrick/spng/lib/python2.7/site-packages/django/core/urlresolvers.py" in callback 
    230.   self._callback = get_callable(self._callback_str) 
File "/home/patrick/spng/lib/python2.7/site-packages/django/utils/functional.py" in wrapper 
    29.   result = func(*args) 
File "/home/patrick/spng/lib/python2.7/site-packages/django/core/urlresolvers.py" in get_callable 
    97.    mod = import_module(mod_name) 
File "/home/patrick/spng/lib/python2.7/site-packages/django/utils/importlib.py" in import_module 
    35.  __import__(name) 
File "/home/patrick/spng/src/internship/views.py" in <module> 
    40. from resume.views import assemble_dict_list 
File "/home/patrick/spng/src/resume/views.py" in <module> 
    20. from resume.forms import (HobbyForm, LanguageForm, EducationForm, 
File "/home/patrick/spng/src/resume/forms.py" in <module> 
    29. class NationalityForm(forms.ModelForm): 
File "/home/patrick/spng/src/resume/forms.py" in NationalityForm 
    31.  nationality = ModelChoiceField(queryset=Country.objects.all(), obj_label=lambda x: x.nationality(), empty_label=None) 
File "/home/patrick/spng/src/stageplaza_ng/fields.py" in __init__ 
    11.   super(django.forms.ModelChoiceField, self).__init__(*args, **kwargs) 
File "/home/patrick/spng/lib/python2.7/site-packages/django/forms/fields.py" in __init__ 
    672.           initial=initial, help_text=help_text, *args, **kwargs) 

Exception Type: TypeError at /stagiaires/overzicht/ 
Exception Value: __init__() got an unexpected keyword argument 'queryset' 

Это, вероятно, что-то действительно глупо, так что кто-нибудь есть идеи?

+1

Переименуйте свой класс, отличный от 'ModelChoiceField' –

ответ

4

Переименовать класс, кроме ModelChoiceField, пожалуйста, заботиться о оставшейся логике

class CustomModelChoiceField(django.forms.ModelChoiceField): 
     """Subclasses Django's ModelChoiceField and adds one parameter, `obj_label`. 
     This should be a callable with one argument (the current object) which 
     returns a string to use as the label of that object or instance.""" 

     def __init__(self, obj_label=None, *args, **kwargs): 
      super(CustomModelChoiceField, self).__init__(*args, **kwargs) 
      self.obj_label = obj_label 

     def label_from_instance(self, obj): 
      if self.obj_label: 
       return self.label(obj) 
      return super(CustomModelChoiceField, self).label_from_instance(obj) 
+1

Помимо переименования, вы также исправили проблему :) У меня была неправильная модель в супервызове ... – Xudonax

+0

Где вы это реализуете? forms.py? полезно ли использовать модель, привязанную к внешнему ключу, и разбивать поля отображения для пользователя? –

0

Оказывается, это действительно было что-то глупо. Я называл Django ModelChoiceField супер в моем супер-вызове. Примерно так: super(django.forms.ModelChoiceField, self).__init__(*args, **kwargs). В этом случае я получаю это исключение. ModelChoiceField super - это ChoiceField. И этот класс не принимает аргумент ключевого слова по имени queryset.

Фактически, я должен был назвать супер текущего класса. Примерно так: super(ModelChoiceField, self).__init__(*args, **kwargs). Это много раз в документах, но на этот раз я пропустил это. Правильное переопределение для ModelChoiceField:

import django.forms 


class ModelChoiceField(django.forms.ModelChoiceField): 
    """Subclasses Django's ModelChoiceField and adds one parameter, `obj_label`. 
    This should be a callable with one argument (the current object) which 
    returns a string to use as the label of that object or instance.""" 

    def __init__(self, obj_label=None, *args, **kwargs): 
     super(ModelChoiceField, self).__init__(*args, **kwargs) 
     self.obj_label = obj_label 

    def label_from_instance(self, obj): 
     if self.obj_label: 
      return self.label(obj) 
     return super(ModelChoiceField, self).label_from_instance(obj) 

Это работает. Но я должен частично согласиться с ответом Шриниваса. Яснее переименовать в ModelChoiceField, чтобы сразу стало ясно, что происходит.

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