2014-10-02 11 views
8

Mam model profilu, który ma relację jeden-do-jednego z modelem użytkownika Django, i mam inny model o nazwie Permission (niezwiązany z wewnętrzną koncepcją uprawnień Django), który ma klucz obcy do profilu. Tak: (I usunęliśmy większość pól tutaj, dla uproszczenia)Django REST Framework: SlugRelatedField dla pośrednio pokrewnego atrybutu?

from django.db import models 
from django.contrib.auth.models import User as DjangoUser 

class Account(models.Model): 
    name = models.CharField(max_length=200, db_index=True) 

class Profile(models.Model): 
    django_user = models.OneToOneField(DjangoUser) 
    default_account = models.ForeignKey(Account) 

class Permission(models.Model): 
    # Which user has the permission 
    user = models.ForeignKey(Profile, db_index=True) 
    # Which account they have the permission on 
    account = models.ForeignKey(Account, db_index=True) 

chcę zrobić serializatora o zgodę, że będą tworzyć obiekty, takie jak ten:

{ 
    "user": "[email protected]", 
    "account": 123 
} 

gdzie wartość "konta" jest kluczem podstawowym konta (więc łatwo, mogę użyć PrimaryKeyRelatedField), a wartość "użytkownika" to adres e-mail użytkownika (jest to część, której jeszcze nie znałem, ponieważ adres e-mail jest nie przechowywane bezpośrednio w obiekcie Profile, znajduje się w powiązanym obiekcie DjangoUser). Zauważ też, że nie jest to tylko do odczytu - podczas tworzenia uprawnienia musi być możliwa deserializacja z adresu e-mail do obiektu profilu.

Niektóre rzeczy próbowałem tak daleko, za reprezentowanie użytkownika na serializatora Permission ...

1.

user = serializers.RelatedField(read_only=False) 

Z tym jednym, jeśli POST adres e-mail (lub klucz podstawowy lub cokolwiek innego) jako "użytkownik", zwraca błąd 400, mówiąc: {"user": "This field is required."}, tak jakbym w ogóle nie uwzględniał pola.

2.

user = serializers.SlugRelatedField(slug_field='django_user.email') 

Z tym jednym, mam AttributeError: 'Profile' object has no attribute 'django_user.email'. To samo dzieje się, gdy używam 'django_user__email'.

Wszelkie pomysły?

Odpowiedz

0

Poświęciłem trochę czasu na napisanie kodu w celu lepszego zrozumienia Twojego pytania. Jeśli chcesz w pełni obsługiwać operacje CRUD na swoim PermissionsSerializer, musisz zagnieździć obiekt Profile, abyś mógł odczytać jego atrybuty. Oto serializery, które proponuję zastosować.

from django.contrib.auth.models import User 
from rest_framework import serializers 
from .models import Permission, Profile, Account 


class UserSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = User 
     fields = ('username', 'email',) 


class ProfileSerializer(serializers.ModelSerializer): 

    django_user = UserSerializer(many=False) 

    class Meta: 
     model = Profile 
     fields = ('django_user',) 


class PermissionSerializer(serializers.ModelSerializer): 

    user = ProfileSerializer(many=False) 

    class Meta: 
     model = Permission 
     fields = ('user', 'account') 

a wyjście jest:

{ 
     "user": { 
      "django_user": { 
       "username": "admin", 
       "email": "[email protected]" 
      } 
     }, 
     "account": 1 
    } 

Nadzieja to może pomóc, jeśli jest to podejście jest użyteczne i chcesz zrobić to napisać-możliwość obejrzenia (http://www.django-rest-framework.org/api-guide/relations/#nested-relationships).

2

Według Django REST ram odniesienia serializer (http://www.django-rest-framework.org/api-guide/fields/#core-arguments):

nazwa atrybutu, który zostanie użyty do wypełnienia pola. Może to być metoda, która przyjmuje tylko własny argument, taki jak URLField (source = 'get_absolute_url'), lub może wykorzystywać notację kropkowaną do przechodzenia przez atrybuty, takie jak EmailField (source = 'user.email').

Jeśli więc nie działa source='user.email', można spróbować utworzyć metodę (np.get_user_email), użyj go w polu source i zwróć ręcznie wiadomość e-mail użytkownika.

+0

Jak określono w pytaniu oryginalnym, pole NIE jest tylko do odczytu. Musi być w stanie deserializować, a nie tylko serializować. – Avril

+0

Użycie 'source' nie oznacza, że ​​jest tylko do odczytu. Co się dzieje, gdy próbujesz deserializować? –