2016-06-01 4 views
0

Ich habe meine models.py wie dies bestätigen:Limit-Entscheidungen und Djangos Fremdschlüssel zu verwandten Objekten (auch in REST) ​​

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) 
    ... 

Und ich Entscheidungen von Category für Todo nur auf diejenigen diejenigen beschränken möchten, wo Todo.user = Category.user

Jede Lösung, die ich gefunden habe, war Abfrage-Set für eine ModelForm setzen oder Methode in einem Formular implementieren. (Wie bei limit_choices_to es nicht möglich ist (?))

Das Problem ist, dass ich mit einer solchen Begrenzung Problem nicht nur ein Modell (zB Tag, etc.)

Auch ich bin mit django REST Rahmen , also muss ich Category überprüfen, wenn Todo hinzugefügt oder bearbeitet wird.

Also, ich auch Funktionen benötigen validate in Serializer Modelle Recht zu begrenzen (da es nicht Modells clean nicht nennen, full_clean Methoden und prüft nicht limit_choices_to)

Also, ich bin auf der Suche nach einer einfachen Lösung, die funktioniert sowohl für django Admin als auch REST Framework.

Oder, wenn es nicht möglich ist, es auf die einfache Art und Weise zu implementieren, suche ich nach einem Ratschlag, wie man es am schmerzlosesten beschreibt.

Antwort

1

Hier ist, was ich bisher gefunden habe:

Foreignkey in Admin zeigte Recht zu erhalten, müssen Sie in ModelAdmin

ein Formular angeben
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 
    ... 

in InlineModelAdminManyToManyField zeigte recht zu erhalten (zB TabularInline) hier kommt mehr dreckiger hack (kann es besser gemacht werden?)

Sie müssen Ihre Quiring-Feld Wert aus Objekt und dann manuell setzen queryset in das Feld. Mein through Modell hat zwei Mitglieder todo und tag

Und ich möchte tag Feld filtern (zeigt Tag Modell):

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) 

Und schließlich auf Elemente beschränken sich nur auf verwandte in Django REST Rahmen, ich habe benutzerdefinierte Field

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

implementieren und es in meinem Serializer verwenden wie

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', ...) 

Nicht sicher, ob es tatsächlich in allen Fällen wie geplant funktioniert. Ich werde diese kleine Untersuchung fortsetzen.

Frage bleibt noch. Könnte es einfacher gemacht werden?

Verwandte Themen