2016-12-06 7 views
0

Ich bin dabei, einen Weg zu finden, eine willkürliche Beziehung zwischen zwei Modellen in Django/Rest Framework zu erstellen.Django Rest Framework Beliebige Beziehung Feld

eine Tabelle der Ansicht, dass mit einem Primärschlüssel vorhanden ist, dass die Maßnahmen zulässig durch einige Benutzer oder eine Gruppe anmeldet, würde die Tabelle wie folgt aussehen:

Auth: pk | user | action

Und pk ist ein automatisch generierter ganze Zahl.

Ich muss einen Serializer oder ein nicht verwaltetes Modell erstellen, der Beziehungsinformationen korrekt abruft, als hätte er einen Fremdschlüssel in dieser Tabelle.

Die allgemeine Idee ist, dass eine Route wie folgt aus:

/customauth/test/

Würden all die Dinge produzieren, dass der Benutzer zu tun berechtigt ist. Beachten Sie, dass das Erstellen eines benutzerdefinierten Attributs und das Auffüllen benutzerdefinierter Abfragesätze in der Ansicht das Problem nicht löst, da ich die JSON-API verwende, die speziell solche Beziehungen anzeigt, die Beziehungen als solche darstellen (also muss das Feld tatsächlich) ein RelatedField oder eine Unterklasse sein).

Grundsätzlich muss ich ein verwandtes Feld (entweder in Serialisierer oder Modelle), die sich wie eine vollständig benutzerdefinierte Datenmenge verhält. Ich stelle die Beziehung basierend auf dem Abfrage-Set zur Verfügung oder gebe manuell an, welche Felder 'verwandt' sind.

Hier ist eine Probe gewünschte Antwort:

{ 
    "data":{ 
     "type":"CustomUserAuthDetailView", 
     "id":"test", 
     "attributes":{ 
     "user":"test" 
     }, 
     "links":{ 
     "self":"http://127.0.0.1:8000/auth/test/" 
     } 
    }, 
    "relationships":{ 
     "auth":{ 
     "links":{ 
      "self":"/customauth/test/relationships/auth" 
     }, 
     "data":{ 
      "type":"auth", 
      "id":"1" 
     } 
     } 
    } 
} 

Die JSON API plugin für Django Rastrahmen macht diese Antwort für mich, die Beziehung (en) müssen jedoch bestehen, und da ich eine echte nicht verwenden können, Beziehung (die 'customauth' ist eine nicht verwaltete Tabelle und stellt tatsächlich etwas wie Active Directory dar, das ich nicht berühren kann und potenziell unbegrenzte unterschiedliche Werte haben könnte), und die Tabelle Auth selbst ist nicht eindeutig unter user (und kann nicht be), und diese Information muss von anderen Tabellen identisch verwendet werden, so dass ich content-type und ein GenericForeignKey System nicht verwenden kann. (Mit dem Inhaltstyp können Sie mehrere auswärtige Beziehungen haben, aber nicht pro Zeile, nur pro Spalte ... es sei denn, ich missverstehe es).

Ich habe das Gefühl, dass ich etwas verpassen muss, da ich nicht die einzige Person sein kann, die das erreichen will. Ich dachte darüber nach, meine eigene Unterklasse von RelatedField zu machen, hatte aber bisher kein Glück, und während ich diesen Weg ging, dachte ich, ich würde nachsehen, ob jemand, der viel mehr Erfahrung hat als ich wusste, etwas vermisse.

Vollbeispielanwendung:

models.py:

from django.db import models 


class Auth(models.Model): 

    actions = (("POST", "Create"), 
       ("GET", "Retrieve"), 
       ("PUT", "Update"), 
       ("DELETE", "Remove")) 

    user = models.CharField(max_length=24) 
    action = models.CharField(max_length=8, choices=actions) 


class CustomUserAuth(models.Model): 

    class Meta: 
     managed = False 

    user = models.CharField(max_length=24, primary_key=True) 

serializers.py:

from rest_framework_json_api import serializers 
from .models import Auth, CustomUserAuth 


class AuthSerializer(serializers.HyperlinkedModelSerializer): 

    class Meta: 
     model = Auth 
     read_only_fields = ('url',) 


class CustomUserAuthSerializer(serializers.HyperlinkedModelSerializer): 

    class Meta: 
     model = CustomUserAuth 
     fields = ('user', 'url') 

views.py:

from rest_framework import views 
from .models import CustomUserAuth 
from .serializers import CustomUserAuthSerializer 
from rest_framework.response import Response 


class CustomUserAuthDetailView(views.APIView): 

    @staticmethod 
    def get(request, pk, format=None): 
     auth = CustomUserAuth() 
     auth.user = pk 
     serialized = CustomUserAuthSerializer(
      auth, 
      context={"request": request} 
     ) 
     return Response(serialized.data) 

urls.py:

from django.conf.urls import url 
from django.contrib import admin 
from fake_relationship.views import CustomUserAuthDetailView 

urlpatterns = [ 
    url(r'^admin/', admin.site.urls), 
    url(r'^auth/(?P<pk>[\w-]+)/$', 
     CustomUserAuthDetailView.as_view(), 
     name='customuserauth-detail' 
    ) 
] 

settings.py:

""" 
Django settings for djtest project. 

Generated by 'django-admin startproject' using Django 1.10.4. 

For more information on this file, see 
https://docs.djangoproject.com/en/1.10/topics/settings/ 

For the full list of settings and their values, see 
https://docs.djangoproject.com/en/1.10/ref/settings/ 
""" 

import os 

# Build paths inside the project like this: os.path.join(BASE_DIR, ...) 
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 


# Quick-start development settings - unsuitable for production 
# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ 

# SECURITY WARNING: keep the secret key used in production secret! 
SECRET_KEY = '[email protected]&3)=$3v2wfq+hzg4fihrla+5()dnxdwka35^[email protected]!b17&' 

# SECURITY WARNING: don't run with debug turned on in production! 
DEBUG = True 

ALLOWED_HOSTS = [] 


# Application definition 

INSTALLED_APPS = [ 
    'django.contrib.admin', 
    'django.contrib.auth', 
    'django.contrib.contenttypes', 
    'django.contrib.sessions', 
    'django.contrib.messages', 
    'django.contrib.staticfiles', 
    'rest_framework', 
    'fake_relationship' 
] 

REST_FRAMEWORK = { 
    'PAGE_SIZE': 10, 
    'EXCEPTION_HANDLER': 'rest_framework_json_api.exceptions.exception_handler', 
    'DEFAULT_PAGINATION_CLASS': 
     'rest_framework_json_api.pagination.PageNumberPagination', 
    'DEFAULT_PARSER_CLASSES': (
     'rest_framework_json_api.parsers.JSONParser', 
     'rest_framework.parsers.FormParser', 
     'rest_framework.parsers.MultiPartParser' 
    ), 
    'DEFAULT_RENDERER_CLASSES': (
     'rest_framework_json_api.renderers.JSONRenderer', 
     'rest_framework.renderers.BrowsableAPIRenderer', 
    ), 
    'DEFAULT_METADATA_CLASS': 'rest_framework_json_api.metadata.JSONAPIMetadata', 
} 

MIDDLEWARE = [ 
    'django.middleware.security.SecurityMiddleware', 
    'django.contrib.sessions.middleware.SessionMiddleware', 
    'django.middleware.common.CommonMiddleware', 
    'django.middleware.csrf.CsrfViewMiddleware', 
    'django.contrib.auth.middleware.AuthenticationMiddleware', 
    'django.contrib.messages.middleware.MessageMiddleware', 
    'django.middleware.clickjacking.XFrameOptionsMiddleware', 
] 

ROOT_URLCONF = 'djtest.urls' 

TEMPLATES = [ 
    { 
     'BACKEND': 'django.template.backends.django.DjangoTemplates', 
     'DIRS': [], 
     'APP_DIRS': True, 
     'OPTIONS': { 
      'context_processors': [ 
       'django.template.context_processors.debug', 
       'django.template.context_processors.request', 
       'django.contrib.auth.context_processors.auth', 
       'django.contrib.messages.context_processors.messages', 
      ], 
     }, 
    }, 
] 

WSGI_APPLICATION = 'djtest.wsgi.application' 


# Database 
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases 

DATABASES = { 
    'default': { 
     'ENGINE': 'django.db.backends.sqlite3', 
     'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 
    } 
} 


# Password validation 
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators 

AUTH_PASSWORD_VALIDATORS = [ 
    { 
     'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 
    }, 
    { 
     'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 
    }, 
    { 
     'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 
    }, 
    { 
     'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 
    }, 
] 


# Internationalization 
# https://docs.djangoproject.com/en/1.10/topics/i18n/ 

LANGUAGE_CODE = 'en-us' 

TIME_ZONE = 'UTC' 

USE_I18N = True 

USE_L10N = True 

USE_TZ = True 


# Static files (CSS, JavaScript, Images) 
# https://docs.djangoproject.com/en/1.10/howto/static-files/ 

STATIC_URL = '/static/' 
+0

Können Sie den Fremdschlüssel in einer Beziehung verwenden? – marin

+0

Nein, die CustomUserAuth-Tabelle existiert nicht wirklich, also kann nichts einen Fremdschlüssel dazu haben, und der Primärschlüssel der Auth-Tabelle ist eine automatisch inkrementierende Ganzzahl - 'Benutzer' ist nicht eindeutig und kann nicht sein. Aus diesen Gründen sind keine Fremdschlüsselbeziehungen möglich. – Keozon

Antwort

0

Sie mit SerializerMethodField versuchen können, und kehren alles, was Sie von dort aus wollen, ist es im Grunde entwerfen für die Herstellung Betrieb vor Rückgabewert, aber Sie können zu Datenmodell und Abrufen von Daten

+0

Leider ist SerializerMethodField keine Unterklasse von RelatedField, daher wird es nicht als eine Beziehung in der Antwort gemeldet. – Keozon

Verwandte Themen