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/'
Können Sie den Fremdschlüssel in einer Beziehung verwenden? – marin
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