mirror of
				https://github.com/graphql-python/graphene-django.git
				synced 2025-11-04 09:57:53 +03:00 
			
		
		
		
	Update travis and tox (#667)
* Update travis and tox * Use xenial distribution * Don't install coveralls twice * Add black and flake8 tox commands * Remove Python 3.5 test for Django master * Fix indent * Ignore migrations * Remove black for now * Run black formatting (#668) * Run black format * Update makefile * Add black to travis build
This commit is contained in:
		
							parent
							
								
									44e9b0d0c5
								
							
						
					
					
						commit
						775d2e3523
					
				
							
								
								
									
										80
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										80
									
								
								.travis.yml
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -1,58 +1,58 @@
 | 
			
		|||
language: python
 | 
			
		||||
sudo: required
 | 
			
		||||
cache: pip
 | 
			
		||||
dist: xenial
 | 
			
		||||
 | 
			
		||||
python:
 | 
			
		||||
  - 2.7
 | 
			
		||||
  - 3.4
 | 
			
		||||
  - 3.5
 | 
			
		||||
  - 3.6
 | 
			
		||||
  - 3.7
 | 
			
		||||
 | 
			
		||||
env:
 | 
			
		||||
  matrix:
 | 
			
		||||
    - DJANGO=1.11
 | 
			
		||||
    - DJANGO=2.1
 | 
			
		||||
    - DJANGO=2.2
 | 
			
		||||
    - DJANGO=master
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
  - TOX_ENV=py${TRAVIS_PYTHON_VERSION}-django${DJANGO}
 | 
			
		||||
  - pip install tox
 | 
			
		||||
  - tox -e $TOX_ENV --notest
 | 
			
		||||
script:
 | 
			
		||||
  - tox -e $TOX_ENV
 | 
			
		||||
  - pip install tox tox-travis
 | 
			
		||||
 | 
			
		||||
after_success:
 | 
			
		||||
  - tox -e $TOX_ENV -- pip install coveralls 
 | 
			
		||||
  - tox -e $TOX_ENV -- coveralls $COVERALLS_OPTION
 | 
			
		||||
script: 
 | 
			
		||||
  - tox
 | 
			
		||||
 | 
			
		||||
after_success: 
 | 
			
		||||
  - pip install coveralls
 | 
			
		||||
  - coveralls
 | 
			
		||||
 | 
			
		||||
matrix:
 | 
			
		||||
  fast_finish: true
 | 
			
		||||
  include:
 | 
			
		||||
  - python: 3.5
 | 
			
		||||
    script: tox -e lint
 | 
			
		||||
  exclude:
 | 
			
		||||
    - python: 2.7
 | 
			
		||||
      env: DJANGO=2.1
 | 
			
		||||
    - python: 2.7
 | 
			
		||||
      env: DJANGO=2.2
 | 
			
		||||
    - python: 2.7
 | 
			
		||||
      env: DJANGO=master
 | 
			
		||||
    - python: 3.4
 | 
			
		||||
      env: DJANGO=2.1
 | 
			
		||||
    - python: 3.4
 | 
			
		||||
      env: DJANGO=2.2
 | 
			
		||||
    - python: 3.4
 | 
			
		||||
      env: DJANGO=master
 | 
			
		||||
      env: DJANGO=1.11
 | 
			
		||||
 | 
			
		||||
    - python: 3.5
 | 
			
		||||
      env: DJANGO=1.11
 | 
			
		||||
    - python: 3.5
 | 
			
		||||
      env: DJANGO=2.0
 | 
			
		||||
    - python: 3.5
 | 
			
		||||
      env: DJANGO=2.1
 | 
			
		||||
    - python: 3.5
 | 
			
		||||
      env: DJANGO=2.2
 | 
			
		||||
 | 
			
		||||
    - python: 3.6
 | 
			
		||||
      env: DJANGO=1.11
 | 
			
		||||
    - python: 3.6
 | 
			
		||||
      env: DJANGO=2.0
 | 
			
		||||
    - python: 3.6
 | 
			
		||||
      env: DJANGO=2.1
 | 
			
		||||
    - python: 3.6
 | 
			
		||||
      env: DJANGO=2.2
 | 
			
		||||
    - python: 3.6
 | 
			
		||||
      env: DJANGO=master
 | 
			
		||||
    - python: 3.7
 | 
			
		||||
      env: DJANGO=1.10
 | 
			
		||||
 | 
			
		||||
    - python: 3.7
 | 
			
		||||
      env: DJANGO=1.11
 | 
			
		||||
  allow_failures:
 | 
			
		||||
    - python: 3.7
 | 
			
		||||
      env: DJANGO=2.0
 | 
			
		||||
    - python: 3.7
 | 
			
		||||
      env: DJANGO=2.1
 | 
			
		||||
    - python: 3.7
 | 
			
		||||
      env: DJANGO=2.2
 | 
			
		||||
    - python: 3.7
 | 
			
		||||
      env: DJANGO=master
 | 
			
		||||
 | 
			
		||||
    - python: 3.7
 | 
			
		||||
      env: TOXENV=black,flake8
 | 
			
		||||
 | 
			
		||||
  allow_failures:
 | 
			
		||||
    - env: DJANGO=master
 | 
			
		||||
 | 
			
		||||
deploy:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -5,7 +5,7 @@ tests:
 | 
			
		|||
	py.test graphene_django --cov=graphene_django -vv
 | 
			
		||||
 | 
			
		||||
format:
 | 
			
		||||
	black graphene_django
 | 
			
		||||
	black --exclude "/migrations/" graphene_django examples
 | 
			
		||||
 | 
			
		||||
lint:
 | 
			
		||||
	flake8 graphene_django
 | 
			
		||||
	flake8 graphene_django examples
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,8 +5,8 @@ from cookbook.ingredients.models import Category, Ingredient
 | 
			
		|||
 | 
			
		||||
@admin.register(Ingredient)
 | 
			
		||||
class IngredientAdmin(admin.ModelAdmin):
 | 
			
		||||
    list_display = ('id', 'name', 'category')
 | 
			
		||||
    list_editable = ('name', 'category')
 | 
			
		||||
    list_display = ("id", "name", "category")
 | 
			
		||||
    list_editable = ("name", "category")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
admin.site.register(Category)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,6 @@ from django.apps import AppConfig
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class IngredientsConfig(AppConfig):
 | 
			
		||||
    name = 'cookbook.ingredients'
 | 
			
		||||
    label = 'ingredients'
 | 
			
		||||
    verbose_name = 'Ingredients'
 | 
			
		||||
    name = "cookbook.ingredients"
 | 
			
		||||
    label = "ingredients"
 | 
			
		||||
    verbose_name = "Ingredients"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,8 @@ from django.db import models
 | 
			
		|||
 | 
			
		||||
class Category(models.Model):
 | 
			
		||||
    class Meta:
 | 
			
		||||
        verbose_name_plural = 'Categories'
 | 
			
		||||
        verbose_name_plural = "Categories"
 | 
			
		||||
 | 
			
		||||
    name = models.CharField(max_length=100)
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +14,9 @@ class Category(models.Model):
 | 
			
		|||
class Ingredient(models.Model):
 | 
			
		||||
    name = models.CharField(max_length=100)
 | 
			
		||||
    notes = models.TextField(null=True, blank=True)
 | 
			
		||||
    category = models.ForeignKey(Category, related_name='ingredients', on_delete=models.CASCADE)
 | 
			
		||||
    category = models.ForeignKey(
 | 
			
		||||
        Category, related_name="ingredients", on_delete=models.CASCADE
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return self.name
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,14 +15,12 @@ class IngredientType(DjangoObjectType):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class Query(object):
 | 
			
		||||
    category = graphene.Field(CategoryType,
 | 
			
		||||
                              id=graphene.Int(),
 | 
			
		||||
                              name=graphene.String())
 | 
			
		||||
    category = graphene.Field(CategoryType, id=graphene.Int(), name=graphene.String())
 | 
			
		||||
    all_categories = graphene.List(CategoryType)
 | 
			
		||||
 | 
			
		||||
    ingredient = graphene.Field(IngredientType,
 | 
			
		||||
                                id=graphene.Int(),
 | 
			
		||||
                                name=graphene.String())
 | 
			
		||||
    ingredient = graphene.Field(
 | 
			
		||||
        IngredientType, id=graphene.Int(), name=graphene.String()
 | 
			
		||||
    )
 | 
			
		||||
    all_ingredients = graphene.List(IngredientType)
 | 
			
		||||
 | 
			
		||||
    def resolve_all_categories(self, context):
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +28,7 @@ class Query(object):
 | 
			
		|||
 | 
			
		||||
    def resolve_all_ingredients(self, context):
 | 
			
		||||
        # We can easily optimize query count in the resolve method
 | 
			
		||||
        return Ingredient.objects.select_related('category').all()
 | 
			
		||||
        return Ingredient.objects.select_related("category").all()
 | 
			
		||||
 | 
			
		||||
    def resolve_category(self, context, id=None, name=None):
 | 
			
		||||
        if id is not None:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1 @@
 | 
			
		|||
 | 
			
		||||
# Create your tests here.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1 @@
 | 
			
		|||
 | 
			
		||||
# Create your views here.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,6 @@ from django.apps import AppConfig
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class RecipesConfig(AppConfig):
 | 
			
		||||
    name = 'cookbook.recipes'
 | 
			
		||||
    label = 'recipes'
 | 
			
		||||
    verbose_name = 'Recipes'
 | 
			
		||||
    name = "cookbook.recipes"
 | 
			
		||||
    label = "recipes"
 | 
			
		||||
    verbose_name = "Recipes"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,17 +6,23 @@ from ..ingredients.models import Ingredient
 | 
			
		|||
class Recipe(models.Model):
 | 
			
		||||
    title = models.CharField(max_length=100)
 | 
			
		||||
    instructions = models.TextField()
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return self.title
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RecipeIngredient(models.Model):
 | 
			
		||||
    recipe = models.ForeignKey(Recipe, related_name='amounts', on_delete=models.CASCADE)
 | 
			
		||||
    ingredient = models.ForeignKey(Ingredient, related_name='used_by', on_delete=models.CASCADE)
 | 
			
		||||
    recipe = models.ForeignKey(Recipe, related_name="amounts", on_delete=models.CASCADE)
 | 
			
		||||
    ingredient = models.ForeignKey(
 | 
			
		||||
        Ingredient, related_name="used_by", on_delete=models.CASCADE
 | 
			
		||||
    )
 | 
			
		||||
    amount = models.FloatField()
 | 
			
		||||
    unit = models.CharField(max_length=20, choices=(
 | 
			
		||||
        ('unit', 'Units'),
 | 
			
		||||
        ('kg', 'Kilograms'),
 | 
			
		||||
        ('l', 'Litres'),
 | 
			
		||||
        ('st', 'Shots'),
 | 
			
		||||
    ))
 | 
			
		||||
    unit = models.CharField(
 | 
			
		||||
        max_length=20,
 | 
			
		||||
        choices=(
 | 
			
		||||
            ("unit", "Units"),
 | 
			
		||||
            ("kg", "Kilograms"),
 | 
			
		||||
            ("l", "Litres"),
 | 
			
		||||
            ("st", "Shots"),
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,13 +15,10 @@ class RecipeIngredientType(DjangoObjectType):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class Query(object):
 | 
			
		||||
    recipe = graphene.Field(RecipeType,
 | 
			
		||||
                            id=graphene.Int(),
 | 
			
		||||
                            title=graphene.String())
 | 
			
		||||
    recipe = graphene.Field(RecipeType, id=graphene.Int(), title=graphene.String())
 | 
			
		||||
    all_recipes = graphene.List(RecipeType)
 | 
			
		||||
 | 
			
		||||
    recipeingredient = graphene.Field(RecipeIngredientType,
 | 
			
		||||
                                      id=graphene.Int())
 | 
			
		||||
    recipeingredient = graphene.Field(RecipeIngredientType, id=graphene.Int())
 | 
			
		||||
    all_recipeingredients = graphene.List(RecipeIngredientType)
 | 
			
		||||
 | 
			
		||||
    def resolve_recipe(self, context, id=None, title=None):
 | 
			
		||||
| 
						 | 
				
			
			@ -43,5 +40,5 @@ class Query(object):
 | 
			
		|||
        return Recipe.objects.all()
 | 
			
		||||
 | 
			
		||||
    def resolve_all_recipeingredients(self, context):
 | 
			
		||||
        related = ['recipe', 'ingredient']
 | 
			
		||||
        related = ["recipe", "ingredient"]
 | 
			
		||||
        return RecipeIngredient.objects.select_related(*related).all()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1 @@
 | 
			
		|||
 | 
			
		||||
# Create your tests here.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1 @@
 | 
			
		|||
 | 
			
		||||
# Create your views here.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,10 +5,12 @@ import graphene
 | 
			
		|||
from graphene_django.debug import DjangoDebug
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Query(cookbook.ingredients.schema.Query,
 | 
			
		||||
            cookbook.recipes.schema.Query,
 | 
			
		||||
            graphene.ObjectType):
 | 
			
		||||
    debug = graphene.Field(DjangoDebug, name='_debug')
 | 
			
		||||
class Query(
 | 
			
		||||
    cookbook.ingredients.schema.Query,
 | 
			
		||||
    cookbook.recipes.schema.Query,
 | 
			
		||||
    graphene.ObjectType,
 | 
			
		||||
):
 | 
			
		||||
    debug = graphene.Field(DjangoDebug, name="_debug")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
schema = graphene.Schema(query=Query)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 | 
			
		|||
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
 | 
			
		||||
 | 
			
		||||
# SECURITY WARNING: keep the secret key used in production secret!
 | 
			
		||||
SECRET_KEY = '_$=$%eqxk$8ss4n7mtgarw^5$8^d5+c83!vwatr@i_81myb=e4'
 | 
			
		||||
SECRET_KEY = "_$=$%eqxk$8ss4n7mtgarw^5$8^d5+c83!vwatr@i_81myb=e4"
 | 
			
		||||
 | 
			
		||||
# SECURITY WARNING: don't run with debug turned on in production!
 | 
			
		||||
DEBUG = True
 | 
			
		||||
| 
						 | 
				
			
			@ -32,64 +32,61 @@ ALLOWED_HOSTS = []
 | 
			
		|||
# Application definition
 | 
			
		||||
 | 
			
		||||
INSTALLED_APPS = [
 | 
			
		||||
    'django.contrib.admin',
 | 
			
		||||
    'django.contrib.auth',
 | 
			
		||||
    'django.contrib.contenttypes',
 | 
			
		||||
    'django.contrib.sessions',
 | 
			
		||||
    'django.contrib.messages',
 | 
			
		||||
    'django.contrib.staticfiles',
 | 
			
		||||
    'graphene_django',
 | 
			
		||||
 | 
			
		||||
    'cookbook.ingredients.apps.IngredientsConfig',
 | 
			
		||||
    'cookbook.recipes.apps.RecipesConfig',
 | 
			
		||||
    "django.contrib.admin",
 | 
			
		||||
    "django.contrib.auth",
 | 
			
		||||
    "django.contrib.contenttypes",
 | 
			
		||||
    "django.contrib.sessions",
 | 
			
		||||
    "django.contrib.messages",
 | 
			
		||||
    "django.contrib.staticfiles",
 | 
			
		||||
    "graphene_django",
 | 
			
		||||
    "cookbook.ingredients.apps.IngredientsConfig",
 | 
			
		||||
    "cookbook.recipes.apps.RecipesConfig",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
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',
 | 
			
		||||
    "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",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
GRAPHENE = {
 | 
			
		||||
    'SCHEMA': 'cookbook.schema.schema',
 | 
			
		||||
    'SCHEMA_INDENT': 2,
 | 
			
		||||
    'MIDDLEWARE': (
 | 
			
		||||
        'graphene_django.debug.DjangoDebugMiddleware',
 | 
			
		||||
    )
 | 
			
		||||
    "SCHEMA": "cookbook.schema.schema",
 | 
			
		||||
    "SCHEMA_INDENT": 2,
 | 
			
		||||
    "MIDDLEWARE": ("graphene_django.debug.DjangoDebugMiddleware",),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ROOT_URLCONF = 'cookbook.urls'
 | 
			
		||||
ROOT_URLCONF = "cookbook.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',
 | 
			
		||||
            ],
 | 
			
		||||
        "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 = 'cookbook.wsgi.application'
 | 
			
		||||
WSGI_APPLICATION = "cookbook.wsgi.application"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Database
 | 
			
		||||
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases
 | 
			
		||||
 | 
			
		||||
DATABASES = {
 | 
			
		||||
    'default': {
 | 
			
		||||
        'ENGINE': 'django.db.backends.sqlite3',
 | 
			
		||||
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
 | 
			
		||||
    "default": {
 | 
			
		||||
        "ENGINE": "django.db.backends.sqlite3",
 | 
			
		||||
        "NAME": os.path.join(BASE_DIR, "db.sqlite3"),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -99,26 +96,20 @@ DATABASES = {
 | 
			
		|||
 | 
			
		||||
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',
 | 
			
		||||
        "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.9/topics/i18n/
 | 
			
		||||
 | 
			
		||||
LANGUAGE_CODE = 'en-us'
 | 
			
		||||
LANGUAGE_CODE = "en-us"
 | 
			
		||||
 | 
			
		||||
TIME_ZONE = 'UTC'
 | 
			
		||||
TIME_ZONE = "UTC"
 | 
			
		||||
 | 
			
		||||
USE_I18N = True
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -130,4 +121,4 @@ USE_TZ = True
 | 
			
		|||
# Static files (CSS, JavaScript, Images)
 | 
			
		||||
# https://docs.djangoproject.com/en/1.9/howto/static-files/
 | 
			
		||||
 | 
			
		||||
STATIC_URL = '/static/'
 | 
			
		||||
STATIC_URL = "/static/"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,6 @@ from graphene_django.views import GraphQLView
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    path('admin/', admin.site.urls),
 | 
			
		||||
    path('graphql/', GraphQLView.as_view(graphiql=True)),
 | 
			
		||||
    path("admin/", admin.site.urls),
 | 
			
		||||
    path("graphql/", GraphQLView.as_view(graphiql=True)),
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,8 +5,8 @@ from cookbook.ingredients.models import Category, Ingredient
 | 
			
		|||
 | 
			
		||||
@admin.register(Ingredient)
 | 
			
		||||
class IngredientAdmin(admin.ModelAdmin):
 | 
			
		||||
    list_display = ('id', 'name', 'category')
 | 
			
		||||
    list_editable = ('name', 'category')
 | 
			
		||||
    list_display = ("id", "name", "category")
 | 
			
		||||
    list_editable = ("name", "category")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
admin.site.register(Category)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,6 @@ from django.apps import AppConfig
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class IngredientsConfig(AppConfig):
 | 
			
		||||
    name = 'cookbook.ingredients'
 | 
			
		||||
    label = 'ingredients'
 | 
			
		||||
    verbose_name = 'Ingredients'
 | 
			
		||||
    name = "cookbook.ingredients"
 | 
			
		||||
    label = "ingredients"
 | 
			
		||||
    verbose_name = "Ingredients"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ class Category(models.Model):
 | 
			
		|||
class Ingredient(models.Model):
 | 
			
		||||
    name = models.CharField(max_length=100)
 | 
			
		||||
    notes = models.TextField(null=True, blank=True)
 | 
			
		||||
    category = models.ForeignKey(Category, related_name='ingredients')
 | 
			
		||||
    category = models.ForeignKey(Category, related_name="ingredients")
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return self.name
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,24 +7,22 @@ from graphene_django.types import DjangoObjectType
 | 
			
		|||
# Graphene will automatically map the Category model's fields onto the CategoryNode.
 | 
			
		||||
# This is configured in the CategoryNode's Meta class (as you can see below)
 | 
			
		||||
class CategoryNode(DjangoObjectType):
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Category
 | 
			
		||||
        interfaces = (Node, )
 | 
			
		||||
        filter_fields = ['name', 'ingredients']
 | 
			
		||||
        interfaces = (Node,)
 | 
			
		||||
        filter_fields = ["name", "ingredients"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IngredientNode(DjangoObjectType):
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Ingredient
 | 
			
		||||
        # Allow for some more advanced filtering here
 | 
			
		||||
        interfaces = (Node, )
 | 
			
		||||
        interfaces = (Node,)
 | 
			
		||||
        filter_fields = {
 | 
			
		||||
            'name': ['exact', 'icontains', 'istartswith'],
 | 
			
		||||
            'notes': ['exact', 'icontains'],
 | 
			
		||||
            'category': ['exact'],
 | 
			
		||||
            'category__name': ['exact'],
 | 
			
		||||
            "name": ["exact", "icontains", "istartswith"],
 | 
			
		||||
            "notes": ["exact", "icontains"],
 | 
			
		||||
            "category": ["exact"],
 | 
			
		||||
            "category__name": ["exact"],
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1 @@
 | 
			
		|||
 | 
			
		||||
# Create your tests here.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1 @@
 | 
			
		|||
 | 
			
		||||
# Create your views here.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,6 @@ from django.apps import AppConfig
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class RecipesConfig(AppConfig):
 | 
			
		||||
    name = 'cookbook.recipes'
 | 
			
		||||
    label = 'recipes'
 | 
			
		||||
    verbose_name = 'Recipes'
 | 
			
		||||
    name = "cookbook.recipes"
 | 
			
		||||
    label = "recipes"
 | 
			
		||||
    verbose_name = "Recipes"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,12 +10,15 @@ class Recipe(models.Model):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class RecipeIngredient(models.Model):
 | 
			
		||||
    recipe = models.ForeignKey(Recipe, related_name='amounts')
 | 
			
		||||
    ingredient = models.ForeignKey(Ingredient, related_name='used_by')
 | 
			
		||||
    recipe = models.ForeignKey(Recipe, related_name="amounts")
 | 
			
		||||
    ingredient = models.ForeignKey(Ingredient, related_name="used_by")
 | 
			
		||||
    amount = models.FloatField()
 | 
			
		||||
    unit = models.CharField(max_length=20, choices=(
 | 
			
		||||
        ('unit', 'Units'),
 | 
			
		||||
        ('kg', 'Kilograms'),
 | 
			
		||||
        ('l', 'Litres'),
 | 
			
		||||
        ('st', 'Shots'),
 | 
			
		||||
    ))
 | 
			
		||||
    unit = models.CharField(
 | 
			
		||||
        max_length=20,
 | 
			
		||||
        choices=(
 | 
			
		||||
            ("unit", "Units"),
 | 
			
		||||
            ("kg", "Kilograms"),
 | 
			
		||||
            ("l", "Litres"),
 | 
			
		||||
            ("st", "Shots"),
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,24 +3,23 @@ from graphene import Node
 | 
			
		|||
from graphene_django.filter import DjangoFilterConnectionField
 | 
			
		||||
from graphene_django.types import DjangoObjectType
 | 
			
		||||
 | 
			
		||||
class RecipeNode(DjangoObjectType):
 | 
			
		||||
 | 
			
		||||
class RecipeNode(DjangoObjectType):
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Recipe
 | 
			
		||||
        interfaces = (Node, )
 | 
			
		||||
        filter_fields = ['title','amounts']
 | 
			
		||||
        interfaces = (Node,)
 | 
			
		||||
        filter_fields = ["title", "amounts"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RecipeIngredientNode(DjangoObjectType):
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = RecipeIngredient
 | 
			
		||||
        # Allow for some more advanced filtering here
 | 
			
		||||
        interfaces = (Node, )
 | 
			
		||||
        interfaces = (Node,)
 | 
			
		||||
        filter_fields = {
 | 
			
		||||
            'ingredient__name': ['exact', 'icontains', 'istartswith'],
 | 
			
		||||
            'recipe': ['exact'],
 | 
			
		||||
            'recipe__title': ['icontains'],
 | 
			
		||||
            "ingredient__name": ["exact", "icontains", "istartswith"],
 | 
			
		||||
            "recipe": ["exact"],
 | 
			
		||||
            "recipe__title": ["icontains"],
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1 @@
 | 
			
		|||
 | 
			
		||||
# Create your tests here.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1 @@
 | 
			
		|||
 | 
			
		||||
# Create your views here.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,10 +5,12 @@ import graphene
 | 
			
		|||
from graphene_django.debug import DjangoDebug
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Query(cookbook.ingredients.schema.Query,
 | 
			
		||||
            cookbook.recipes.schema.Query,
 | 
			
		||||
            graphene.ObjectType):
 | 
			
		||||
    debug = graphene.Field(DjangoDebug, name='_debug')
 | 
			
		||||
class Query(
 | 
			
		||||
    cookbook.ingredients.schema.Query,
 | 
			
		||||
    cookbook.recipes.schema.Query,
 | 
			
		||||
    graphene.ObjectType,
 | 
			
		||||
):
 | 
			
		||||
    debug = graphene.Field(DjangoDebug, name="_debug")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
schema = graphene.Schema(query=Query)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 | 
			
		|||
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
 | 
			
		||||
 | 
			
		||||
# SECURITY WARNING: keep the secret key used in production secret!
 | 
			
		||||
SECRET_KEY = '_$=$%eqxk$8ss4n7mtgarw^5$8^d5+c83!vwatr@i_81myb=e4'
 | 
			
		||||
SECRET_KEY = "_$=$%eqxk$8ss4n7mtgarw^5$8^d5+c83!vwatr@i_81myb=e4"
 | 
			
		||||
 | 
			
		||||
# SECURITY WARNING: don't run with debug turned on in production!
 | 
			
		||||
DEBUG = True
 | 
			
		||||
| 
						 | 
				
			
			@ -32,65 +32,62 @@ ALLOWED_HOSTS = []
 | 
			
		|||
# Application definition
 | 
			
		||||
 | 
			
		||||
INSTALLED_APPS = [
 | 
			
		||||
    'django.contrib.admin',
 | 
			
		||||
    'django.contrib.auth',
 | 
			
		||||
    'django.contrib.contenttypes',
 | 
			
		||||
    'django.contrib.sessions',
 | 
			
		||||
    'django.contrib.messages',
 | 
			
		||||
    'django.contrib.staticfiles',
 | 
			
		||||
    'graphene_django',
 | 
			
		||||
 | 
			
		||||
    'cookbook.ingredients.apps.IngredientsConfig',
 | 
			
		||||
    'cookbook.recipes.apps.RecipesConfig',
 | 
			
		||||
    "django.contrib.admin",
 | 
			
		||||
    "django.contrib.auth",
 | 
			
		||||
    "django.contrib.contenttypes",
 | 
			
		||||
    "django.contrib.sessions",
 | 
			
		||||
    "django.contrib.messages",
 | 
			
		||||
    "django.contrib.staticfiles",
 | 
			
		||||
    "graphene_django",
 | 
			
		||||
    "cookbook.ingredients.apps.IngredientsConfig",
 | 
			
		||||
    "cookbook.recipes.apps.RecipesConfig",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
MIDDLEWARE_CLASSES = [
 | 
			
		||||
    'django.middleware.security.SecurityMiddleware',
 | 
			
		||||
    'django.contrib.sessions.middleware.SessionMiddleware',
 | 
			
		||||
    'django.middleware.common.CommonMiddleware',
 | 
			
		||||
    'django.middleware.csrf.CsrfViewMiddleware',
 | 
			
		||||
    'django.contrib.auth.middleware.AuthenticationMiddleware',
 | 
			
		||||
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 | 
			
		||||
    'django.contrib.messages.middleware.MessageMiddleware',
 | 
			
		||||
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
 | 
			
		||||
    "django.middleware.security.SecurityMiddleware",
 | 
			
		||||
    "django.contrib.sessions.middleware.SessionMiddleware",
 | 
			
		||||
    "django.middleware.common.CommonMiddleware",
 | 
			
		||||
    "django.middleware.csrf.CsrfViewMiddleware",
 | 
			
		||||
    "django.contrib.auth.middleware.AuthenticationMiddleware",
 | 
			
		||||
    "django.contrib.auth.middleware.SessionAuthenticationMiddleware",
 | 
			
		||||
    "django.contrib.messages.middleware.MessageMiddleware",
 | 
			
		||||
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
GRAPHENE = {
 | 
			
		||||
    'SCHEMA': 'cookbook.schema.schema',
 | 
			
		||||
    'SCHEMA_INDENT': 2,
 | 
			
		||||
    'MIDDLEWARE': (
 | 
			
		||||
        'graphene_django.debug.DjangoDebugMiddleware',
 | 
			
		||||
    )
 | 
			
		||||
    "SCHEMA": "cookbook.schema.schema",
 | 
			
		||||
    "SCHEMA_INDENT": 2,
 | 
			
		||||
    "MIDDLEWARE": ("graphene_django.debug.DjangoDebugMiddleware",),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ROOT_URLCONF = 'cookbook.urls'
 | 
			
		||||
ROOT_URLCONF = "cookbook.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',
 | 
			
		||||
            ],
 | 
			
		||||
        "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 = 'cookbook.wsgi.application'
 | 
			
		||||
WSGI_APPLICATION = "cookbook.wsgi.application"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Database
 | 
			
		||||
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases
 | 
			
		||||
 | 
			
		||||
DATABASES = {
 | 
			
		||||
    'default': {
 | 
			
		||||
        'ENGINE': 'django.db.backends.sqlite3',
 | 
			
		||||
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
 | 
			
		||||
    "default": {
 | 
			
		||||
        "ENGINE": "django.db.backends.sqlite3",
 | 
			
		||||
        "NAME": os.path.join(BASE_DIR, "db.sqlite3"),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -100,26 +97,20 @@ DATABASES = {
 | 
			
		|||
 | 
			
		||||
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',
 | 
			
		||||
        "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.9/topics/i18n/
 | 
			
		||||
 | 
			
		||||
LANGUAGE_CODE = 'en-us'
 | 
			
		||||
LANGUAGE_CODE = "en-us"
 | 
			
		||||
 | 
			
		||||
TIME_ZONE = 'UTC'
 | 
			
		||||
TIME_ZONE = "UTC"
 | 
			
		||||
 | 
			
		||||
USE_I18N = True
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -131,4 +122,4 @@ USE_TZ = True
 | 
			
		|||
# Static files (CSS, JavaScript, Images)
 | 
			
		||||
# https://docs.djangoproject.com/en/1.9/howto/static-files/
 | 
			
		||||
 | 
			
		||||
STATIC_URL = '/static/'
 | 
			
		||||
STATIC_URL = "/static/"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,6 @@ from graphene_django.views import GraphQLView
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    url(r'^admin/', admin.site.urls),
 | 
			
		||||
    url(r'^graphql$', GraphQLView.as_view(graphiql=True)),
 | 
			
		||||
    url(r"^admin/", admin.site.urls),
 | 
			
		||||
    url(r"^graphql$", GraphQLView.as_view(graphiql=True)),
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,97 +2,50 @@ from .models import Character, Faction, Ship
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
def initialize():
 | 
			
		||||
    human = Character(
 | 
			
		||||
        name='Human'
 | 
			
		||||
    )
 | 
			
		||||
    human = Character(name="Human")
 | 
			
		||||
    human.save()
 | 
			
		||||
 | 
			
		||||
    droid = Character(
 | 
			
		||||
        name='Droid'
 | 
			
		||||
    )
 | 
			
		||||
    droid = Character(name="Droid")
 | 
			
		||||
    droid.save()
 | 
			
		||||
 | 
			
		||||
    rebels = Faction(
 | 
			
		||||
        id='1',
 | 
			
		||||
        name='Alliance to Restore the Republic',
 | 
			
		||||
        hero=human
 | 
			
		||||
    )
 | 
			
		||||
    rebels = Faction(id="1", name="Alliance to Restore the Republic", hero=human)
 | 
			
		||||
    rebels.save()
 | 
			
		||||
 | 
			
		||||
    empire = Faction(
 | 
			
		||||
        id='2',
 | 
			
		||||
        name='Galactic Empire',
 | 
			
		||||
        hero=droid
 | 
			
		||||
    )
 | 
			
		||||
    empire = Faction(id="2", name="Galactic Empire", hero=droid)
 | 
			
		||||
    empire.save()
 | 
			
		||||
 | 
			
		||||
    xwing = Ship(
 | 
			
		||||
        id='1',
 | 
			
		||||
        name='X-Wing',
 | 
			
		||||
        faction=rebels,
 | 
			
		||||
    )
 | 
			
		||||
    xwing = Ship(id="1", name="X-Wing", faction=rebels)
 | 
			
		||||
    xwing.save()
 | 
			
		||||
 | 
			
		||||
    human.ship = xwing
 | 
			
		||||
    human.save()
 | 
			
		||||
 | 
			
		||||
    ywing = Ship(
 | 
			
		||||
        id='2',
 | 
			
		||||
        name='Y-Wing',
 | 
			
		||||
        faction=rebels,
 | 
			
		||||
    )
 | 
			
		||||
    ywing = Ship(id="2", name="Y-Wing", faction=rebels)
 | 
			
		||||
    ywing.save()
 | 
			
		||||
 | 
			
		||||
    awing = Ship(
 | 
			
		||||
        id='3',
 | 
			
		||||
        name='A-Wing',
 | 
			
		||||
        faction=rebels,
 | 
			
		||||
    )
 | 
			
		||||
    awing = Ship(id="3", name="A-Wing", faction=rebels)
 | 
			
		||||
    awing.save()
 | 
			
		||||
 | 
			
		||||
    # Yeah, technically it's Corellian. But it flew in the service of the rebels,
 | 
			
		||||
    # so for the purposes of this demo it's a rebel ship.
 | 
			
		||||
    falcon = Ship(
 | 
			
		||||
        id='4',
 | 
			
		||||
        name='Millenium Falcon',
 | 
			
		||||
        faction=rebels,
 | 
			
		||||
    )
 | 
			
		||||
    falcon = Ship(id="4", name="Millenium Falcon", faction=rebels)
 | 
			
		||||
    falcon.save()
 | 
			
		||||
 | 
			
		||||
    homeOne = Ship(
 | 
			
		||||
        id='5',
 | 
			
		||||
        name='Home One',
 | 
			
		||||
        faction=rebels,
 | 
			
		||||
    )
 | 
			
		||||
    homeOne = Ship(id="5", name="Home One", faction=rebels)
 | 
			
		||||
    homeOne.save()
 | 
			
		||||
 | 
			
		||||
    tieFighter = Ship(
 | 
			
		||||
        id='6',
 | 
			
		||||
        name='TIE Fighter',
 | 
			
		||||
        faction=empire,
 | 
			
		||||
    )
 | 
			
		||||
    tieFighter = Ship(id="6", name="TIE Fighter", faction=empire)
 | 
			
		||||
    tieFighter.save()
 | 
			
		||||
 | 
			
		||||
    tieInterceptor = Ship(
 | 
			
		||||
        id='7',
 | 
			
		||||
        name='TIE Interceptor',
 | 
			
		||||
        faction=empire,
 | 
			
		||||
    )
 | 
			
		||||
    tieInterceptor = Ship(id="7", name="TIE Interceptor", faction=empire)
 | 
			
		||||
    tieInterceptor.save()
 | 
			
		||||
 | 
			
		||||
    executor = Ship(
 | 
			
		||||
        id='8',
 | 
			
		||||
        name='Executor',
 | 
			
		||||
        faction=empire,
 | 
			
		||||
    )
 | 
			
		||||
    executor = Ship(id="8", name="Executor", faction=empire)
 | 
			
		||||
    executor.save()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def create_ship(ship_name, faction_id):
 | 
			
		||||
    new_ship = Ship(
 | 
			
		||||
        name=ship_name,
 | 
			
		||||
        faction_id=faction_id
 | 
			
		||||
    )
 | 
			
		||||
    new_ship = Ship(name=ship_name, faction_id=faction_id)
 | 
			
		||||
    new_ship.save()
 | 
			
		||||
    return new_ship
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,13 @@ from django.db import models
 | 
			
		|||
 | 
			
		||||
class Character(models.Model):
 | 
			
		||||
    name = models.CharField(max_length=50)
 | 
			
		||||
    ship = models.ForeignKey('Ship', on_delete=models.CASCADE, blank=True, null=True, related_name='characters')
 | 
			
		||||
    ship = models.ForeignKey(
 | 
			
		||||
        "Ship",
 | 
			
		||||
        on_delete=models.CASCADE,
 | 
			
		||||
        blank=True,
 | 
			
		||||
        null=True,
 | 
			
		||||
        related_name="characters",
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return self.name
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +27,7 @@ class Faction(models.Model):
 | 
			
		|||
 | 
			
		||||
class Ship(models.Model):
 | 
			
		||||
    name = models.CharField(max_length=50)
 | 
			
		||||
    faction = models.ForeignKey(Faction, on_delete=models.CASCADE, related_name='ships')
 | 
			
		||||
    faction = models.ForeignKey(Faction, on_delete=models.CASCADE, related_name="ships")
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return self.name
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,18 +2,16 @@ import graphene
 | 
			
		|||
from graphene import Schema, relay, resolve_only_args
 | 
			
		||||
from graphene_django import DjangoConnectionField, DjangoObjectType
 | 
			
		||||
 | 
			
		||||
from .data import (create_ship, get_empire, get_faction, get_rebels, get_ship,
 | 
			
		||||
                   get_ships)
 | 
			
		||||
from .data import create_ship, get_empire, get_faction, get_rebels, get_ship, get_ships
 | 
			
		||||
from .models import Character as CharacterModel
 | 
			
		||||
from .models import Faction as FactionModel
 | 
			
		||||
from .models import Ship as ShipModel
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Ship(DjangoObjectType):
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = ShipModel
 | 
			
		||||
        interfaces = (relay.Node, )
 | 
			
		||||
        interfaces = (relay.Node,)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_node(cls, info, id):
 | 
			
		||||
| 
						 | 
				
			
			@ -22,16 +20,14 @@ class Ship(DjangoObjectType):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class Character(DjangoObjectType):
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = CharacterModel
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Faction(DjangoObjectType):
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = FactionModel
 | 
			
		||||
        interfaces = (relay.Node, )
 | 
			
		||||
        interfaces = (relay.Node,)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_node(cls, info, id):
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +35,6 @@ class Faction(DjangoObjectType):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class IntroduceShip(relay.ClientIDMutation):
 | 
			
		||||
 | 
			
		||||
    class Input:
 | 
			
		||||
        ship_name = graphene.String(required=True)
 | 
			
		||||
        faction_id = graphene.String(required=True)
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +43,9 @@ class IntroduceShip(relay.ClientIDMutation):
 | 
			
		|||
    faction = graphene.Field(Faction)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def mutate_and_get_payload(cls, root, info, ship_name, faction_id, client_mutation_id=None):
 | 
			
		||||
    def mutate_and_get_payload(
 | 
			
		||||
        cls, root, info, ship_name, faction_id, client_mutation_id=None
 | 
			
		||||
    ):
 | 
			
		||||
        ship = create_ship(ship_name, faction_id)
 | 
			
		||||
        faction = get_faction(faction_id)
 | 
			
		||||
        return IntroduceShip(ship=ship, faction=faction)
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +55,7 @@ class Query(graphene.ObjectType):
 | 
			
		|||
    rebels = graphene.Field(Faction)
 | 
			
		||||
    empire = graphene.Field(Faction)
 | 
			
		||||
    node = relay.Node.Field()
 | 
			
		||||
    ships = DjangoConnectionField(Ship, description='All the ships.')
 | 
			
		||||
    ships = DjangoConnectionField(Ship, description="All the ships.")
 | 
			
		||||
 | 
			
		||||
    @resolve_only_args
 | 
			
		||||
    def resolve_ships(self):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ pytestmark = pytest.mark.django_db
 | 
			
		|||
 | 
			
		||||
def test_correct_fetch_first_ship_rebels():
 | 
			
		||||
    initialize()
 | 
			
		||||
    query = '''
 | 
			
		||||
    query = """
 | 
			
		||||
    query RebelsShipsQuery {
 | 
			
		||||
      rebels {
 | 
			
		||||
        name,
 | 
			
		||||
| 
						 | 
				
			
			@ -24,22 +24,12 @@ def test_correct_fetch_first_ship_rebels():
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    '''
 | 
			
		||||
    """
 | 
			
		||||
    expected = {
 | 
			
		||||
        'rebels': {
 | 
			
		||||
            'name': 'Alliance to Restore the Republic',
 | 
			
		||||
            'hero': {
 | 
			
		||||
                'name': 'Human'
 | 
			
		||||
            },
 | 
			
		||||
            'ships': {
 | 
			
		||||
                'edges': [
 | 
			
		||||
                    {
 | 
			
		||||
                        'node': {
 | 
			
		||||
                            'name': 'X-Wing'
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                ]
 | 
			
		||||
            }
 | 
			
		||||
        "rebels": {
 | 
			
		||||
            "name": "Alliance to Restore the Republic",
 | 
			
		||||
            "hero": {"name": "Human"},
 | 
			
		||||
            "ships": {"edges": [{"node": {"name": "X-Wing"}}]},
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    result = schema.execute(query)
 | 
			
		||||
| 
						 | 
				
			
			@ -49,7 +39,7 @@ def test_correct_fetch_first_ship_rebels():
 | 
			
		|||
 | 
			
		||||
def test_correct_list_characters():
 | 
			
		||||
    initialize()
 | 
			
		||||
    query = '''
 | 
			
		||||
    query = """
 | 
			
		||||
    query RebelsShipsQuery {
 | 
			
		||||
      node(id: "U2hpcDox") {
 | 
			
		||||
        ... on Ship {
 | 
			
		||||
| 
						 | 
				
			
			@ -60,15 +50,8 @@ def test_correct_list_characters():
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    '''
 | 
			
		||||
    expected = {
 | 
			
		||||
        'node': {
 | 
			
		||||
            'name': 'X-Wing',
 | 
			
		||||
            'characters': [{
 | 
			
		||||
                'name': 'Human'
 | 
			
		||||
            }],
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    """
 | 
			
		||||
    expected = {"node": {"name": "X-Wing", "characters": [{"name": "Human"}]}}
 | 
			
		||||
    result = schema.execute(query)
 | 
			
		||||
    assert not result.errors
 | 
			
		||||
    assert result.data == expected
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,7 @@ pytestmark = pytest.mark.django_db
 | 
			
		|||
def test_mutations():
 | 
			
		||||
    initialize()
 | 
			
		||||
 | 
			
		||||
    query = '''
 | 
			
		||||
    query = """
 | 
			
		||||
    mutation MyMutation {
 | 
			
		||||
      introduceShip(input:{clientMutationId:"abc", shipName: "Peter", factionId: "1"}) {
 | 
			
		||||
        ship {
 | 
			
		||||
| 
						 | 
				
			
			@ -29,49 +29,23 @@ def test_mutations():
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    '''
 | 
			
		||||
    """
 | 
			
		||||
    expected = {
 | 
			
		||||
        'introduceShip': {
 | 
			
		||||
            'ship': {
 | 
			
		||||
                'id': 'U2hpcDo5',
 | 
			
		||||
                'name': 'Peter'
 | 
			
		||||
            },
 | 
			
		||||
            'faction': {
 | 
			
		||||
                'name': 'Alliance to Restore the Republic',
 | 
			
		||||
                'ships': {
 | 
			
		||||
                    'edges': [{
 | 
			
		||||
                        'node': {
 | 
			
		||||
                            'id': 'U2hpcDox',
 | 
			
		||||
                            'name': 'X-Wing'
 | 
			
		||||
                        }
 | 
			
		||||
                    }, {
 | 
			
		||||
                        'node': {
 | 
			
		||||
                            'id': 'U2hpcDoy',
 | 
			
		||||
                            'name': 'Y-Wing'
 | 
			
		||||
                        }
 | 
			
		||||
                    }, {
 | 
			
		||||
                        'node': {
 | 
			
		||||
                            'id': 'U2hpcDoz',
 | 
			
		||||
                            'name': 'A-Wing'
 | 
			
		||||
                        }
 | 
			
		||||
                    }, {
 | 
			
		||||
                        'node': {
 | 
			
		||||
                            'id': 'U2hpcDo0',
 | 
			
		||||
                            'name': 'Millenium Falcon'
 | 
			
		||||
                        }
 | 
			
		||||
                    }, {
 | 
			
		||||
                        'node': {
 | 
			
		||||
                            'id': 'U2hpcDo1',
 | 
			
		||||
                            'name': 'Home One'
 | 
			
		||||
                        }
 | 
			
		||||
                    }, {
 | 
			
		||||
                        'node': {
 | 
			
		||||
                            'id': 'U2hpcDo5',
 | 
			
		||||
                            'name': 'Peter'
 | 
			
		||||
                        }
 | 
			
		||||
                    }]
 | 
			
		||||
        "introduceShip": {
 | 
			
		||||
            "ship": {"id": "U2hpcDo5", "name": "Peter"},
 | 
			
		||||
            "faction": {
 | 
			
		||||
                "name": "Alliance to Restore the Republic",
 | 
			
		||||
                "ships": {
 | 
			
		||||
                    "edges": [
 | 
			
		||||
                        {"node": {"id": "U2hpcDox", "name": "X-Wing"}},
 | 
			
		||||
                        {"node": {"id": "U2hpcDoy", "name": "Y-Wing"}},
 | 
			
		||||
                        {"node": {"id": "U2hpcDoz", "name": "A-Wing"}},
 | 
			
		||||
                        {"node": {"id": "U2hpcDo0", "name": "Millenium Falcon"}},
 | 
			
		||||
                        {"node": {"id": "U2hpcDo1", "name": "Home One"}},
 | 
			
		||||
                        {"node": {"id": "U2hpcDo5", "name": "Peter"}},
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
            }
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    result = schema.execute(query)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,19 +8,16 @@ pytestmark = pytest.mark.django_db
 | 
			
		|||
 | 
			
		||||
def test_correctly_fetches_id_name_rebels():
 | 
			
		||||
    initialize()
 | 
			
		||||
    query = '''
 | 
			
		||||
    query = """
 | 
			
		||||
      query RebelsQuery {
 | 
			
		||||
        rebels {
 | 
			
		||||
          id
 | 
			
		||||
          name
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    '''
 | 
			
		||||
    """
 | 
			
		||||
    expected = {
 | 
			
		||||
        'rebels': {
 | 
			
		||||
            'id': 'RmFjdGlvbjox',
 | 
			
		||||
            'name': 'Alliance to Restore the Republic'
 | 
			
		||||
        }
 | 
			
		||||
        "rebels": {"id": "RmFjdGlvbjox", "name": "Alliance to Restore the Republic"}
 | 
			
		||||
    }
 | 
			
		||||
    result = schema.execute(query)
 | 
			
		||||
    assert not result.errors
 | 
			
		||||
| 
						 | 
				
			
			@ -29,7 +26,7 @@ def test_correctly_fetches_id_name_rebels():
 | 
			
		|||
 | 
			
		||||
def test_correctly_refetches_rebels():
 | 
			
		||||
    initialize()
 | 
			
		||||
    query = '''
 | 
			
		||||
    query = """
 | 
			
		||||
      query RebelsRefetchQuery {
 | 
			
		||||
        node(id: "RmFjdGlvbjox") {
 | 
			
		||||
          id
 | 
			
		||||
| 
						 | 
				
			
			@ -38,12 +35,9 @@ def test_correctly_refetches_rebels():
 | 
			
		|||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    '''
 | 
			
		||||
    """
 | 
			
		||||
    expected = {
 | 
			
		||||
        'node': {
 | 
			
		||||
            'id': 'RmFjdGlvbjox',
 | 
			
		||||
            'name': 'Alliance to Restore the Republic'
 | 
			
		||||
        }
 | 
			
		||||
        "node": {"id": "RmFjdGlvbjox", "name": "Alliance to Restore the Republic"}
 | 
			
		||||
    }
 | 
			
		||||
    result = schema.execute(query)
 | 
			
		||||
    assert not result.errors
 | 
			
		||||
| 
						 | 
				
			
			@ -52,20 +46,15 @@ def test_correctly_refetches_rebels():
 | 
			
		|||
 | 
			
		||||
def test_correctly_fetches_id_name_empire():
 | 
			
		||||
    initialize()
 | 
			
		||||
    query = '''
 | 
			
		||||
    query = """
 | 
			
		||||
      query EmpireQuery {
 | 
			
		||||
        empire {
 | 
			
		||||
          id
 | 
			
		||||
          name
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    '''
 | 
			
		||||
    expected = {
 | 
			
		||||
        'empire': {
 | 
			
		||||
            'id': 'RmFjdGlvbjoy',
 | 
			
		||||
            'name': 'Galactic Empire'
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    """
 | 
			
		||||
    expected = {"empire": {"id": "RmFjdGlvbjoy", "name": "Galactic Empire"}}
 | 
			
		||||
    result = schema.execute(query)
 | 
			
		||||
    assert not result.errors
 | 
			
		||||
    assert result.data == expected
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +62,7 @@ def test_correctly_fetches_id_name_empire():
 | 
			
		|||
 | 
			
		||||
def test_correctly_refetches_empire():
 | 
			
		||||
    initialize()
 | 
			
		||||
    query = '''
 | 
			
		||||
    query = """
 | 
			
		||||
      query EmpireRefetchQuery {
 | 
			
		||||
        node(id: "RmFjdGlvbjoy") {
 | 
			
		||||
          id
 | 
			
		||||
| 
						 | 
				
			
			@ -82,13 +71,8 @@ def test_correctly_refetches_empire():
 | 
			
		|||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    '''
 | 
			
		||||
    expected = {
 | 
			
		||||
        'node': {
 | 
			
		||||
            'id': 'RmFjdGlvbjoy',
 | 
			
		||||
            'name': 'Galactic Empire'
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    """
 | 
			
		||||
    expected = {"node": {"id": "RmFjdGlvbjoy", "name": "Galactic Empire"}}
 | 
			
		||||
    result = schema.execute(query)
 | 
			
		||||
    assert not result.errors
 | 
			
		||||
    assert result.data == expected
 | 
			
		||||
| 
						 | 
				
			
			@ -96,7 +80,7 @@ def test_correctly_refetches_empire():
 | 
			
		|||
 | 
			
		||||
def test_correctly_refetches_xwing():
 | 
			
		||||
    initialize()
 | 
			
		||||
    query = '''
 | 
			
		||||
    query = """
 | 
			
		||||
      query XWingRefetchQuery {
 | 
			
		||||
        node(id: "U2hpcDox") {
 | 
			
		||||
          id
 | 
			
		||||
| 
						 | 
				
			
			@ -105,13 +89,8 @@ def test_correctly_refetches_xwing():
 | 
			
		|||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    '''
 | 
			
		||||
    expected = {
 | 
			
		||||
        'node': {
 | 
			
		||||
            'id': 'U2hpcDox',
 | 
			
		||||
            'name': 'X-Wing'
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    """
 | 
			
		||||
    expected = {"node": {"id": "U2hpcDox", "name": "X-Wing"}}
 | 
			
		||||
    result = schema.execute(query)
 | 
			
		||||
    assert not result.errors
 | 
			
		||||
    assert result.data == expected
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -177,7 +177,11 @@ def convert_field_to_list_or_connection(field, registry=None):
 | 
			
		|||
        if not _type:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        description = field.help_text if isinstance(field, models.ManyToManyField) else field.field.help_text
 | 
			
		||||
        description = (
 | 
			
		||||
            field.help_text
 | 
			
		||||
            if isinstance(field, models.ManyToManyField)
 | 
			
		||||
            else field.field.help_text
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        # If there is a connection, we should transform the field
 | 
			
		||||
        # into a DjangoConnectionField
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,10 +41,9 @@ class DjangoFilterConnectionField(DjangoConnectionField):
 | 
			
		|||
                meta.update(self._extra_filter_meta)
 | 
			
		||||
 | 
			
		||||
            filterset_class = self._provided_filterset_class or (
 | 
			
		||||
                self.node_type._meta.filterset_class)
 | 
			
		||||
            self._filterset_class = get_filterset_class(
 | 
			
		||||
                filterset_class, **meta
 | 
			
		||||
                self.node_type._meta.filterset_class
 | 
			
		||||
            )
 | 
			
		||||
            self._filterset_class = get_filterset_class(filterset_class, **meta)
 | 
			
		||||
 | 
			
		||||
        return self._filterset_class
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -229,6 +229,7 @@ def test_filter_filterset_information_on_meta_related():
 | 
			
		|||
 | 
			
		||||
def test_filter_filterset_class_filter_fields_exception():
 | 
			
		||||
    with pytest.raises(Exception):
 | 
			
		||||
 | 
			
		||||
        class ReporterFilter(FilterSet):
 | 
			
		||||
            class Meta:
 | 
			
		||||
                model = Reporter
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -104,7 +104,9 @@ def test_write_only_field():
 | 
			
		|||
    )
 | 
			
		||||
 | 
			
		||||
    assert hasattr(result, "cool_name")
 | 
			
		||||
    assert not hasattr(result, "password"), "'password' is write_only field and shouldn't be visible"
 | 
			
		||||
    assert not hasattr(
 | 
			
		||||
        result, "password"
 | 
			
		||||
    ), "'password' is write_only field and shouldn't be visible"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@mark.django_db
 | 
			
		||||
| 
						 | 
				
			
			@ -124,7 +126,9 @@ def test_write_only_field_using_extra_kwargs():
 | 
			
		|||
    )
 | 
			
		||||
 | 
			
		||||
    assert hasattr(result, "cool_name")
 | 
			
		||||
    assert not hasattr(result, "password"), "'password' is write_only field and shouldn't be visible"
 | 
			
		||||
    assert not hasattr(
 | 
			
		||||
        result, "password"
 | 
			
		||||
    ), "'password' is write_only field and shouldn't be visible"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_nested_model():
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1015,13 +1015,13 @@ def test_proxy_model_support():
 | 
			
		|||
            "edges": [
 | 
			
		||||
                {"node": {"id": to_global_id("CNNReporterType", cnn_reporter.id)}}
 | 
			
		||||
            ]
 | 
			
		||||
        }
 | 
			
		||||
        },
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    result = schema.execute(query)
 | 
			
		||||
    assert not result.errors
 | 
			
		||||
    assert result.data == expected
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_should_resolve_get_queryset_connectionfields():
 | 
			
		||||
    reporter_1 = Reporter.objects.create(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,10 +82,12 @@ class DjangoObjectType(ObjectType):
 | 
			
		|||
            raise Exception("Can't set both filter_fields and filterset_class")
 | 
			
		||||
 | 
			
		||||
        if not DJANGO_FILTER_INSTALLED and (filter_fields or filterset_class):
 | 
			
		||||
            raise Exception((
 | 
			
		||||
                "Can only set filter_fields or filterset_class if "
 | 
			
		||||
                "Django-Filter is installed"
 | 
			
		||||
            ))
 | 
			
		||||
            raise Exception(
 | 
			
		||||
                (
 | 
			
		||||
                    "Can only set filter_fields or filterset_class if "
 | 
			
		||||
                    "Django-Filter is installed"
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        django_fields = yank_fields_from_attrs(
 | 
			
		||||
            construct_fields(model, registry, only_fields, exclude_fields), _as=Field
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										46
									
								
								tox.ini
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								tox.ini
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -1,31 +1,39 @@
 | 
			
		|||
[tox]
 | 
			
		||||
envlist = py{2.7,3.4,3.5,3.6,3.7,pypy,pypy3}-django{1.10,1.11,2.0,2.1,2.2,master},lint
 | 
			
		||||
envlist =
 | 
			
		||||
    py{27,35,36,37}-django{111,20,21,22,master},
 | 
			
		||||
    black,flake8
 | 
			
		||||
 | 
			
		||||
[travis:env]
 | 
			
		||||
DJANGO =
 | 
			
		||||
    1.11: django111
 | 
			
		||||
    2.0: django20
 | 
			
		||||
    2.1: django21
 | 
			
		||||
    2.2: django22
 | 
			
		||||
    master: djangomaster
 | 
			
		||||
 | 
			
		||||
[testenv]
 | 
			
		||||
passenv = *
 | 
			
		||||
usedevelop = True
 | 
			
		||||
setenv = 
 | 
			
		||||
setenv =
 | 
			
		||||
    DJANGO_SETTINGS_MODULE=django_test_settings
 | 
			
		||||
basepython =
 | 
			
		||||
    py2.7: python2.7
 | 
			
		||||
    py3.4: python3.4
 | 
			
		||||
    py3.5: python3.5
 | 
			
		||||
    py3.6: python3.6
 | 
			
		||||
    py3.7: python3.7
 | 
			
		||||
    pypypy: pypy
 | 
			
		||||
    pypypy3: pypy3
 | 
			
		||||
deps =
 | 
			
		||||
    -e.[test]
 | 
			
		||||
    psycopg2
 | 
			
		||||
    django1.10: Django>=1.10,<1.11
 | 
			
		||||
    django1.11: Django>=1.11,<1.12
 | 
			
		||||
    django2.0: Django>=2.0
 | 
			
		||||
    django2.1: Django>=2.1
 | 
			
		||||
    django111: Django>=1.11,<2.0
 | 
			
		||||
    django20: Django>=2.0,<2.1
 | 
			
		||||
    django21: Django>=2.1,<2.2
 | 
			
		||||
    django22: Django>=2.2,<3.0
 | 
			
		||||
    djangomaster: https://github.com/django/django/archive/master.zip
 | 
			
		||||
commands = {posargs:py.test --cov=graphene_django graphene_django examples}
 | 
			
		||||
 | 
			
		||||
[testenv:lint]
 | 
			
		||||
basepython = python
 | 
			
		||||
deps =
 | 
			
		||||
    prospector
 | 
			
		||||
commands = prospector graphene_django -0
 | 
			
		||||
[testenv:black]
 | 
			
		||||
basepython = python3.7
 | 
			
		||||
deps = black
 | 
			
		||||
commands  =
 | 
			
		||||
    black --exclude "/migrations/" graphene_django examples --check
 | 
			
		||||
 | 
			
		||||
[testenv:flake8]
 | 
			
		||||
basepython = python3.7
 | 
			
		||||
deps = flake8
 | 
			
		||||
commands =
 | 
			
		||||
    flake8 graphene_django examples
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user