2015-07-23 3 views
7

Я пытаюсь ограничить Django Admin выбором ForeignKey, используя limit_choices_to, но я не могу понять, как это сделать правильно.Django ForeignKey limit_choices_to other ForeignKey id

Этот код делает то, что я хочу, если идентификатор категории равен 16, но я не могу понять, как использовать идентификатор текущей категории, а не жестко-кодировать его.

class MovieCategory(models.Model):  
    category = models.ForeignKey(Category) 
    movie = models.ForeignKey(Movie) 
    prefix = models.ForeignKey('Prefix', limit_choices_to={'category_id': '16'}, 
           blank=True, null=True) 
    number = models.DecimalField(verbose_name='Movie Number', max_digits=2, 
           blank=True, null=True, decimal_places=0) 

Можно ли как-то ссылаться на идентификатор категории ForeignKey?

+0

Если вы довольны только поднятием ошибки проверки, см. Http://stackoverflow.com/q/37946885/247696 – Flimm

ответ

13

После нескольких часов чтения вопросов, связанных с полу, я, наконец, понял это.

Вы не можете самостоятельно ссылаться на модель так, как я пытался это сделать, нет способа заставить django действовать так, как я хотел использовать limit_choices_to, потому что он не может найти идентификатор другого ForeignKey в той же модели ,

Это может быть сделано, если вы измените способ работы django, но более простой способ решить это - это внести изменения в admin.py.

Вот что это выглядит как в моем models.py:

# models.py 
class MovieCategory(models.Model):  
    category = models.ForeignKey(Category) 
    movie = models.ForeignKey(Movie) 
    prefix = models.ForeignKey('Prefix', blank=True, null=True) 
    number = models.DecimalField(verbose_name='Movie Number', max_digits=2, 
           blank=True, null=True, decimal_places=0) 

Я просто удалены limit_choices_to полностью. Я нашел похожую проблему here с решением отправил Kyle Duncan. Разница заключается в том, что это использует ManyToMany, а не ForeignKey. Это означает, что мне пришлось удалить filter_horizontal = ('prefix',) под мой класс MovieCategoryAdmin(admin.ModelAdmin):, поскольку это только для полей ManyToMany.

В admin.py Для создания формы вам нужно добавить from django import forms. Это как форма выглядит:

class MovieCategoryForm(forms.ModelForm): 

    class Meta: 
     model = MovieCategory 
     fields = ['prefix'] 

    def __init__(self, *args, **kwargs): 
     super(MovieCategoryForm, self).__init__(*args, **kwargs) 
     self.fields['prefix'].queryset = Prefix.objects.filter(
             category_id=self.instance.category.id) 

И мой AdminModel:

class MovieCategoryAdmin(admin.ModelAdmin): 
    """ 
    Admin Class for 'Movie Category'. 
    """ 
    fieldsets = [ 
     ('Category',  {'fields': ['category']}), 
     ('Movie',   {'fields': ['movie']}), 
     ('Prefix',  {'fields': ['prefix']}), 
     ('Number',  {'fields': ['number']}), 
    ] 
    list_display = ('category', 'movie', 'prefix', 'number') 
    search_fields = ['category__category_name', 'movie__title', 'prefix__prefix'] 
    form = MovieCategoryForm 

Это точно, как Кайл описывает это в своем ответе, за исключением того, я должен был добавить fields = ['prefix'] к форме или Wouldn» t запустить. Если вы выполните его шаги и не забудьте удалить filter_horizontal и добавить поля, которые вы используете, они должны работать.

Редактировать: Это решение отлично работает при редактировании, но не при создании новой записи, поскольку не может найти идентификатор категории, если он не выходит. Я пытаюсь выяснить, как это решить.

+1

Поскольку я был довольно занят, я закодировал проблему создания новых элементов. В настоящее время я создаю новые элементы в модели категорий, а не в этом, и поскольку префикс имеет чужой ключ, связывающий его с тем, что проблема устранена для меня. Если я найду способ решить эту проблему, я обновлю свое решение, но, поскольку он стоит, он делает то, что нужно для моего приложения. – ti66

+1

Это было очень полезно, спасибо. – Hassan

0

Другой подход, если вы не хотите добавлять пользовательский ModelForm, должен обрабатывать это в методе get_form() ModelAdmin. Это было предпочтительнее для меня, потому что мне нужен был легкий доступ к объекту запроса для моего запроса.

class StoryAdmin(admin.ModelAdmin): 

    def get_form(self, request, obj=None, **kwargs): 
     form = super(StoryAdmin, self).get_form(request, obj, **kwargs) 

     form.base_fields['local_categories'].queryset = LocalStoryCategory.\ 
      objects.filter(office=request.user.profile.office) 

     return form 
-1

У меня был тот же вопрос, и ваш ответ сам помог мне начать. Но я также нашел еще одну запись (question-12399803), которая завершила ответ, то есть, как фильтровать при создании новой записи.

В views.py

form = CustomerForm(groupid=request.user.groups.first().id) 

В формах.ру

def __init__(self, *args, **kwargs): 
    if 'groupid' in kwargs: 
     groupid = kwargs.pop('groupid') 
    else: 
     groupid = None 
    super(CustomerForm, self).__init__(*args, **kwargs) 
    if not groupid: 
     groupid = self.instance.group.id 
    self.fields['address'].queryset = Address.objects.filter(group_id=groupid) 

Так ли добавление нового клиента или обновление существующего клиента, я могу нажать на ссылку для перехода добавить новый адрес, который будет назначен для этого клиента.

Это мой первый ответ на StackOverflow. Я надеюсь, что это помогает.