2016-06-01 9 views
0

私はこのような私のmodels.pyありますリミットの選択肢と(RESTにも)関連するオブジェクトへのDjangoの外部キーを検証

class Category(models.Model): 
    user = models.ForeignKey(User) 
    name = models.CharField(max_length=256, db_index=True) 

class Todo(models.Model): 
    user = models.ForeignKey(User) 
    category = models.ForeignKey(Category) 
    ... 

を私はTodo.user = Category.userのみのものにTodoためCategoryの選択肢を制限したいです

私が見つけたすべての解決策は、クエリーセットをModelFormに設定するか、フォーム内にメソッドを実装することでした。 (limit_choices_toと同じように、それは(可能ではないでしょうか?))

問題は、私は、このような制限の問題で一つのモデルだけでなく、を持っているということである(例えばTag、など)。また

、私はジャンゴRESTフレームワークを使用していますだから、Todoが追加または編集されたときにCategoryをチェックする必要があります。

だから、私もそう

を(それがモデルのcleanfull_cleanメソッドを呼び出さないとlimit_choices_toをチェックしないよう)シリアライザで機能validateは、右のモデルを制限する必要がある、私は簡単な解決策、探していましたdjango AdminとRESTフレームワークの両方で動作します。

単純な方法で実装することができない場合は、最も難しい方法でコードを作成する方法のアドバイスを探しています。私は、これまでに発見した。ここ

答えて

1

Foreignkeyを取得するには、右の管理者であった、あなたはManyToManyFieldは右InlineModelAdminに示した取得するにModelAdmin

class TodoAdminForm(ModelForm): 
    def __init__(self, *args, **kwargs): 
     super().__init__(*args, **kwargs) 
     self.fields['category'].queryset = Category.objects.filter(user__pk=self.instance.user.pk) 

@admin.register(Todo) 
class TodoAdmin(admin.ModelAdmin): 
    form = TodoAdminForm 
    ... 

でフォームを指定する必要があります(例えばTabularInlineを)ここでは、より汚れたハックが発生します(より良い結果が得られますか?)

オブジェクトからquiringフィールド値を保存し、手動でクエリーセットをフィールドに設定する必要があります。私throughモデルは、2人のメンバーtodotag

を持っていると私はtagフィールド(Tagをモデル化するために指して)フィルタリングしたいと思います:DjangoのRESTフレームワークにのみ関連する要素を制限するために、

class MembershipInline(admin.TabularInline): 
    model = Todo.tags.through 

    def get_formset(self, request, obj=None, **kwargs): 
     request.saved_user_pk = obj.user.pk # Not sure if it can be None 
     return super().get_formset(request, obj, **kwargs) 

    def formfield_for_foreignkey(self, db_field, request=None, **kwargs): 
     if db_field.name == 'tag': 
      kwargs['queryset'] = Tag.objects.filter(user__pk=request.saved_user_pk) 
     return super().formfield_for_foreignkey(db_field, request, **kwargs) 

そして最後に、私はカスタムにField

class PrimaryKeyRelatedByUser(serializers.PrimaryKeyRelatedField): 
    def get_queryset(self): 
     return super().get_queryset().filter(user=self.context['request'].user) 

を実装し、

ように私のシリアライザでそれを使用する必要があります
class TodoSerializer(serializers.ModelSerializer): 
    category = PrimaryKeyRelatedByUser(required=False, allow_null=True, queryset=Category.objects.all()) 
    tags = PrimaryKeyRelatedByUser(required=False, many=True, queryset=Tag.objects.all()) 

class Meta: 
    model = Todo 
    fields = ('id', 'category', 'tags', ...) 

実際にすべてのケースで計画どおりに作業しているかどうかは不明です。私はこの小さな調査を続けます。

まだ質問が残っています。もっとシンプルにできますか?

関連する問題