mirror of
				https://github.com/graphql-python/graphene-django.git
				synced 2025-11-04 09:57:53 +03:00 
			
		
		
		
	Format with pre-commit
dedent docs/schema.py to allow formatting
This commit is contained in:
		
							parent
							
								
									9b44082dc4
								
							
						
					
					
						commit
						81787d9cdd
					
				
							
								
								
									
										6
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -27,8 +27,8 @@ a github repo, https://repl.it or similar (you can use this template as a starti
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
* **Please tell us about your environment:**
 | 
			
		||||
  
 | 
			
		||||
  - Version: 
 | 
			
		||||
  - Platform: 
 | 
			
		||||
 | 
			
		||||
  - Version:
 | 
			
		||||
  - Platform:
 | 
			
		||||
 | 
			
		||||
* **Other information** (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,4 +59,4 @@ Then to produce a HTML version of the documentation:
 | 
			
		|||
 | 
			
		||||
```sh
 | 
			
		||||
make html
 | 
			
		||||
```
 | 
			
		||||
```
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,4 +3,4 @@ recursive-include graphene_django/templates *
 | 
			
		|||
recursive-include graphene_django/static *
 | 
			
		||||
 | 
			
		||||
include examples/cookbook/cookbook/ingredients/fixtures/ingredients.json
 | 
			
		||||
include examples/cookbook-plain/cookbook/ingredients/fixtures/ingredients.json
 | 
			
		||||
include examples/cookbook-plain/cookbook/ingredients/fixtures/ingredients.json
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,60 +1,57 @@
 | 
			
		|||
  import graphene
 | 
			
		||||
import graphene
 | 
			
		||||
 | 
			
		||||
  from graphene_django.types import DjangoObjectType
 | 
			
		||||
from graphene_django.types import DjangoObjectType
 | 
			
		||||
 | 
			
		||||
  from cookbook.ingredients.models import Category, Ingredient
 | 
			
		||||
from cookbook.ingredients.models import Category, Ingredient
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  class CategoryType(DjangoObjectType):
 | 
			
		||||
      class Meta:
 | 
			
		||||
          model = Category
 | 
			
		||||
          fields = '__all__'
 | 
			
		||||
class CategoryType(DjangoObjectType):
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Category
 | 
			
		||||
        fields = "__all__"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  class IngredientType(DjangoObjectType):
 | 
			
		||||
      class Meta:
 | 
			
		||||
          model = Ingredient
 | 
			
		||||
          fields = '__all__'
 | 
			
		||||
class IngredientType(DjangoObjectType):
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Ingredient
 | 
			
		||||
        fields = "__all__"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  class Query(object):
 | 
			
		||||
      category = graphene.Field(CategoryType,
 | 
			
		||||
                                id=graphene.Int(),
 | 
			
		||||
                                name=graphene.String())
 | 
			
		||||
      all_categories = graphene.List(CategoryType)
 | 
			
		||||
class Query:
 | 
			
		||||
    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()
 | 
			
		||||
    )
 | 
			
		||||
    all_ingredients = graphene.List(IngredientType)
 | 
			
		||||
 | 
			
		||||
      ingredient = graphene.Field(IngredientType,
 | 
			
		||||
                                  id=graphene.Int(),
 | 
			
		||||
                                  name=graphene.String())
 | 
			
		||||
      all_ingredients = graphene.List(IngredientType)
 | 
			
		||||
    def resolve_all_categories(self, info, **kwargs):
 | 
			
		||||
        return Category.objects.all()
 | 
			
		||||
 | 
			
		||||
      def resolve_all_categories(self, info, **kwargs):
 | 
			
		||||
          return Category.objects.all()
 | 
			
		||||
    def resolve_all_ingredients(self, info, **kwargs):
 | 
			
		||||
        return Ingredient.objects.all()
 | 
			
		||||
 | 
			
		||||
      def resolve_all_ingredients(self, info, **kwargs):
 | 
			
		||||
          return Ingredient.objects.all()
 | 
			
		||||
    def resolve_category(self, info, **kwargs):
 | 
			
		||||
        id = kwargs.get("id")
 | 
			
		||||
        name = kwargs.get("name")
 | 
			
		||||
 | 
			
		||||
      def resolve_category(self, info, **kwargs):
 | 
			
		||||
          id = kwargs.get('id')
 | 
			
		||||
          name = kwargs.get('name')
 | 
			
		||||
        if id is not None:
 | 
			
		||||
            return Category.objects.get(pk=id)
 | 
			
		||||
 | 
			
		||||
          if id is not None:
 | 
			
		||||
              return Category.objects.get(pk=id)
 | 
			
		||||
        if name is not None:
 | 
			
		||||
            return Category.objects.get(name=name)
 | 
			
		||||
 | 
			
		||||
          if name is not None:
 | 
			
		||||
              return Category.objects.get(name=name)
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
          return None
 | 
			
		||||
    def resolve_ingredient(self, info, **kwargs):
 | 
			
		||||
        id = kwargs.get("id")
 | 
			
		||||
        name = kwargs.get("name")
 | 
			
		||||
 | 
			
		||||
      def resolve_ingredient(self, info, **kwargs):
 | 
			
		||||
          id = kwargs.get('id')
 | 
			
		||||
          name = kwargs.get('name')
 | 
			
		||||
        if id is not None:
 | 
			
		||||
            return Ingredient.objects.get(pk=id)
 | 
			
		||||
 | 
			
		||||
          if id is not None:
 | 
			
		||||
              return Ingredient.objects.get(pk=id)
 | 
			
		||||
        if name is not None:
 | 
			
		||||
            return Ingredient.objects.get(name=name)
 | 
			
		||||
 | 
			
		||||
          if name is not None:
 | 
			
		||||
              return Ingredient.objects.get(name=name)
 | 
			
		||||
 | 
			
		||||
          return None
 | 
			
		||||
        return None
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -85,8 +85,8 @@ Make sure the app name in ``cookbook.ingredients.apps.IngredientsConfig`` is set
 | 
			
		|||
    # cookbook/ingredients/apps.py
 | 
			
		||||
 | 
			
		||||
    from django.apps import AppConfig
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    class IngredientsConfig(AppConfig):
 | 
			
		||||
        default_auto_field = 'django.db.models.BigAutoField'
 | 
			
		||||
        name = 'cookbook.ingredients'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1 +1,52 @@
 | 
			
		|||
[{"model": "ingredients.category", "pk": 1, "fields": {"name": "Dairy"}}, {"model": "ingredients.category", "pk": 2, "fields": {"name": "Meat"}}, {"model": "ingredients.ingredient", "pk": 1, "fields": {"name": "Eggs", "notes": "Good old eggs", "category": 1}}, {"model": "ingredients.ingredient", "pk": 2, "fields": {"name": "Milk", "notes": "Comes from a cow", "category": 1}}, {"model": "ingredients.ingredient", "pk": 3, "fields": {"name": "Beef", "notes": "Much like milk, this comes from a cow", "category": 2}}, {"model": "ingredients.ingredient", "pk": 4, "fields": {"name": "Chicken", "notes": "Definitely doesn't come from a cow", "category": 2}}]
 | 
			
		||||
[
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "name": "Dairy"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.category",
 | 
			
		||||
    "pk": 1
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "name": "Meat"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.category",
 | 
			
		||||
    "pk": 2
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 1,
 | 
			
		||||
      "name": "Eggs",
 | 
			
		||||
      "notes": "Good old eggs"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 1
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 1,
 | 
			
		||||
      "name": "Milk",
 | 
			
		||||
      "notes": "Comes from a cow"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 2
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 2,
 | 
			
		||||
      "name": "Beef",
 | 
			
		||||
      "notes": "Much like milk, this comes from a cow"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 3
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 2,
 | 
			
		||||
      "name": "Chicken",
 | 
			
		||||
      "notes": "Definitely doesn't come from a cow"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 4
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,4 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
# Generated by Django 1.9 on 2015-12-04 18:15
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
| 
						 | 
				
			
			@ -10,24 +8,46 @@ class Migration(migrations.Migration):
 | 
			
		|||
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
    ]
 | 
			
		||||
    dependencies = []
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name='Category',
 | 
			
		||||
            name="Category",
 | 
			
		||||
            fields=[
 | 
			
		||||
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
			
		||||
                ('name', models.CharField(max_length=100)),
 | 
			
		||||
                (
 | 
			
		||||
                    "id",
 | 
			
		||||
                    models.AutoField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        verbose_name="ID",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("name", models.CharField(max_length=100)),
 | 
			
		||||
            ],
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name='Ingredient',
 | 
			
		||||
            name="Ingredient",
 | 
			
		||||
            fields=[
 | 
			
		||||
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
			
		||||
                ('name', models.CharField(max_length=100)),
 | 
			
		||||
                ('notes', models.TextField()),
 | 
			
		||||
                ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ingredients', to='ingredients.Category')),
 | 
			
		||||
                (
 | 
			
		||||
                    "id",
 | 
			
		||||
                    models.AutoField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        verbose_name="ID",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("name", models.CharField(max_length=100)),
 | 
			
		||||
                ("notes", models.TextField()),
 | 
			
		||||
                (
 | 
			
		||||
                    "category",
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        related_name="ingredients",
 | 
			
		||||
                        to="ingredients.Category",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,4 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
# Generated by Django 1.9 on 2016-11-04 00:50
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -8,13 +6,13 @@ from django.db import migrations, models
 | 
			
		|||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('ingredients', '0001_initial'),
 | 
			
		||||
        ("ingredients", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name='ingredient',
 | 
			
		||||
            name='notes',
 | 
			
		||||
            model_name="ingredient",
 | 
			
		||||
            name="notes",
 | 
			
		||||
            field=models.TextField(blank=True, null=True),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,12 +6,12 @@ from django.db import migrations
 | 
			
		|||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('ingredients', '0002_auto_20161104_0050'),
 | 
			
		||||
        ("ingredients", "0002_auto_20161104_0050"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterModelOptions(
 | 
			
		||||
            name='category',
 | 
			
		||||
            options={'verbose_name_plural': 'Categories'},
 | 
			
		||||
            name="category",
 | 
			
		||||
            options={"verbose_name_plural": "Categories"},
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ class IngredientType(DjangoObjectType):
 | 
			
		|||
        fields = "__all__"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Query(object):
 | 
			
		||||
class Query:
 | 
			
		||||
    category = graphene.Field(CategoryType, id=graphene.Int(), name=graphene.String())
 | 
			
		||||
    all_categories = graphene.List(CategoryType)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,4 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
# Generated by Django 1.9 on 2015-12-04 18:20
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
| 
						 | 
				
			
			@ -11,26 +9,62 @@ class Migration(migrations.Migration):
 | 
			
		|||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('ingredients', '0001_initial'),
 | 
			
		||||
        ("ingredients", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name='Recipe',
 | 
			
		||||
            name="Recipe",
 | 
			
		||||
            fields=[
 | 
			
		||||
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
			
		||||
                ('title', models.CharField(max_length=100)),
 | 
			
		||||
                ('instructions', models.TextField()),
 | 
			
		||||
                (
 | 
			
		||||
                    "id",
 | 
			
		||||
                    models.AutoField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        verbose_name="ID",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("title", models.CharField(max_length=100)),
 | 
			
		||||
                ("instructions", models.TextField()),
 | 
			
		||||
            ],
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name='RecipeIngredient',
 | 
			
		||||
            name="RecipeIngredient",
 | 
			
		||||
            fields=[
 | 
			
		||||
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
			
		||||
                ('amount', models.FloatField()),
 | 
			
		||||
                ('unit', models.CharField(choices=[('kg', 'Kilograms'), ('l', 'Litres'), ('', 'Units')], max_length=20)),
 | 
			
		||||
                ('ingredient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='used_by', to='ingredients.Ingredient')),
 | 
			
		||||
                ('recipes', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='amounts', to='recipes.Recipe')),
 | 
			
		||||
                (
 | 
			
		||||
                    "id",
 | 
			
		||||
                    models.AutoField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        verbose_name="ID",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("amount", models.FloatField()),
 | 
			
		||||
                (
 | 
			
		||||
                    "unit",
 | 
			
		||||
                    models.CharField(
 | 
			
		||||
                        choices=[("kg", "Kilograms"), ("l", "Litres"), ("", "Units")],
 | 
			
		||||
                        max_length=20,
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "ingredient",
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        related_name="used_by",
 | 
			
		||||
                        to="ingredients.Ingredient",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "recipes",
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        related_name="amounts",
 | 
			
		||||
                        to="recipes.Recipe",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,4 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
# Generated by Django 1.9 on 2016-11-04 01:06
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -8,18 +6,26 @@ from django.db import migrations, models
 | 
			
		|||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('recipes', '0001_initial'),
 | 
			
		||||
        ("recipes", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.RenameField(
 | 
			
		||||
            model_name='recipeingredient',
 | 
			
		||||
            old_name='recipes',
 | 
			
		||||
            new_name='recipe',
 | 
			
		||||
            model_name="recipeingredient",
 | 
			
		||||
            old_name="recipes",
 | 
			
		||||
            new_name="recipe",
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name='recipeingredient',
 | 
			
		||||
            name='unit',
 | 
			
		||||
            field=models.CharField(choices=[(b'unit', b'Units'), (b'kg', b'Kilograms'), (b'l', b'Litres'), (b'st', b'Shots')], max_length=20),
 | 
			
		||||
            model_name="recipeingredient",
 | 
			
		||||
            name="unit",
 | 
			
		||||
            field=models.CharField(
 | 
			
		||||
                choices=[
 | 
			
		||||
                    (b"unit", b"Units"),
 | 
			
		||||
                    (b"kg", b"Kilograms"),
 | 
			
		||||
                    (b"l", b"Litres"),
 | 
			
		||||
                    (b"st", b"Shots"),
 | 
			
		||||
                ],
 | 
			
		||||
                max_length=20,
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,13 +6,21 @@ from django.db import migrations, models
 | 
			
		|||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('recipes', '0002_auto_20161104_0106'),
 | 
			
		||||
        ("recipes", "0002_auto_20161104_0106"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name='recipeingredient',
 | 
			
		||||
            name='unit',
 | 
			
		||||
            field=models.CharField(choices=[('unit', 'Units'), ('kg', 'Kilograms'), ('l', 'Litres'), ('st', 'Shots')], max_length=20),
 | 
			
		||||
            model_name="recipeingredient",
 | 
			
		||||
            name="unit",
 | 
			
		||||
            field=models.CharField(
 | 
			
		||||
                choices=[
 | 
			
		||||
                    ("unit", "Units"),
 | 
			
		||||
                    ("kg", "Kilograms"),
 | 
			
		||||
                    ("l", "Litres"),
 | 
			
		||||
                    ("st", "Shots"),
 | 
			
		||||
                ],
 | 
			
		||||
                max_length=20,
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ class RecipeIngredientType(DjangoObjectType):
 | 
			
		|||
        fields = "__all__"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Query(object):
 | 
			
		||||
class Query:
 | 
			
		||||
    recipe = graphene.Field(RecipeType, id=graphene.Int(), title=graphene.String())
 | 
			
		||||
    all_recipes = graphene.List(RecipeType)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1 +1,52 @@
 | 
			
		|||
[{"model": "ingredients.category", "pk": 1, "fields": {"name": "Dairy"}}, {"model": "ingredients.category", "pk": 2, "fields": {"name": "Meat"}}, {"model": "ingredients.ingredient", "pk": 1, "fields": {"name": "Eggs", "notes": "Good old eggs", "category": 1}}, {"model": "ingredients.ingredient", "pk": 2, "fields": {"name": "Milk", "notes": "Comes from a cow", "category": 1}}, {"model": "ingredients.ingredient", "pk": 3, "fields": {"name": "Beef", "notes": "Much like milk, this comes from a cow", "category": 2}}, {"model": "ingredients.ingredient", "pk": 4, "fields": {"name": "Chicken", "notes": "Definitely doesn't come from a cow", "category": 2}}]
 | 
			
		||||
[
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "name": "Dairy"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.category",
 | 
			
		||||
    "pk": 1
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "name": "Meat"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.category",
 | 
			
		||||
    "pk": 2
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 1,
 | 
			
		||||
      "name": "Eggs",
 | 
			
		||||
      "notes": "Good old eggs"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 1
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 1,
 | 
			
		||||
      "name": "Milk",
 | 
			
		||||
      "notes": "Comes from a cow"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 2
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 2,
 | 
			
		||||
      "name": "Beef",
 | 
			
		||||
      "notes": "Much like milk, this comes from a cow"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 3
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 2,
 | 
			
		||||
      "name": "Chicken",
 | 
			
		||||
      "notes": "Definitely doesn't come from a cow"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 4
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,4 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
# Generated by Django 1.9 on 2015-12-04 18:15
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
| 
						 | 
				
			
			@ -10,24 +8,46 @@ class Migration(migrations.Migration):
 | 
			
		|||
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
    ]
 | 
			
		||||
    dependencies = []
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name='Category',
 | 
			
		||||
            name="Category",
 | 
			
		||||
            fields=[
 | 
			
		||||
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
			
		||||
                ('name', models.CharField(max_length=100)),
 | 
			
		||||
                (
 | 
			
		||||
                    "id",
 | 
			
		||||
                    models.AutoField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        verbose_name="ID",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("name", models.CharField(max_length=100)),
 | 
			
		||||
            ],
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name='Ingredient',
 | 
			
		||||
            name="Ingredient",
 | 
			
		||||
            fields=[
 | 
			
		||||
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
			
		||||
                ('name', models.CharField(max_length=100)),
 | 
			
		||||
                ('notes', models.TextField()),
 | 
			
		||||
                ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ingredients', to='ingredients.Category')),
 | 
			
		||||
                (
 | 
			
		||||
                    "id",
 | 
			
		||||
                    models.AutoField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        verbose_name="ID",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("name", models.CharField(max_length=100)),
 | 
			
		||||
                ("notes", models.TextField()),
 | 
			
		||||
                (
 | 
			
		||||
                    "category",
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        related_name="ingredients",
 | 
			
		||||
                        to="ingredients.Category",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,4 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
# Generated by Django 1.9 on 2016-11-04 00:50
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -8,13 +6,13 @@ from django.db import migrations, models
 | 
			
		|||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('ingredients', '0001_initial'),
 | 
			
		||||
        ("ingredients", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name='ingredient',
 | 
			
		||||
            name='notes',
 | 
			
		||||
            model_name="ingredient",
 | 
			
		||||
            name="notes",
 | 
			
		||||
            field=models.TextField(blank=True, null=True),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ class IngredientNode(DjangoObjectType):
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Query(object):
 | 
			
		||||
class Query:
 | 
			
		||||
    category = Node.Field(CategoryNode)
 | 
			
		||||
    all_categories = DjangoFilterConnectionField(CategoryNode)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,4 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
# Generated by Django 1.9 on 2015-12-04 18:20
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
| 
						 | 
				
			
			@ -11,26 +9,62 @@ class Migration(migrations.Migration):
 | 
			
		|||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('ingredients', '0001_initial'),
 | 
			
		||||
        ("ingredients", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name='Recipe',
 | 
			
		||||
            name="Recipe",
 | 
			
		||||
            fields=[
 | 
			
		||||
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
			
		||||
                ('title', models.CharField(max_length=100)),
 | 
			
		||||
                ('instructions', models.TextField()),
 | 
			
		||||
                (
 | 
			
		||||
                    "id",
 | 
			
		||||
                    models.AutoField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        verbose_name="ID",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("title", models.CharField(max_length=100)),
 | 
			
		||||
                ("instructions", models.TextField()),
 | 
			
		||||
            ],
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name='RecipeIngredient',
 | 
			
		||||
            name="RecipeIngredient",
 | 
			
		||||
            fields=[
 | 
			
		||||
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
			
		||||
                ('amount', models.FloatField()),
 | 
			
		||||
                ('unit', models.CharField(choices=[('kg', 'Kilograms'), ('l', 'Litres'), ('', 'Units')], max_length=20)),
 | 
			
		||||
                ('ingredient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='used_by', to='ingredients.Ingredient')),
 | 
			
		||||
                ('recipes', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='amounts', to='recipes.Recipe')),
 | 
			
		||||
                (
 | 
			
		||||
                    "id",
 | 
			
		||||
                    models.AutoField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        verbose_name="ID",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("amount", models.FloatField()),
 | 
			
		||||
                (
 | 
			
		||||
                    "unit",
 | 
			
		||||
                    models.CharField(
 | 
			
		||||
                        choices=[("kg", "Kilograms"), ("l", "Litres"), ("", "Units")],
 | 
			
		||||
                        max_length=20,
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "ingredient",
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        related_name="used_by",
 | 
			
		||||
                        to="ingredients.Ingredient",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "recipes",
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        related_name="amounts",
 | 
			
		||||
                        to="recipes.Recipe",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,4 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
# Generated by Django 1.9 on 2016-11-04 01:06
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -8,18 +6,26 @@ from django.db import migrations, models
 | 
			
		|||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('recipes', '0001_initial'),
 | 
			
		||||
        ("recipes", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.RenameField(
 | 
			
		||||
            model_name='recipeingredient',
 | 
			
		||||
            old_name='recipes',
 | 
			
		||||
            new_name='recipe',
 | 
			
		||||
            model_name="recipeingredient",
 | 
			
		||||
            old_name="recipes",
 | 
			
		||||
            new_name="recipe",
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name='recipeingredient',
 | 
			
		||||
            name='unit',
 | 
			
		||||
            field=models.CharField(choices=[(b'unit', b'Units'), (b'kg', b'Kilograms'), (b'l', b'Litres'), (b'st', b'Shots')], max_length=20),
 | 
			
		||||
            model_name="recipeingredient",
 | 
			
		||||
            name="unit",
 | 
			
		||||
            field=models.CharField(
 | 
			
		||||
                choices=[
 | 
			
		||||
                    (b"unit", b"Units"),
 | 
			
		||||
                    (b"kg", b"Kilograms"),
 | 
			
		||||
                    (b"l", b"Litres"),
 | 
			
		||||
                    (b"st", b"Shots"),
 | 
			
		||||
                ],
 | 
			
		||||
                max_length=20,
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ class RecipeIngredientNode(DjangoObjectType):
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Query(object):
 | 
			
		||||
class Query:
 | 
			
		||||
    recipe = Node.Field(RecipeNode)
 | 
			
		||||
    all_recipes = DjangoFilterConnectionField(RecipeNode)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1 +1,302 @@
 | 
			
		|||
[{"model": "auth.user", "pk": 1, "fields": {"password": "pbkdf2_sha256$24000$0SgBlSlnbv5c$ijVQipm2aNDlcrTL8Qi3SVNHphTm4HIsDfUi4kn9tog=", "last_login": "2016-11-04T00:46:58Z", "is_superuser": true, "username": "admin", "first_name": "", "last_name": "", "email": "asdf@example.com", "is_staff": true, "is_active": true, "date_joined": "2016-11-03T18:24:40Z", "groups": [], "user_permissions": []}}, {"model": "recipes.recipe", "pk": 1, "fields": {"title": "Cheerios With a Shot of Vermouth", "instructions": "https://xkcd.com/720/"}}, {"model": "recipes.recipe", "pk": 2, "fields": {"title": "Quail Eggs in Whipped Cream and MSG", "instructions": "https://xkcd.com/720/"}}, {"model": "recipes.recipe", "pk": 3, "fields": {"title": "Deep Fried Skittles", "instructions": "https://xkcd.com/720/"}}, {"model": "recipes.recipe", "pk": 4, "fields": {"title": "Newt ala Doritos", "instructions": "https://xkcd.com/720/"}}, {"model": "recipes.recipe", "pk": 5, "fields": {"title": "Fruit Salad", "instructions": "Chop up and add together"}}, {"model": "recipes.recipeingredient", "pk": 1, "fields": {"recipes": 5, "ingredient": 9, "amount": 1.0, "unit": "unit"}}, {"model": "recipes.recipeingredient", "pk": 2, "fields": {"recipes": 5, "ingredient": 10, "amount": 2.0, "unit": "unit"}}, {"model": "recipes.recipeingredient", "pk": 3, "fields": {"recipes": 5, "ingredient": 7, "amount": 3.0, "unit": "unit"}}, {"model": "recipes.recipeingredient", "pk": 4, "fields": {"recipes": 5, "ingredient": 8, "amount": 4.0, "unit": "unit"}}, {"model": "recipes.recipeingredient", "pk": 5, "fields": {"recipes": 4, "ingredient": 5, "amount": 1.0, "unit": "kg"}}, {"model": "recipes.recipeingredient", "pk": 6, "fields": {"recipes": 4, "ingredient": 6, "amount": 2.0, "unit": "l"}}, {"model": "recipes.recipeingredient", "pk": 7, "fields": {"recipes": 3, "ingredient": 4, "amount": 1.0, "unit": "unit"}}, {"model": "recipes.recipeingredient", "pk": 8, "fields": {"recipes": 2, "ingredient": 2, "amount": 1.0, "unit": "kg"}}, {"model": "recipes.recipeingredient", "pk": 9, "fields": {"recipes": 2, "ingredient": 11, "amount": 2.0, "unit": "l"}}, {"model": "recipes.recipeingredient", "pk": 10, "fields": {"recipes": 2, "ingredient": 12, "amount": 3.0, "unit": "st"}}, {"model": "recipes.recipeingredient", "pk": 11, "fields": {"recipes": 1, "ingredient": 1, "amount": 1.0, "unit": "kg"}}, {"model": "recipes.recipeingredient", "pk": 12, "fields": {"recipes": 1, "ingredient": 3, "amount": 1.0, "unit": "st"}}, {"model": "ingredients.category", "pk": 1, "fields": {"name": "fruit"}}, {"model": "ingredients.category", "pk": 3, "fields": {"name": "xkcd"}}, {"model": "ingredients.ingredient", "pk": 1, "fields": {"name": "Cheerios", "notes": "this is a note", "category": 3}}, {"model": "ingredients.ingredient", "pk": 2, "fields": {"name": "Quail Eggs", "notes": "has more notes", "category": 3}}, {"model": "ingredients.ingredient", "pk": 3, "fields": {"name": "Vermouth", "notes": "", "category": 3}}, {"model": "ingredients.ingredient", "pk": 4, "fields": {"name": "Skittles", "notes": "", "category": 3}}, {"model": "ingredients.ingredient", "pk": 5, "fields": {"name": "Newt", "notes": "Braised and Confuesd", "category": 3}}, {"model": "ingredients.ingredient", "pk": 6, "fields": {"name": "Doritos", "notes": "Crushed", "category": 3}}, {"model": "ingredients.ingredient", "pk": 7, "fields": {"name": "Apple", "notes": "", "category": 1}}, {"model": "ingredients.ingredient", "pk": 8, "fields": {"name": "Orange", "notes": "", "category": 1}}, {"model": "ingredients.ingredient", "pk": 9, "fields": {"name": "Banana", "notes": "", "category": 1}}, {"model": "ingredients.ingredient", "pk": 10, "fields": {"name": "Grapes", "notes": "", "category": 1}}, {"model": "ingredients.ingredient", "pk": 11, "fields": {"name": "Whipped Cream", "notes": "", "category": 3}}, {"model": "ingredients.ingredient", "pk": 12, "fields": {"name": "MSG", "notes": "", "category": 3}}]
 | 
			
		||||
[
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "date_joined": "2016-11-03T18:24:40Z",
 | 
			
		||||
      "email": "asdf@example.com",
 | 
			
		||||
      "first_name": "",
 | 
			
		||||
      "groups": [],
 | 
			
		||||
      "is_active": true,
 | 
			
		||||
      "is_staff": true,
 | 
			
		||||
      "is_superuser": true,
 | 
			
		||||
      "last_login": "2016-11-04T00:46:58Z",
 | 
			
		||||
      "last_name": "",
 | 
			
		||||
      "password": "pbkdf2_sha256$24000$0SgBlSlnbv5c$ijVQipm2aNDlcrTL8Qi3SVNHphTm4HIsDfUi4kn9tog=",
 | 
			
		||||
      "user_permissions": [],
 | 
			
		||||
      "username": "admin"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "auth.user",
 | 
			
		||||
    "pk": 1
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "instructions": "https://xkcd.com/720/",
 | 
			
		||||
      "title": "Cheerios With a Shot of Vermouth"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipe",
 | 
			
		||||
    "pk": 1
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "instructions": "https://xkcd.com/720/",
 | 
			
		||||
      "title": "Quail Eggs in Whipped Cream and MSG"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipe",
 | 
			
		||||
    "pk": 2
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "instructions": "https://xkcd.com/720/",
 | 
			
		||||
      "title": "Deep Fried Skittles"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipe",
 | 
			
		||||
    "pk": 3
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "instructions": "https://xkcd.com/720/",
 | 
			
		||||
      "title": "Newt ala Doritos"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipe",
 | 
			
		||||
    "pk": 4
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "instructions": "Chop up and add together",
 | 
			
		||||
      "title": "Fruit Salad"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipe",
 | 
			
		||||
    "pk": 5
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "amount": 1.0,
 | 
			
		||||
      "ingredient": 9,
 | 
			
		||||
      "recipes": 5,
 | 
			
		||||
      "unit": "unit"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipeingredient",
 | 
			
		||||
    "pk": 1
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "amount": 2.0,
 | 
			
		||||
      "ingredient": 10,
 | 
			
		||||
      "recipes": 5,
 | 
			
		||||
      "unit": "unit"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipeingredient",
 | 
			
		||||
    "pk": 2
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "amount": 3.0,
 | 
			
		||||
      "ingredient": 7,
 | 
			
		||||
      "recipes": 5,
 | 
			
		||||
      "unit": "unit"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipeingredient",
 | 
			
		||||
    "pk": 3
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "amount": 4.0,
 | 
			
		||||
      "ingredient": 8,
 | 
			
		||||
      "recipes": 5,
 | 
			
		||||
      "unit": "unit"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipeingredient",
 | 
			
		||||
    "pk": 4
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "amount": 1.0,
 | 
			
		||||
      "ingredient": 5,
 | 
			
		||||
      "recipes": 4,
 | 
			
		||||
      "unit": "kg"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipeingredient",
 | 
			
		||||
    "pk": 5
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "amount": 2.0,
 | 
			
		||||
      "ingredient": 6,
 | 
			
		||||
      "recipes": 4,
 | 
			
		||||
      "unit": "l"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipeingredient",
 | 
			
		||||
    "pk": 6
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "amount": 1.0,
 | 
			
		||||
      "ingredient": 4,
 | 
			
		||||
      "recipes": 3,
 | 
			
		||||
      "unit": "unit"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipeingredient",
 | 
			
		||||
    "pk": 7
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "amount": 1.0,
 | 
			
		||||
      "ingredient": 2,
 | 
			
		||||
      "recipes": 2,
 | 
			
		||||
      "unit": "kg"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipeingredient",
 | 
			
		||||
    "pk": 8
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "amount": 2.0,
 | 
			
		||||
      "ingredient": 11,
 | 
			
		||||
      "recipes": 2,
 | 
			
		||||
      "unit": "l"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipeingredient",
 | 
			
		||||
    "pk": 9
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "amount": 3.0,
 | 
			
		||||
      "ingredient": 12,
 | 
			
		||||
      "recipes": 2,
 | 
			
		||||
      "unit": "st"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipeingredient",
 | 
			
		||||
    "pk": 10
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "amount": 1.0,
 | 
			
		||||
      "ingredient": 1,
 | 
			
		||||
      "recipes": 1,
 | 
			
		||||
      "unit": "kg"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipeingredient",
 | 
			
		||||
    "pk": 11
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "amount": 1.0,
 | 
			
		||||
      "ingredient": 3,
 | 
			
		||||
      "recipes": 1,
 | 
			
		||||
      "unit": "st"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "recipes.recipeingredient",
 | 
			
		||||
    "pk": 12
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "name": "fruit"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.category",
 | 
			
		||||
    "pk": 1
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "name": "xkcd"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.category",
 | 
			
		||||
    "pk": 3
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 3,
 | 
			
		||||
      "name": "Cheerios",
 | 
			
		||||
      "notes": "this is a note"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 1
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 3,
 | 
			
		||||
      "name": "Quail Eggs",
 | 
			
		||||
      "notes": "has more notes"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 2
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 3,
 | 
			
		||||
      "name": "Vermouth",
 | 
			
		||||
      "notes": ""
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 3
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 3,
 | 
			
		||||
      "name": "Skittles",
 | 
			
		||||
      "notes": ""
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 4
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 3,
 | 
			
		||||
      "name": "Newt",
 | 
			
		||||
      "notes": "Braised and Confuesd"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 5
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 3,
 | 
			
		||||
      "name": "Doritos",
 | 
			
		||||
      "notes": "Crushed"
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 6
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 1,
 | 
			
		||||
      "name": "Apple",
 | 
			
		||||
      "notes": ""
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 7
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 1,
 | 
			
		||||
      "name": "Orange",
 | 
			
		||||
      "notes": ""
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 8
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 1,
 | 
			
		||||
      "name": "Banana",
 | 
			
		||||
      "notes": ""
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 9
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 1,
 | 
			
		||||
      "name": "Grapes",
 | 
			
		||||
      "notes": ""
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 10
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 3,
 | 
			
		||||
      "name": "Whipped Cream",
 | 
			
		||||
      "notes": ""
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 11
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "fields": {
 | 
			
		||||
      "category": 3,
 | 
			
		||||
      "name": "MSG",
 | 
			
		||||
      "notes": ""
 | 
			
		||||
    },
 | 
			
		||||
    "model": "ingredients.ingredient",
 | 
			
		||||
    "pk": 12
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
from __future__ import absolute_import
 | 
			
		||||
 | 
			
		||||
from django.db import models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
class MissingType(object):
 | 
			
		||||
class MissingType:
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,8 +68,7 @@ def get_choices(choices):
 | 
			
		|||
        choices = choices.items()
 | 
			
		||||
    for value, help_text in choices:
 | 
			
		||||
        if isinstance(help_text, (tuple, list)):
 | 
			
		||||
            for choice in get_choices(help_text):
 | 
			
		||||
                yield choice
 | 
			
		||||
            yield from get_choices(help_text)
 | 
			
		||||
        else:
 | 
			
		||||
            name = convert_choice_name(value)
 | 
			
		||||
            while name in converted_names:
 | 
			
		||||
| 
						 | 
				
			
			@ -86,7 +85,7 @@ def convert_choices_to_named_enum_with_descriptions(name, choices):
 | 
			
		|||
    named_choices = [(c[0], c[1]) for c in choices]
 | 
			
		||||
    named_choices_descriptions = {c[0]: c[2] for c in choices}
 | 
			
		||||
 | 
			
		||||
    class EnumWithDescriptionsType(object):
 | 
			
		||||
    class EnumWithDescriptionsType:
 | 
			
		||||
        @property
 | 
			
		||||
        def description(self):
 | 
			
		||||
            return str(named_choices_descriptions[self.name])
 | 
			
		||||
| 
						 | 
				
			
			@ -103,7 +102,7 @@ def generate_enum_name(django_model_meta, field):
 | 
			
		|||
        )
 | 
			
		||||
        name = custom_func(field)
 | 
			
		||||
    elif graphene_settings.DJANGO_CHOICE_FIELD_ENUM_V2_NAMING is True:
 | 
			
		||||
        name = to_camel_case("{}_{}".format(django_model_meta.object_name, field.name))
 | 
			
		||||
        name = to_camel_case(f"{django_model_meta.object_name}_{field.name}")
 | 
			
		||||
    else:
 | 
			
		||||
        name = "{app_label}{object_name}{field_name}Choices".format(
 | 
			
		||||
            app_label=to_camel_case(django_model_meta.app_label.title()),
 | 
			
		||||
| 
						 | 
				
			
			@ -149,7 +148,9 @@ def get_django_field_description(field):
 | 
			
		|||
@singledispatch
 | 
			
		||||
def convert_django_field(field, registry=None):
 | 
			
		||||
    raise Exception(
 | 
			
		||||
        "Don't know how to convert the Django field %s (%s)" % (field, field.__class__)
 | 
			
		||||
        "Don't know how to convert the Django field {} ({})".format(
 | 
			
		||||
            field, field.__class__
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ from .exception.formating import wrap_exception
 | 
			
		|||
from .types import DjangoDebug
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DjangoDebugContext(object):
 | 
			
		||||
class DjangoDebugContext:
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.debug_promise = None
 | 
			
		||||
        self.promises = []
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +46,7 @@ class DjangoDebugContext(object):
 | 
			
		|||
            unwrap_cursor(connection)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DjangoDebugMiddleware(object):
 | 
			
		||||
class DjangoDebugMiddleware:
 | 
			
		||||
    def resolve(self, next, root, info, **args):
 | 
			
		||||
        context = info.context
 | 
			
		||||
        django_debug = getattr(context, "django_debug", None)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,4 @@
 | 
			
		|||
# Code obtained from django-debug-toolbar sql panel tracking
 | 
			
		||||
from __future__ import absolute_import, unicode_literals
 | 
			
		||||
 | 
			
		||||
import json
 | 
			
		||||
from threading import local
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +49,7 @@ def unwrap_cursor(connection):
 | 
			
		|||
        del connection._graphene_cursor
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ExceptionCursorWrapper(object):
 | 
			
		||||
class ExceptionCursorWrapper:
 | 
			
		||||
    """
 | 
			
		||||
    Wraps a cursor and raises an exception on any operation.
 | 
			
		||||
    Used in Templates panel.
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +62,7 @@ class ExceptionCursorWrapper(object):
 | 
			
		|||
        raise SQLQueryTriggered()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NormalCursorWrapper(object):
 | 
			
		||||
class NormalCursorWrapper:
 | 
			
		||||
    """
 | 
			
		||||
    Wraps a cursor and logs queries.
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +84,7 @@ class NormalCursorWrapper(object):
 | 
			
		|||
        if not params:
 | 
			
		||||
            return params
 | 
			
		||||
        if isinstance(params, dict):
 | 
			
		||||
            return dict((key, self._quote_expr(value)) for key, value in params.items())
 | 
			
		||||
            return {key: self._quote_expr(value) for key, value in params.items()}
 | 
			
		||||
        return list(map(self._quote_expr, params))
 | 
			
		||||
 | 
			
		||||
    def _decode(self, param):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ from ..middleware import DjangoDebugMiddleware
 | 
			
		|||
from ..types import DjangoDebug
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class context(object):
 | 
			
		||||
class context:
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ class DjangoListField(Field):
 | 
			
		|||
            _type = _type.of_type
 | 
			
		||||
 | 
			
		||||
        # Django would never return a Set of None  vvvvvvv
 | 
			
		||||
        super(DjangoListField, self).__init__(List(NonNull(_type)), *args, **kwargs)
 | 
			
		||||
        super().__init__(List(NonNull(_type)), *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
        assert issubclass(
 | 
			
		||||
            self._underlying_type, DjangoObjectType
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +63,7 @@ class DjangoListField(Field):
 | 
			
		|||
        return queryset
 | 
			
		||||
 | 
			
		||||
    def wrap_resolve(self, parent_resolver):
 | 
			
		||||
        resolver = super(DjangoListField, self).wrap_resolve(parent_resolver)
 | 
			
		||||
        resolver = super().wrap_resolve(parent_resolver)
 | 
			
		||||
        _type = self.type
 | 
			
		||||
        if isinstance(_type, NonNull):
 | 
			
		||||
            _type = _type.of_type
 | 
			
		||||
| 
						 | 
				
			
			@ -87,7 +87,7 @@ class DjangoConnectionField(ConnectionField):
 | 
			
		|||
            graphene_settings.RELAY_CONNECTION_ENFORCE_FIRST_OR_LAST,
 | 
			
		||||
        )
 | 
			
		||||
        kwargs.setdefault("offset", Int())
 | 
			
		||||
        super(DjangoConnectionField, self).__init__(*args, **kwargs)
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def type(self):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,7 @@ class DjangoFilterConnectionField(DjangoConnectionField):
 | 
			
		|||
        self._filtering_args = None
 | 
			
		||||
        self._extra_filter_meta = extra_filter_meta
 | 
			
		||||
        self._base_args = None
 | 
			
		||||
        super(DjangoFilterConnectionField, self).__init__(type_, *args, **kwargs)
 | 
			
		||||
        super().__init__(type_, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def args(self):
 | 
			
		||||
| 
						 | 
				
			
			@ -90,9 +90,7 @@ class DjangoFilterConnectionField(DjangoConnectionField):
 | 
			
		|||
                    kwargs[k] = convert_enum(v)
 | 
			
		||||
            return kwargs
 | 
			
		||||
 | 
			
		||||
        qs = super(DjangoFilterConnectionField, cls).resolve_queryset(
 | 
			
		||||
            connection, iterable, info, args
 | 
			
		||||
        )
 | 
			
		||||
        qs = super().resolve_queryset(connection, iterable, info, args)
 | 
			
		||||
 | 
			
		||||
        filterset = filterset_class(
 | 
			
		||||
            data=filter_kwargs(), queryset=qs, request=info.context
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,6 @@ class ArrayFilter(TypedFilter):
 | 
			
		|||
            return qs
 | 
			
		||||
        if self.distinct:
 | 
			
		||||
            qs = qs.distinct()
 | 
			
		||||
        lookup = "%s__%s" % (self.field_name, self.lookup_expr)
 | 
			
		||||
        lookup = f"{self.field_name}__{self.lookup_expr}"
 | 
			
		||||
        qs = self.get_method(qs)(**{lookup: value})
 | 
			
		||||
        return qs
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ class GlobalIDFilter(Filter):
 | 
			
		|||
        _id = None
 | 
			
		||||
        if value is not None:
 | 
			
		||||
            _, _id = from_global_id(value)
 | 
			
		||||
        return super(GlobalIDFilter, self).filter(qs, _id)
 | 
			
		||||
        return super().filter(qs, _id)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GlobalIDMultipleChoiceFilter(MultipleChoiceFilter):
 | 
			
		||||
| 
						 | 
				
			
			@ -25,4 +25,4 @@ class GlobalIDMultipleChoiceFilter(MultipleChoiceFilter):
 | 
			
		|||
 | 
			
		||||
    def filter(self, qs, value):
 | 
			
		||||
        gids = [from_global_id(v)[1] for v in value]
 | 
			
		||||
        return super(GlobalIDMultipleChoiceFilter, self).filter(qs, gids)
 | 
			
		||||
        return super().filter(qs, gids)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,4 +23,4 @@ class ListFilter(TypedFilter):
 | 
			
		|||
            else:
 | 
			
		||||
                return qs.none()
 | 
			
		||||
        else:
 | 
			
		||||
            return super(ListFilter, self).filter(qs, value)
 | 
			
		||||
            return super().filter(qs, value)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ class TypedFilter(Filter):
 | 
			
		|||
 | 
			
		||||
    def __init__(self, input_type=None, *args, **kwargs):
 | 
			
		||||
        self._input_type = input_type
 | 
			
		||||
        super(TypedFilter, self).__init__(*args, **kwargs)
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def input_type(self):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ class GrapheneFilterSetMixin(BaseFilterSet):
 | 
			
		|||
def setup_filterset(filterset_class):
 | 
			
		||||
    """Wrap a provided filterset in Graphene-specific functionality"""
 | 
			
		||||
    return type(
 | 
			
		||||
        "Graphene{}".format(filterset_class.__name__),
 | 
			
		||||
        f"Graphene{filterset_class.__name__}",
 | 
			
		||||
        (filterset_class, GrapheneFilterSetMixin),
 | 
			
		||||
        {},
 | 
			
		||||
    )
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +40,7 @@ def setup_filterset(filterset_class):
 | 
			
		|||
def custom_filterset_factory(model, filterset_base_class=FilterSet, **meta):
 | 
			
		||||
    """Create a filterset for the given model using the provided meta data"""
 | 
			
		||||
    meta.update({"model": model})
 | 
			
		||||
    meta_class = type(str("Meta"), (object,), meta)
 | 
			
		||||
    meta_class = type("Meta", (object,), meta)
 | 
			
		||||
    filterset = type(
 | 
			
		||||
        str("%sFilterSet" % model._meta.object_name),
 | 
			
		||||
        (filterset_base_class, GrapheneFilterSetMixin),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
from mock import MagicMock
 | 
			
		||||
from unittest.mock import MagicMock
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
from django.db import models
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,7 +67,7 @@ def assert_arguments(field, *arguments):
 | 
			
		|||
    actual = [name for name in args if name not in ignore and not name.startswith("_")]
 | 
			
		||||
    assert set(arguments) == set(
 | 
			
		||||
        actual
 | 
			
		||||
    ), "Expected arguments ({}) did not match actual ({})".format(arguments, actual)
 | 
			
		||||
    ), f"Expected arguments ({arguments}) did not match actual ({actual})"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def assert_orderable(field):
 | 
			
		||||
| 
						 | 
				
			
			@ -141,7 +141,7 @@ def test_filter_shortcut_filterset_context():
 | 
			
		|||
 | 
			
		||||
        @property
 | 
			
		||||
        def qs(self):
 | 
			
		||||
            qs = super(ArticleContextFilter, self).qs
 | 
			
		||||
            qs = super().qs
 | 
			
		||||
            return qs.filter(reporter=self.request.reporter)
 | 
			
		||||
 | 
			
		||||
    class Query(ObjectType):
 | 
			
		||||
| 
						 | 
				
			
			@ -166,7 +166,7 @@ def test_filter_shortcut_filterset_context():
 | 
			
		|||
        editor=r2,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    class context(object):
 | 
			
		||||
    class context:
 | 
			
		||||
        reporter = r2
 | 
			
		||||
 | 
			
		||||
    query = """
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -349,19 +349,19 @@ def test_fk_id_in_filter(query):
 | 
			
		|||
    schema = Schema(query=query)
 | 
			
		||||
 | 
			
		||||
    query = """
 | 
			
		||||
    query {
 | 
			
		||||
        articles (reporter_In: [%s, %s]) {
 | 
			
		||||
            edges {
 | 
			
		||||
                node {
 | 
			
		||||
    query {{
 | 
			
		||||
        articles (reporter_In: [{}, {}]) {{
 | 
			
		||||
            edges {{
 | 
			
		||||
                node {{
 | 
			
		||||
                    headline
 | 
			
		||||
                    reporter {
 | 
			
		||||
                    reporter {{
 | 
			
		||||
                        lastName
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    """ % (
 | 
			
		||||
                    }}
 | 
			
		||||
                }}
 | 
			
		||||
            }}
 | 
			
		||||
        }}
 | 
			
		||||
    }}
 | 
			
		||||
    """.format(
 | 
			
		||||
        john_doe.id,
 | 
			
		||||
        jean_bon.id,
 | 
			
		||||
    )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -98,7 +98,7 @@ def test_typed_filter_schema(schema):
 | 
			
		|||
    )
 | 
			
		||||
 | 
			
		||||
    for filter_field, gql_type in filters.items():
 | 
			
		||||
        assert "{}: {}".format(filter_field, gql_type) in all_articles_filters
 | 
			
		||||
        assert f"{filter_field}: {gql_type}" in all_articles_filters
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_typed_filters_work(schema):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -95,7 +95,7 @@ class DjangoFormMutation(BaseDjangoFormMutation):
 | 
			
		|||
        _meta.fields = yank_fields_from_attrs(output_fields, _as=Field)
 | 
			
		||||
 | 
			
		||||
        input_fields = yank_fields_from_attrs(input_fields, _as=InputField)
 | 
			
		||||
        super(DjangoFormMutation, cls).__init_subclass_with_meta__(
 | 
			
		||||
        super().__init_subclass_with_meta__(
 | 
			
		||||
            _meta=_meta, input_fields=input_fields, **options
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -127,7 +127,7 @@ class DjangoModelFormMutation(BaseDjangoFormMutation):
 | 
			
		|||
        return_field_name=None,
 | 
			
		||||
        only_fields=(),
 | 
			
		||||
        exclude_fields=(),
 | 
			
		||||
        **options
 | 
			
		||||
        **options,
 | 
			
		||||
    ):
 | 
			
		||||
 | 
			
		||||
        if not form_class:
 | 
			
		||||
| 
						 | 
				
			
			@ -147,7 +147,7 @@ class DjangoModelFormMutation(BaseDjangoFormMutation):
 | 
			
		|||
        registry = get_global_registry()
 | 
			
		||||
        model_type = registry.get_type_for_model(model)
 | 
			
		||||
        if not model_type:
 | 
			
		||||
            raise Exception("No type registered for model: {}".format(model.__name__))
 | 
			
		||||
            raise Exception(f"No type registered for model: {model.__name__}")
 | 
			
		||||
 | 
			
		||||
        if not return_field_name:
 | 
			
		||||
            model_name = model.__name__
 | 
			
		||||
| 
						 | 
				
			
			@ -163,7 +163,7 @@ class DjangoModelFormMutation(BaseDjangoFormMutation):
 | 
			
		|||
        _meta.fields = yank_fields_from_attrs(output_fields, _as=Field)
 | 
			
		||||
 | 
			
		||||
        input_fields = yank_fields_from_attrs(input_fields, _as=InputField)
 | 
			
		||||
        super(DjangoModelFormMutation, cls).__init_subclass_with_meta__(
 | 
			
		||||
        super().__init_subclass_with_meta__(
 | 
			
		||||
            _meta=_meta, input_fields=input_fields, **options
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,16 +73,12 @@ class Command(CommandArguments):
 | 
			
		|||
            elif file_extension == ".json":
 | 
			
		||||
                self.save_json_file(out, schema_dict, indent)
 | 
			
		||||
            else:
 | 
			
		||||
                raise CommandError(
 | 
			
		||||
                    'Unrecognised file format "{}"'.format(file_extension)
 | 
			
		||||
                )
 | 
			
		||||
                raise CommandError(f'Unrecognised file format "{file_extension}"')
 | 
			
		||||
 | 
			
		||||
            style = getattr(self, "style", None)
 | 
			
		||||
            success = getattr(style, "SUCCESS", lambda x: x)
 | 
			
		||||
 | 
			
		||||
            self.stdout.write(
 | 
			
		||||
                success("Successfully dumped GraphQL schema to {}".format(out))
 | 
			
		||||
            )
 | 
			
		||||
            self.stdout.write(success(f"Successfully dumped GraphQL schema to {out}"))
 | 
			
		||||
 | 
			
		||||
    def handle(self, *args, **options):
 | 
			
		||||
        options_schema = options.get("schema")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
class Registry(object):
 | 
			
		||||
class Registry:
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self._registry = {}
 | 
			
		||||
        self._field_registry = {}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -114,7 +114,7 @@ class SerializerMutation(ClientIDMutation):
 | 
			
		|||
        _meta.fields = yank_fields_from_attrs(output_fields, _as=Field)
 | 
			
		||||
 | 
			
		||||
        input_fields = yank_fields_from_attrs(input_fields, _as=InputField)
 | 
			
		||||
        super(SerializerMutation, cls).__init_subclass_with_meta__(
 | 
			
		||||
        super().__init_subclass_with_meta__(
 | 
			
		||||
            _meta=_meta, input_fields=input_fields, **options
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,7 +72,7 @@ def convert_serializer_to_input_type(serializer_class):
 | 
			
		|||
        for name, field in serializer.fields.items()
 | 
			
		||||
    }
 | 
			
		||||
    ret_type = type(
 | 
			
		||||
        "{}Input".format(serializer.__class__.__name__),
 | 
			
		||||
        f"{serializer.__class__.__name__}Input",
 | 
			
		||||
        (graphene.InputObjectType,),
 | 
			
		||||
        items,
 | 
			
		||||
    )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,6 @@ This module provides the `graphene_settings` object, that is used to access
 | 
			
		|||
Graphene settings, checking for user settings first, then falling
 | 
			
		||||
back to the defaults.
 | 
			
		||||
"""
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.test.signals import setting_changed
 | 
			
		||||
| 
						 | 
				
			
			@ -77,7 +76,7 @@ def import_from_string(val, setting_name):
 | 
			
		|||
        module = importlib.import_module(module_path)
 | 
			
		||||
        return getattr(module, class_name)
 | 
			
		||||
    except (ImportError, AttributeError) as e:
 | 
			
		||||
        msg = "Could not import '%s' for Graphene setting '%s'. %s: %s." % (
 | 
			
		||||
        msg = "Could not import '{}' for Graphene setting '{}'. {}: {}.".format(
 | 
			
		||||
            val,
 | 
			
		||||
            setting_name,
 | 
			
		||||
            e.__class__.__name__,
 | 
			
		||||
| 
						 | 
				
			
			@ -86,7 +85,7 @@ def import_from_string(val, setting_name):
 | 
			
		|||
        raise ImportError(msg)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GrapheneSettings(object):
 | 
			
		||||
class GrapheneSettings:
 | 
			
		||||
    """
 | 
			
		||||
    A settings object, that allows API settings to be accessed as properties.
 | 
			
		||||
    For example:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
from __future__ import absolute_import
 | 
			
		||||
 | 
			
		||||
from django.db import models
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -37,7 +35,7 @@ class Film(models.Model):
 | 
			
		|||
 | 
			
		||||
class DoeReporterManager(models.Manager):
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return super(DoeReporterManager, self).get_queryset().filter(last_name="Doe")
 | 
			
		||||
        return super().get_queryset().filter(last_name="Doe")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Reporter(models.Model):
 | 
			
		||||
| 
						 | 
				
			
			@ -57,7 +55,7 @@ class Reporter(models.Model):
 | 
			
		|||
    )
 | 
			
		||||
 | 
			
		||||
    def __str__(self):  # __unicode__ on Python 2
 | 
			
		||||
        return "%s %s" % (self.first_name, self.last_name)
 | 
			
		||||
        return f"{self.first_name} {self.last_name}"
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +65,7 @@ class Reporter(models.Model):
 | 
			
		|||
        when a CNNReporter is pulled from the database, it is still
 | 
			
		||||
        of type Reporter. This was added to test proxy model support.
 | 
			
		||||
        """
 | 
			
		||||
        super(Reporter, self).__init__(*args, **kwargs)
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        if self.reporter_type == 2:  # quick and dirty way without enums
 | 
			
		||||
            self.__class__ = CNNReporter
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -77,7 +75,7 @@ class Reporter(models.Model):
 | 
			
		|||
 | 
			
		||||
class CNNReporterManager(models.Manager):
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return super(CNNReporterManager, self).get_queryset().filter(reporter_type=2)
 | 
			
		||||
        return super().get_queryset().filter(reporter_type=2)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CNNReporter(Reporter):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@ from textwrap import dedent
 | 
			
		|||
 | 
			
		||||
from django.core import management
 | 
			
		||||
from io import StringIO
 | 
			
		||||
from mock import mock_open, patch
 | 
			
		||||
from unittest.mock import mock_open, patch
 | 
			
		||||
 | 
			
		||||
from graphene import ObjectType, Schema, String
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1151,9 +1151,9 @@ def test_connection_should_limit_after_to_list_length():
 | 
			
		|||
 | 
			
		||||
REPORTERS = [
 | 
			
		||||
    dict(
 | 
			
		||||
        first_name="First {}".format(i),
 | 
			
		||||
        last_name="Last {}".format(i),
 | 
			
		||||
        email="johndoe+{}@example.com".format(i),
 | 
			
		||||
        first_name=f"First {i}",
 | 
			
		||||
        last_name=f"Last {i}",
 | 
			
		||||
        email=f"johndoe+{i}@example.com",
 | 
			
		||||
        a_choice=1,
 | 
			
		||||
    )
 | 
			
		||||
    for i in range(6)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@ from textwrap import dedent
 | 
			
		|||
 | 
			
		||||
import pytest
 | 
			
		||||
from django.db import models
 | 
			
		||||
from mock import patch
 | 
			
		||||
from unittest.mock import patch
 | 
			
		||||
 | 
			
		||||
from graphene import Connection, Field, Interface, ObjectType, Schema, String
 | 
			
		||||
from graphene.relay import Node
 | 
			
		||||
| 
						 | 
				
			
			@ -104,7 +104,7 @@ def test_django_objecttype_with_custom_meta():
 | 
			
		|||
        @classmethod
 | 
			
		||||
        def __init_subclass_with_meta__(cls, **options):
 | 
			
		||||
            options.setdefault("_meta", ArticleTypeOptions(cls))
 | 
			
		||||
            super(ArticleType, cls).__init_subclass_with_meta__(**options)
 | 
			
		||||
            super().__init_subclass_with_meta__(**options)
 | 
			
		||||
 | 
			
		||||
    class Article(ArticleType):
 | 
			
		||||
        class Meta:
 | 
			
		||||
| 
						 | 
				
			
			@ -484,7 +484,7 @@ def test_django_objecttype_neither_fields_nor_exclude():
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
def custom_enum_name(field):
 | 
			
		||||
    return "CustomEnum{}".format(field.name.title())
 | 
			
		||||
    return f"CustomEnum{field.name.title()}"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestDjangoObjectType:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@ import json
 | 
			
		|||
 | 
			
		||||
import pytest
 | 
			
		||||
from django.utils.translation import gettext_lazy
 | 
			
		||||
from mock import patch
 | 
			
		||||
from unittest.mock import patch
 | 
			
		||||
 | 
			
		||||
from ..utils import camelize, get_model_fields, GraphQLTestCase
 | 
			
		||||
from .models import Film, Reporter
 | 
			
		||||
| 
						 | 
				
			
			@ -11,11 +11,11 @@ from ..utils.testing import graphql_query
 | 
			
		|||
 | 
			
		||||
def test_get_model_fields_no_duplication():
 | 
			
		||||
    reporter_fields = get_model_fields(Reporter)
 | 
			
		||||
    reporter_name_set = set([field[0] for field in reporter_fields])
 | 
			
		||||
    reporter_name_set = {field[0] for field in reporter_fields}
 | 
			
		||||
    assert len(reporter_fields) == len(reporter_name_set)
 | 
			
		||||
 | 
			
		||||
    film_fields = get_model_fields(Film)
 | 
			
		||||
    film_name_set = set([field[0] for field in film_fields])
 | 
			
		||||
    film_name_set = {field[0] for field in film_fields}
 | 
			
		||||
    assert len(film_fields) == len(film_name_set)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@ import json
 | 
			
		|||
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
from mock import patch
 | 
			
		||||
from unittest.mock import patch
 | 
			
		||||
 | 
			
		||||
from django.db import connection
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -507,7 +507,7 @@ def test_handles_invalid_json_bodies(client):
 | 
			
		|||
 | 
			
		||||
def test_handles_django_request_error(client, monkeypatch):
 | 
			
		||||
    def mocked_read(*args):
 | 
			
		||||
        raise IOError("foo-bar")
 | 
			
		||||
        raise OSError("foo-bar")
 | 
			
		||||
 | 
			
		||||
    monkeypatch.setattr("django.http.request.HttpRequest.read", mocked_read)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -168,10 +168,8 @@ class DjangoObjectType(ObjectType):
 | 
			
		|||
 | 
			
		||||
        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"
 | 
			
		||||
                )
 | 
			
		||||
                "Can only set filter_fields or filterset_class if "
 | 
			
		||||
                "Django-Filter is installed"
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        assert not (fields and exclude), (
 | 
			
		||||
| 
						 | 
				
			
			@ -228,7 +226,7 @@ class DjangoObjectType(ObjectType):
 | 
			
		|||
 | 
			
		||||
        if use_connection is None and interfaces:
 | 
			
		||||
            use_connection = any(
 | 
			
		||||
                (issubclass(interface, Node) for interface in interfaces)
 | 
			
		||||
                issubclass(interface, Node) for interface in interfaces
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        if use_connection and not connection:
 | 
			
		||||
| 
						 | 
				
			
			@ -255,7 +253,7 @@ class DjangoObjectType(ObjectType):
 | 
			
		|||
        _meta.fields = django_fields
 | 
			
		||||
        _meta.connection = connection
 | 
			
		||||
 | 
			
		||||
        super(DjangoObjectType, cls).__init_subclass_with_meta__(
 | 
			
		||||
        super().__init_subclass_with_meta__(
 | 
			
		||||
            _meta=_meta, interfaces=interfaces, **options
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,7 +63,7 @@ def graphql_query(
 | 
			
		|||
    return resp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GraphQLTestMixin(object):
 | 
			
		||||
class GraphQLTestMixin:
 | 
			
		||||
    """
 | 
			
		||||
    Based on: https://www.sam.today/blog/testing-graphql-with-graphene-django/
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ class HttpError(Exception):
 | 
			
		|||
    def __init__(self, response, message=None, *args, **kwargs):
 | 
			
		||||
        self.response = response
 | 
			
		||||
        self.message = message = message or response.content.decode()
 | 
			
		||||
        super(HttpError, self).__init__(message, *args, **kwargs)
 | 
			
		||||
        super().__init__(message, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_accepted_content_types(request):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user