mirror of
https://github.com/graphql-python/graphene-django.git
synced 2024-11-21 17:16:56 +03:00
👷 Add pre-commit (#1336)
* 🔧 Add pre-commit config Similar to graphene and graphene-sqlalchemy * ⬆ Bump black * 👷 Lint on CI * ⬆ Bump flake8-black * 🔧 Keep excluding migrations * ⬆ Bump flake8 * 🔧 Remove black and flake8 from tox config * ⬆ Update pre-commit versions * Upgrade syntax to python 3.7+ * Format with pre-commit dedent docs/schema.py to allow formatting * Fix tests on python 3.7
This commit is contained in:
parent
f24cbd5148
commit
4517e32224
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:**
|
* **Please tell us about your environment:**
|
||||||
|
|
||||||
- Version:
|
- Version:
|
||||||
- Platform:
|
- Platform:
|
||||||
|
|
||||||
* **Other information** (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow)
|
* **Other information** (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow)
|
||||||
|
|
4
.github/workflows/lint.yml
vendored
4
.github/workflows/lint.yml
vendored
|
@ -16,7 +16,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install tox
|
pip install tox
|
||||||
- name: Run lint 💅
|
- name: Run pre-commit 💅
|
||||||
run: tox
|
run: tox
|
||||||
env:
|
env:
|
||||||
TOXENV: flake8
|
TOXENV: pre-commit
|
||||||
|
|
30
.pre-commit-config.yaml
Normal file
30
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
default_language_version:
|
||||||
|
python: python3.9
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.3.0
|
||||||
|
hooks:
|
||||||
|
- id: check-merge-conflict
|
||||||
|
- id: check-json
|
||||||
|
- id: check-yaml
|
||||||
|
- id: debug-statements
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
exclude: ^docs/.*$
|
||||||
|
- id: pretty-format-json
|
||||||
|
args:
|
||||||
|
- --autofix
|
||||||
|
- id: trailing-whitespace
|
||||||
|
exclude: README.md
|
||||||
|
- repo: https://github.com/asottile/pyupgrade
|
||||||
|
rev: v2.37.3
|
||||||
|
hooks:
|
||||||
|
- id: pyupgrade
|
||||||
|
args: [--py37-plus]
|
||||||
|
- repo: https://github.com/psf/black
|
||||||
|
rev: 22.6.0
|
||||||
|
hooks:
|
||||||
|
- id: black
|
||||||
|
- repo: https://github.com/PyCQA/flake8
|
||||||
|
rev: 5.0.4
|
||||||
|
hooks:
|
||||||
|
- id: flake8
|
|
@ -59,4 +59,4 @@ Then to produce a HTML version of the documentation:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make html
|
make html
|
||||||
```
|
```
|
||||||
|
|
|
@ -3,4 +3,4 @@ recursive-include graphene_django/templates *
|
||||||
recursive-include graphene_django/static *
|
recursive-include graphene_django/static *
|
||||||
|
|
||||||
include examples/cookbook/cookbook/ingredients/fixtures/ingredients.json
|
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
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -13,7 +13,7 @@ tests:
|
||||||
|
|
||||||
.PHONY: format ## Format code
|
.PHONY: format ## Format code
|
||||||
format:
|
format:
|
||||||
black --exclude "/migrations/" graphene_django examples setup.py
|
black graphene_django examples setup.py
|
||||||
|
|
||||||
.PHONY: lint ## Lint code
|
.PHONY: lint ## Lint code
|
||||||
lint:
|
lint:
|
||||||
|
|
|
@ -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 CategoryType(DjangoObjectType):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Category
|
model = Category
|
||||||
fields = '__all__'
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
class IngredientType(DjangoObjectType):
|
class IngredientType(DjangoObjectType):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Ingredient
|
model = Ingredient
|
||||||
fields = '__all__'
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
class Query(object):
|
class Query:
|
||||||
category = graphene.Field(CategoryType,
|
category = graphene.Field(CategoryType, id=graphene.Int(), name=graphene.String())
|
||||||
id=graphene.Int(),
|
all_categories = graphene.List(CategoryType)
|
||||||
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,
|
def resolve_all_categories(self, info, **kwargs):
|
||||||
id=graphene.Int(),
|
return Category.objects.all()
|
||||||
name=graphene.String())
|
|
||||||
all_ingredients = graphene.List(IngredientType)
|
|
||||||
|
|
||||||
def resolve_all_categories(self, info, **kwargs):
|
def resolve_all_ingredients(self, info, **kwargs):
|
||||||
return Category.objects.all()
|
return Ingredient.objects.all()
|
||||||
|
|
||||||
def resolve_all_ingredients(self, info, **kwargs):
|
def resolve_category(self, info, **kwargs):
|
||||||
return Ingredient.objects.all()
|
id = kwargs.get("id")
|
||||||
|
name = kwargs.get("name")
|
||||||
|
|
||||||
def resolve_category(self, info, **kwargs):
|
if id is not None:
|
||||||
id = kwargs.get('id')
|
return Category.objects.get(pk=id)
|
||||||
name = kwargs.get('name')
|
|
||||||
|
|
||||||
if id is not None:
|
if name is not None:
|
||||||
return Category.objects.get(pk=id)
|
return Category.objects.get(name=name)
|
||||||
|
|
||||||
if name is not None:
|
return None
|
||||||
return Category.objects.get(name=name)
|
|
||||||
|
|
||||||
return None
|
def resolve_ingredient(self, info, **kwargs):
|
||||||
|
id = kwargs.get("id")
|
||||||
|
name = kwargs.get("name")
|
||||||
|
|
||||||
def resolve_ingredient(self, info, **kwargs):
|
if id is not None:
|
||||||
id = kwargs.get('id')
|
return Ingredient.objects.get(pk=id)
|
||||||
name = kwargs.get('name')
|
|
||||||
|
|
||||||
if id is not None:
|
if name is not None:
|
||||||
return Ingredient.objects.get(pk=id)
|
return Ingredient.objects.get(name=name)
|
||||||
|
|
||||||
if name is not None:
|
return None
|
||||||
return Ingredient.objects.get(name=name)
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
|
@ -85,8 +85,8 @@ Make sure the app name in ``cookbook.ingredients.apps.IngredientsConfig`` is set
|
||||||
# cookbook/ingredients/apps.py
|
# cookbook/ingredients/apps.py
|
||||||
|
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class IngredientsConfig(AppConfig):
|
class IngredientsConfig(AppConfig):
|
||||||
default_auto_field = 'django.db.models.BigAutoField'
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
name = 'cookbook.ingredients'
|
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
|
# Generated by Django 1.9 on 2015-12-04 18:15
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -10,24 +8,46 @@ class Migration(migrations.Migration):
|
||||||
|
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = []
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Category',
|
name="Category",
|
||||||
fields=[
|
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(
|
migrations.CreateModel(
|
||||||
name='Ingredient',
|
name="Ingredient",
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
(
|
||||||
('name', models.CharField(max_length=100)),
|
"id",
|
||||||
('notes', models.TextField()),
|
models.AutoField(
|
||||||
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ingredients', to='ingredients.Category')),
|
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
|
# Generated by Django 1.9 on 2016-11-04 00:50
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
@ -8,13 +6,13 @@ from django.db import migrations, models
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('ingredients', '0001_initial'),
|
("ingredients", "0001_initial"),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='ingredient',
|
model_name="ingredient",
|
||||||
name='notes',
|
name="notes",
|
||||||
field=models.TextField(blank=True, null=True),
|
field=models.TextField(blank=True, null=True),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -6,12 +6,12 @@ from django.db import migrations
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('ingredients', '0002_auto_20161104_0050'),
|
("ingredients", "0002_auto_20161104_0050"),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AlterModelOptions(
|
migrations.AlterModelOptions(
|
||||||
name='category',
|
name="category",
|
||||||
options={'verbose_name_plural': 'Categories'},
|
options={"verbose_name_plural": "Categories"},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -16,7 +16,7 @@ class IngredientType(DjangoObjectType):
|
||||||
fields = "__all__"
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
class Query(object):
|
class Query:
|
||||||
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)
|
all_categories = graphene.List(CategoryType)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.9 on 2015-12-04 18:20
|
# Generated by Django 1.9 on 2015-12-04 18:20
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -11,26 +9,62 @@ class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('ingredients', '0001_initial'),
|
("ingredients", "0001_initial"),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Recipe',
|
name="Recipe",
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
(
|
||||||
('title', models.CharField(max_length=100)),
|
"id",
|
||||||
('instructions', models.TextField()),
|
models.AutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("title", models.CharField(max_length=100)),
|
||||||
|
("instructions", models.TextField()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='RecipeIngredient',
|
name="RecipeIngredient",
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
(
|
||||||
('amount', models.FloatField()),
|
"id",
|
||||||
('unit', models.CharField(choices=[('kg', 'Kilograms'), ('l', 'Litres'), ('', 'Units')], max_length=20)),
|
models.AutoField(
|
||||||
('ingredient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='used_by', to='ingredients.Ingredient')),
|
auto_created=True,
|
||||||
('recipes', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='amounts', to='recipes.Recipe')),
|
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
|
# Generated by Django 1.9 on 2016-11-04 01:06
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
@ -8,18 +6,26 @@ from django.db import migrations, models
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('recipes', '0001_initial'),
|
("recipes", "0001_initial"),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.RenameField(
|
migrations.RenameField(
|
||||||
model_name='recipeingredient',
|
model_name="recipeingredient",
|
||||||
old_name='recipes',
|
old_name="recipes",
|
||||||
new_name='recipe',
|
new_name="recipe",
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='recipeingredient',
|
model_name="recipeingredient",
|
||||||
name='unit',
|
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),
|
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):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('recipes', '0002_auto_20161104_0106'),
|
("recipes", "0002_auto_20161104_0106"),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='recipeingredient',
|
model_name="recipeingredient",
|
||||||
name='unit',
|
name="unit",
|
||||||
field=models.CharField(choices=[('unit', 'Units'), ('kg', 'Kilograms'), ('l', 'Litres'), ('st', 'Shots')], max_length=20),
|
field=models.CharField(
|
||||||
|
choices=[
|
||||||
|
("unit", "Units"),
|
||||||
|
("kg", "Kilograms"),
|
||||||
|
("l", "Litres"),
|
||||||
|
("st", "Shots"),
|
||||||
|
],
|
||||||
|
max_length=20,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -16,7 +16,7 @@ class RecipeIngredientType(DjangoObjectType):
|
||||||
fields = "__all__"
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
class Query(object):
|
class Query:
|
||||||
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)
|
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
|
# Generated by Django 1.9 on 2015-12-04 18:15
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -10,24 +8,46 @@ class Migration(migrations.Migration):
|
||||||
|
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = []
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Category',
|
name="Category",
|
||||||
fields=[
|
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(
|
migrations.CreateModel(
|
||||||
name='Ingredient',
|
name="Ingredient",
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
(
|
||||||
('name', models.CharField(max_length=100)),
|
"id",
|
||||||
('notes', models.TextField()),
|
models.AutoField(
|
||||||
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ingredients', to='ingredients.Category')),
|
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
|
# Generated by Django 1.9 on 2016-11-04 00:50
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
@ -8,13 +6,13 @@ from django.db import migrations, models
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('ingredients', '0001_initial'),
|
("ingredients", "0001_initial"),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='ingredient',
|
model_name="ingredient",
|
||||||
name='notes',
|
name="notes",
|
||||||
field=models.TextField(blank=True, null=True),
|
field=models.TextField(blank=True, null=True),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -28,7 +28,7 @@ class IngredientNode(DjangoObjectType):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Query(object):
|
class Query:
|
||||||
category = Node.Field(CategoryNode)
|
category = Node.Field(CategoryNode)
|
||||||
all_categories = DjangoFilterConnectionField(CategoryNode)
|
all_categories = DjangoFilterConnectionField(CategoryNode)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.9 on 2015-12-04 18:20
|
# Generated by Django 1.9 on 2015-12-04 18:20
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -11,26 +9,62 @@ class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('ingredients', '0001_initial'),
|
("ingredients", "0001_initial"),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Recipe',
|
name="Recipe",
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
(
|
||||||
('title', models.CharField(max_length=100)),
|
"id",
|
||||||
('instructions', models.TextField()),
|
models.AutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("title", models.CharField(max_length=100)),
|
||||||
|
("instructions", models.TextField()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='RecipeIngredient',
|
name="RecipeIngredient",
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
(
|
||||||
('amount', models.FloatField()),
|
"id",
|
||||||
('unit', models.CharField(choices=[('kg', 'Kilograms'), ('l', 'Litres'), ('', 'Units')], max_length=20)),
|
models.AutoField(
|
||||||
('ingredient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='used_by', to='ingredients.Ingredient')),
|
auto_created=True,
|
||||||
('recipes', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='amounts', to='recipes.Recipe')),
|
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
|
# Generated by Django 1.9 on 2016-11-04 01:06
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
@ -8,18 +6,26 @@ from django.db import migrations, models
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('recipes', '0001_initial'),
|
("recipes", "0001_initial"),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.RenameField(
|
migrations.RenameField(
|
||||||
model_name='recipeingredient',
|
model_name="recipeingredient",
|
||||||
old_name='recipes',
|
old_name="recipes",
|
||||||
new_name='recipe',
|
new_name="recipe",
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='recipeingredient',
|
model_name="recipeingredient",
|
||||||
name='unit',
|
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),
|
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)
|
recipe = Node.Field(RecipeNode)
|
||||||
all_recipes = DjangoFilterConnectionField(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
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class MissingType(object):
|
class MissingType:
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -74,8 +74,7 @@ def get_choices(choices):
|
||||||
choices = choices.items()
|
choices = choices.items()
|
||||||
for value, help_text in choices:
|
for value, help_text in choices:
|
||||||
if isinstance(help_text, (tuple, list)):
|
if isinstance(help_text, (tuple, list)):
|
||||||
for choice in get_choices(help_text):
|
yield from get_choices(help_text)
|
||||||
yield choice
|
|
||||||
else:
|
else:
|
||||||
name = convert_choice_name(value)
|
name = convert_choice_name(value)
|
||||||
while name in converted_names:
|
while name in converted_names:
|
||||||
|
@ -92,7 +91,7 @@ def convert_choices_to_named_enum_with_descriptions(name, choices):
|
||||||
named_choices = [(c[0], c[1]) for c in choices]
|
named_choices = [(c[0], c[1]) for c in choices]
|
||||||
named_choices_descriptions = {c[0]: c[2] for c in choices}
|
named_choices_descriptions = {c[0]: c[2] for c in choices}
|
||||||
|
|
||||||
class EnumWithDescriptionsType(object):
|
class EnumWithDescriptionsType:
|
||||||
@property
|
@property
|
||||||
def description(self):
|
def description(self):
|
||||||
return str(named_choices_descriptions[self.name])
|
return str(named_choices_descriptions[self.name])
|
||||||
|
@ -109,7 +108,7 @@ def generate_enum_name(django_model_meta, field):
|
||||||
)
|
)
|
||||||
name = custom_func(field)
|
name = custom_func(field)
|
||||||
elif graphene_settings.DJANGO_CHOICE_FIELD_ENUM_V2_NAMING is True:
|
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:
|
else:
|
||||||
name = "{app_label}{object_name}{field_name}Choices".format(
|
name = "{app_label}{object_name}{field_name}Choices".format(
|
||||||
app_label=to_camel_case(django_model_meta.app_label.title()),
|
app_label=to_camel_case(django_model_meta.app_label.title()),
|
||||||
|
@ -155,7 +154,9 @@ def get_django_field_description(field):
|
||||||
@singledispatch
|
@singledispatch
|
||||||
def convert_django_field(field, registry=None):
|
def convert_django_field(field, registry=None):
|
||||||
raise Exception(
|
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
|
from .types import DjangoDebug
|
||||||
|
|
||||||
|
|
||||||
class DjangoDebugContext(object):
|
class DjangoDebugContext:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.debug_promise = None
|
self.debug_promise = None
|
||||||
self.promises = []
|
self.promises = []
|
||||||
|
@ -46,7 +46,7 @@ class DjangoDebugContext(object):
|
||||||
unwrap_cursor(connection)
|
unwrap_cursor(connection)
|
||||||
|
|
||||||
|
|
||||||
class DjangoDebugMiddleware(object):
|
class DjangoDebugMiddleware:
|
||||||
def resolve(self, next, root, info, **args):
|
def resolve(self, next, root, info, **args):
|
||||||
context = info.context
|
context = info.context
|
||||||
django_debug = getattr(context, "django_debug", None)
|
django_debug = getattr(context, "django_debug", None)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
# Code obtained from django-debug-toolbar sql panel tracking
|
# Code obtained from django-debug-toolbar sql panel tracking
|
||||||
from __future__ import absolute_import, unicode_literals
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from threading import local
|
from threading import local
|
||||||
|
@ -50,7 +49,7 @@ def unwrap_cursor(connection):
|
||||||
del connection._graphene_cursor
|
del connection._graphene_cursor
|
||||||
|
|
||||||
|
|
||||||
class ExceptionCursorWrapper(object):
|
class ExceptionCursorWrapper:
|
||||||
"""
|
"""
|
||||||
Wraps a cursor and raises an exception on any operation.
|
Wraps a cursor and raises an exception on any operation.
|
||||||
Used in Templates panel.
|
Used in Templates panel.
|
||||||
|
@ -63,7 +62,7 @@ class ExceptionCursorWrapper(object):
|
||||||
raise SQLQueryTriggered()
|
raise SQLQueryTriggered()
|
||||||
|
|
||||||
|
|
||||||
class NormalCursorWrapper(object):
|
class NormalCursorWrapper:
|
||||||
"""
|
"""
|
||||||
Wraps a cursor and logs queries.
|
Wraps a cursor and logs queries.
|
||||||
"""
|
"""
|
||||||
|
@ -85,7 +84,7 @@ class NormalCursorWrapper(object):
|
||||||
if not params:
|
if not params:
|
||||||
return params
|
return params
|
||||||
if isinstance(params, dict):
|
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))
|
return list(map(self._quote_expr, params))
|
||||||
|
|
||||||
def _decode(self, param):
|
def _decode(self, param):
|
||||||
|
|
|
@ -8,7 +8,7 @@ from ..middleware import DjangoDebugMiddleware
|
||||||
from ..types import DjangoDebug
|
from ..types import DjangoDebug
|
||||||
|
|
||||||
|
|
||||||
class context(object):
|
class context:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ class DjangoListField(Field):
|
||||||
_type = _type.of_type
|
_type = _type.of_type
|
||||||
|
|
||||||
# Django would never return a Set of None vvvvvvv
|
# 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(
|
assert issubclass(
|
||||||
self._underlying_type, DjangoObjectType
|
self._underlying_type, DjangoObjectType
|
||||||
|
@ -63,7 +63,7 @@ class DjangoListField(Field):
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
def wrap_resolve(self, parent_resolver):
|
def wrap_resolve(self, parent_resolver):
|
||||||
resolver = super(DjangoListField, self).wrap_resolve(parent_resolver)
|
resolver = super().wrap_resolve(parent_resolver)
|
||||||
_type = self.type
|
_type = self.type
|
||||||
if isinstance(_type, NonNull):
|
if isinstance(_type, NonNull):
|
||||||
_type = _type.of_type
|
_type = _type.of_type
|
||||||
|
@ -87,7 +87,7 @@ class DjangoConnectionField(ConnectionField):
|
||||||
graphene_settings.RELAY_CONNECTION_ENFORCE_FIRST_OR_LAST,
|
graphene_settings.RELAY_CONNECTION_ENFORCE_FIRST_OR_LAST,
|
||||||
)
|
)
|
||||||
kwargs.setdefault("offset", Int())
|
kwargs.setdefault("offset", Int())
|
||||||
super(DjangoConnectionField, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def type(self):
|
def type(self):
|
||||||
|
|
|
@ -44,7 +44,7 @@ class DjangoFilterConnectionField(DjangoConnectionField):
|
||||||
self._filtering_args = None
|
self._filtering_args = None
|
||||||
self._extra_filter_meta = extra_filter_meta
|
self._extra_filter_meta = extra_filter_meta
|
||||||
self._base_args = None
|
self._base_args = None
|
||||||
super(DjangoFilterConnectionField, self).__init__(type_, *args, **kwargs)
|
super().__init__(type_, *args, **kwargs)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def args(self):
|
def args(self):
|
||||||
|
@ -90,9 +90,7 @@ class DjangoFilterConnectionField(DjangoConnectionField):
|
||||||
kwargs[k] = convert_enum(v)
|
kwargs[k] = convert_enum(v)
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
qs = super(DjangoFilterConnectionField, cls).resolve_queryset(
|
qs = super().resolve_queryset(connection, iterable, info, args)
|
||||||
connection, iterable, info, args
|
|
||||||
)
|
|
||||||
|
|
||||||
filterset = filterset_class(
|
filterset = filterset_class(
|
||||||
data=filter_kwargs(), queryset=qs, request=info.context
|
data=filter_kwargs(), queryset=qs, request=info.context
|
||||||
|
|
|
@ -22,6 +22,6 @@ class ArrayFilter(TypedFilter):
|
||||||
return qs
|
return qs
|
||||||
if self.distinct:
|
if self.distinct:
|
||||||
qs = qs.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})
|
qs = self.get_method(qs)(**{lookup: value})
|
||||||
return qs
|
return qs
|
||||||
|
|
|
@ -17,7 +17,7 @@ class GlobalIDFilter(Filter):
|
||||||
_id = None
|
_id = None
|
||||||
if value is not None:
|
if value is not None:
|
||||||
_, _id = from_global_id(value)
|
_, _id = from_global_id(value)
|
||||||
return super(GlobalIDFilter, self).filter(qs, _id)
|
return super().filter(qs, _id)
|
||||||
|
|
||||||
|
|
||||||
class GlobalIDMultipleChoiceFilter(MultipleChoiceFilter):
|
class GlobalIDMultipleChoiceFilter(MultipleChoiceFilter):
|
||||||
|
@ -25,4 +25,4 @@ class GlobalIDMultipleChoiceFilter(MultipleChoiceFilter):
|
||||||
|
|
||||||
def filter(self, qs, value):
|
def filter(self, qs, value):
|
||||||
gids = [from_global_id(v)[1] for v in 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:
|
else:
|
||||||
return qs.none()
|
return qs.none()
|
||||||
else:
|
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):
|
def __init__(self, input_type=None, *args, **kwargs):
|
||||||
self._input_type = input_type
|
self._input_type = input_type
|
||||||
super(TypedFilter, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def input_type(self):
|
def input_type(self):
|
||||||
|
|
|
@ -31,7 +31,7 @@ class GrapheneFilterSetMixin(BaseFilterSet):
|
||||||
def setup_filterset(filterset_class):
|
def setup_filterset(filterset_class):
|
||||||
"""Wrap a provided filterset in Graphene-specific functionality"""
|
"""Wrap a provided filterset in Graphene-specific functionality"""
|
||||||
return type(
|
return type(
|
||||||
"Graphene{}".format(filterset_class.__name__),
|
f"Graphene{filterset_class.__name__}",
|
||||||
(filterset_class, GrapheneFilterSetMixin),
|
(filterset_class, GrapheneFilterSetMixin),
|
||||||
{},
|
{},
|
||||||
)
|
)
|
||||||
|
@ -40,7 +40,7 @@ def setup_filterset(filterset_class):
|
||||||
def custom_filterset_factory(model, filterset_base_class=FilterSet, **meta):
|
def custom_filterset_factory(model, filterset_base_class=FilterSet, **meta):
|
||||||
"""Create a filterset for the given model using the provided meta data"""
|
"""Create a filterset for the given model using the provided meta data"""
|
||||||
meta.update({"model": model})
|
meta.update({"model": model})
|
||||||
meta_class = type(str("Meta"), (object,), meta)
|
meta_class = type("Meta", (object,), meta)
|
||||||
filterset = type(
|
filterset = type(
|
||||||
str("%sFilterSet" % model._meta.object_name),
|
str("%sFilterSet" % model._meta.object_name),
|
||||||
(filterset_base_class, GrapheneFilterSetMixin),
|
(filterset_base_class, GrapheneFilterSetMixin),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from django.db import models
|
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("_")]
|
actual = [name for name in args if name not in ignore and not name.startswith("_")]
|
||||||
assert set(arguments) == set(
|
assert set(arguments) == set(
|
||||||
actual
|
actual
|
||||||
), "Expected arguments ({}) did not match actual ({})".format(arguments, actual)
|
), f"Expected arguments ({arguments}) did not match actual ({actual})"
|
||||||
|
|
||||||
|
|
||||||
def assert_orderable(field):
|
def assert_orderable(field):
|
||||||
|
@ -141,7 +141,7 @@ def test_filter_shortcut_filterset_context():
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def qs(self):
|
def qs(self):
|
||||||
qs = super(ArticleContextFilter, self).qs
|
qs = super().qs
|
||||||
return qs.filter(reporter=self.request.reporter)
|
return qs.filter(reporter=self.request.reporter)
|
||||||
|
|
||||||
class Query(ObjectType):
|
class Query(ObjectType):
|
||||||
|
@ -166,7 +166,7 @@ def test_filter_shortcut_filterset_context():
|
||||||
editor=r2,
|
editor=r2,
|
||||||
)
|
)
|
||||||
|
|
||||||
class context(object):
|
class context:
|
||||||
reporter = r2
|
reporter = r2
|
||||||
|
|
||||||
query = """
|
query = """
|
||||||
|
|
|
@ -349,19 +349,19 @@ def test_fk_id_in_filter(query):
|
||||||
schema = Schema(query=query)
|
schema = Schema(query=query)
|
||||||
|
|
||||||
query = """
|
query = """
|
||||||
query {
|
query {{
|
||||||
articles (reporter_In: [%s, %s]) {
|
articles (reporter_In: [{}, {}]) {{
|
||||||
edges {
|
edges {{
|
||||||
node {
|
node {{
|
||||||
headline
|
headline
|
||||||
reporter {
|
reporter {{
|
||||||
lastName
|
lastName
|
||||||
}
|
}}
|
||||||
}
|
}}
|
||||||
}
|
}}
|
||||||
}
|
}}
|
||||||
}
|
}}
|
||||||
""" % (
|
""".format(
|
||||||
john_doe.id,
|
john_doe.id,
|
||||||
jean_bon.id,
|
jean_bon.id,
|
||||||
)
|
)
|
||||||
|
|
|
@ -98,7 +98,7 @@ def test_typed_filter_schema(schema):
|
||||||
)
|
)
|
||||||
|
|
||||||
for filter_field, gql_type in filters.items():
|
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):
|
def test_typed_filters_work(schema):
|
||||||
|
|
|
@ -95,7 +95,7 @@ class DjangoFormMutation(BaseDjangoFormMutation):
|
||||||
_meta.fields = yank_fields_from_attrs(output_fields, _as=Field)
|
_meta.fields = yank_fields_from_attrs(output_fields, _as=Field)
|
||||||
|
|
||||||
input_fields = yank_fields_from_attrs(input_fields, _as=InputField)
|
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
|
_meta=_meta, input_fields=input_fields, **options
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ class DjangoModelFormMutation(BaseDjangoFormMutation):
|
||||||
return_field_name=None,
|
return_field_name=None,
|
||||||
only_fields=(),
|
only_fields=(),
|
||||||
exclude_fields=(),
|
exclude_fields=(),
|
||||||
**options
|
**options,
|
||||||
):
|
):
|
||||||
|
|
||||||
if not form_class:
|
if not form_class:
|
||||||
|
@ -147,7 +147,7 @@ class DjangoModelFormMutation(BaseDjangoFormMutation):
|
||||||
registry = get_global_registry()
|
registry = get_global_registry()
|
||||||
model_type = registry.get_type_for_model(model)
|
model_type = registry.get_type_for_model(model)
|
||||||
if not model_type:
|
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:
|
if not return_field_name:
|
||||||
model_name = model.__name__
|
model_name = model.__name__
|
||||||
|
@ -163,7 +163,7 @@ class DjangoModelFormMutation(BaseDjangoFormMutation):
|
||||||
_meta.fields = yank_fields_from_attrs(output_fields, _as=Field)
|
_meta.fields = yank_fields_from_attrs(output_fields, _as=Field)
|
||||||
|
|
||||||
input_fields = yank_fields_from_attrs(input_fields, _as=InputField)
|
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
|
_meta=_meta, input_fields=input_fields, **options
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -73,16 +73,12 @@ class Command(CommandArguments):
|
||||||
elif file_extension == ".json":
|
elif file_extension == ".json":
|
||||||
self.save_json_file(out, schema_dict, indent)
|
self.save_json_file(out, schema_dict, indent)
|
||||||
else:
|
else:
|
||||||
raise CommandError(
|
raise CommandError(f'Unrecognised file format "{file_extension}"')
|
||||||
'Unrecognised file format "{}"'.format(file_extension)
|
|
||||||
)
|
|
||||||
|
|
||||||
style = getattr(self, "style", None)
|
style = getattr(self, "style", None)
|
||||||
success = getattr(style, "SUCCESS", lambda x: x)
|
success = getattr(style, "SUCCESS", lambda x: x)
|
||||||
|
|
||||||
self.stdout.write(
|
self.stdout.write(success(f"Successfully dumped GraphQL schema to {out}"))
|
||||||
success("Successfully dumped GraphQL schema to {}".format(out))
|
|
||||||
)
|
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
options_schema = options.get("schema")
|
options_schema = options.get("schema")
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Registry(object):
|
class Registry:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._registry = {}
|
self._registry = {}
|
||||||
self._field_registry = {}
|
self._field_registry = {}
|
||||||
|
|
|
@ -114,7 +114,7 @@ class SerializerMutation(ClientIDMutation):
|
||||||
_meta.fields = yank_fields_from_attrs(output_fields, _as=Field)
|
_meta.fields = yank_fields_from_attrs(output_fields, _as=Field)
|
||||||
|
|
||||||
input_fields = yank_fields_from_attrs(input_fields, _as=InputField)
|
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
|
_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()
|
for name, field in serializer.fields.items()
|
||||||
}
|
}
|
||||||
ret_type = type(
|
ret_type = type(
|
||||||
"{}Input".format(serializer.__class__.__name__),
|
f"{serializer.__class__.__name__}Input",
|
||||||
(graphene.InputObjectType,),
|
(graphene.InputObjectType,),
|
||||||
items,
|
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
|
Graphene settings, checking for user settings first, then falling
|
||||||
back to the defaults.
|
back to the defaults.
|
||||||
"""
|
"""
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.test.signals import setting_changed
|
from django.test.signals import setting_changed
|
||||||
|
@ -78,7 +77,7 @@ def import_from_string(val, setting_name):
|
||||||
module = importlib.import_module(module_path)
|
module = importlib.import_module(module_path)
|
||||||
return getattr(module, class_name)
|
return getattr(module, class_name)
|
||||||
except (ImportError, AttributeError) as e:
|
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,
|
val,
|
||||||
setting_name,
|
setting_name,
|
||||||
e.__class__.__name__,
|
e.__class__.__name__,
|
||||||
|
@ -87,7 +86,7 @@ def import_from_string(val, setting_name):
|
||||||
raise ImportError(msg)
|
raise ImportError(msg)
|
||||||
|
|
||||||
|
|
||||||
class GrapheneSettings(object):
|
class GrapheneSettings:
|
||||||
"""
|
"""
|
||||||
A settings object, that allows API settings to be accessed as properties.
|
A settings object, that allows API settings to be accessed as properties.
|
||||||
For example:
|
For example:
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
@ -37,7 +35,7 @@ class Film(models.Model):
|
||||||
|
|
||||||
class DoeReporterManager(models.Manager):
|
class DoeReporterManager(models.Manager):
|
||||||
def get_queryset(self):
|
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):
|
class Reporter(models.Model):
|
||||||
|
@ -57,7 +55,7 @@ class Reporter(models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self): # __unicode__ on Python 2
|
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):
|
def __init__(self, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -67,7 +65,7 @@ class Reporter(models.Model):
|
||||||
when a CNNReporter is pulled from the database, it is still
|
when a CNNReporter is pulled from the database, it is still
|
||||||
of type Reporter. This was added to test proxy model support.
|
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
|
if self.reporter_type == 2: # quick and dirty way without enums
|
||||||
self.__class__ = CNNReporter
|
self.__class__ = CNNReporter
|
||||||
|
|
||||||
|
@ -77,7 +75,7 @@ class Reporter(models.Model):
|
||||||
|
|
||||||
class CNNReporterManager(models.Manager):
|
class CNNReporterManager(models.Manager):
|
||||||
def get_queryset(self):
|
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):
|
class CNNReporter(Reporter):
|
||||||
|
|
|
@ -2,7 +2,7 @@ from textwrap import dedent
|
||||||
|
|
||||||
from django.core import management
|
from django.core import management
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from mock import mock_open, patch
|
from unittest.mock import mock_open, patch
|
||||||
|
|
||||||
from graphene import ObjectType, Schema, String
|
from graphene import ObjectType, Schema, String
|
||||||
|
|
||||||
|
|
|
@ -1151,9 +1151,9 @@ def test_connection_should_limit_after_to_list_length():
|
||||||
|
|
||||||
REPORTERS = [
|
REPORTERS = [
|
||||||
dict(
|
dict(
|
||||||
first_name="First {}".format(i),
|
first_name=f"First {i}",
|
||||||
last_name="Last {}".format(i),
|
last_name=f"Last {i}",
|
||||||
email="johndoe+{}@example.com".format(i),
|
email=f"johndoe+{i}@example.com",
|
||||||
a_choice=1,
|
a_choice=1,
|
||||||
)
|
)
|
||||||
for i in range(6)
|
for i in range(6)
|
||||||
|
|
|
@ -3,7 +3,7 @@ from textwrap import dedent
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.db import models
|
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 import Connection, Field, Interface, ObjectType, Schema, String
|
||||||
from graphene.relay import Node
|
from graphene.relay import Node
|
||||||
|
@ -104,7 +104,7 @@ def test_django_objecttype_with_custom_meta():
|
||||||
@classmethod
|
@classmethod
|
||||||
def __init_subclass_with_meta__(cls, **options):
|
def __init_subclass_with_meta__(cls, **options):
|
||||||
options.setdefault("_meta", ArticleTypeOptions(cls))
|
options.setdefault("_meta", ArticleTypeOptions(cls))
|
||||||
super(ArticleType, cls).__init_subclass_with_meta__(**options)
|
super().__init_subclass_with_meta__(**options)
|
||||||
|
|
||||||
class Article(ArticleType):
|
class Article(ArticleType):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -484,7 +484,7 @@ def test_django_objecttype_neither_fields_nor_exclude():
|
||||||
|
|
||||||
|
|
||||||
def custom_enum_name(field):
|
def custom_enum_name(field):
|
||||||
return "CustomEnum{}".format(field.name.title())
|
return f"CustomEnum{field.name.title()}"
|
||||||
|
|
||||||
|
|
||||||
class TestDjangoObjectType:
|
class TestDjangoObjectType:
|
||||||
|
|
|
@ -2,7 +2,7 @@ import json
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.utils.translation import gettext_lazy
|
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 ..utils import camelize, get_model_fields, GraphQLTestCase
|
||||||
from .models import Film, Reporter
|
from .models import Film, Reporter
|
||||||
|
@ -11,11 +11,11 @@ from ..utils.testing import graphql_query
|
||||||
|
|
||||||
def test_get_model_fields_no_duplication():
|
def test_get_model_fields_no_duplication():
|
||||||
reporter_fields = get_model_fields(Reporter)
|
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)
|
assert len(reporter_fields) == len(reporter_name_set)
|
||||||
|
|
||||||
film_fields = get_model_fields(Film)
|
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)
|
assert len(film_fields) == len(film_name_set)
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ def test_graphql_test_case_operation_name(post_mock):
|
||||||
tc._pre_setup()
|
tc._pre_setup()
|
||||||
tc.setUpClass()
|
tc.setUpClass()
|
||||||
tc.query("query { }", operation_name="QueryName")
|
tc.query("query { }", operation_name="QueryName")
|
||||||
body = json.loads(post_mock.call_args.args[1])
|
body = json.loads(post_mock.call_args[0][1])
|
||||||
# `operationName` field from https://graphql.org/learn/serving-over-http/#post-request
|
# `operationName` field from https://graphql.org/learn/serving-over-http/#post-request
|
||||||
assert (
|
assert (
|
||||||
"operationName",
|
"operationName",
|
||||||
|
@ -66,7 +66,7 @@ def test_graphql_test_case_operation_name(post_mock):
|
||||||
@patch("graphene_django.utils.testing.Client.post")
|
@patch("graphene_django.utils.testing.Client.post")
|
||||||
def test_graphql_query_case_operation_name(post_mock):
|
def test_graphql_query_case_operation_name(post_mock):
|
||||||
graphql_query("query { }", operation_name="QueryName")
|
graphql_query("query { }", operation_name="QueryName")
|
||||||
body = json.loads(post_mock.call_args.args[1])
|
body = json.loads(post_mock.call_args[0][1])
|
||||||
# `operationName` field from https://graphql.org/learn/serving-over-http/#post-request
|
# `operationName` field from https://graphql.org/learn/serving-over-http/#post-request
|
||||||
assert (
|
assert (
|
||||||
"operationName",
|
"operationName",
|
||||||
|
|
|
@ -2,7 +2,7 @@ import json
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from django.db import connection
|
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 test_handles_django_request_error(client, monkeypatch):
|
||||||
def mocked_read(*args):
|
def mocked_read(*args):
|
||||||
raise IOError("foo-bar")
|
raise OSError("foo-bar")
|
||||||
|
|
||||||
monkeypatch.setattr("django.http.request.HttpRequest.read", mocked_read)
|
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):
|
if not DJANGO_FILTER_INSTALLED and (filter_fields or filterset_class):
|
||||||
raise Exception(
|
raise Exception(
|
||||||
(
|
"Can only set filter_fields or filterset_class if "
|
||||||
"Can only set filter_fields or filterset_class if "
|
"Django-Filter is installed"
|
||||||
"Django-Filter is installed"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not (fields and exclude), (
|
assert not (fields and exclude), (
|
||||||
|
@ -228,7 +226,7 @@ class DjangoObjectType(ObjectType):
|
||||||
|
|
||||||
if use_connection is None and interfaces:
|
if use_connection is None and interfaces:
|
||||||
use_connection = any(
|
use_connection = any(
|
||||||
(issubclass(interface, Node) for interface in interfaces)
|
issubclass(interface, Node) for interface in interfaces
|
||||||
)
|
)
|
||||||
|
|
||||||
if use_connection and not connection:
|
if use_connection and not connection:
|
||||||
|
@ -255,7 +253,7 @@ class DjangoObjectType(ObjectType):
|
||||||
_meta.fields = django_fields
|
_meta.fields = django_fields
|
||||||
_meta.connection = connection
|
_meta.connection = connection
|
||||||
|
|
||||||
super(DjangoObjectType, cls).__init_subclass_with_meta__(
|
super().__init_subclass_with_meta__(
|
||||||
_meta=_meta, interfaces=interfaces, **options
|
_meta=_meta, interfaces=interfaces, **options
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ def graphql_query(
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
class GraphQLTestMixin(object):
|
class GraphQLTestMixin:
|
||||||
"""
|
"""
|
||||||
Based on: https://www.sam.today/blog/testing-graphql-with-graphene-django/
|
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):
|
def __init__(self, response, message=None, *args, **kwargs):
|
||||||
self.response = response
|
self.response = response
|
||||||
self.message = message = message or response.content.decode()
|
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):
|
def get_accepted_content_types(request):
|
||||||
|
|
|
@ -5,7 +5,7 @@ test=pytest
|
||||||
universal=1
|
universal=1
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
exclude = docs,graphene_django/debug/sql/*,migrations
|
exclude = docs,graphene_django/debug/sql/*
|
||||||
max-line-length = 120
|
max-line-length = 120
|
||||||
select =
|
select =
|
||||||
# Dictionary key repeated
|
# Dictionary key repeated
|
||||||
|
|
16
tox.ini
16
tox.ini
|
@ -2,7 +2,7 @@
|
||||||
envlist =
|
envlist =
|
||||||
py{37,38,39,310}-django32,
|
py{37,38,39,310}-django32,
|
||||||
py{38,39,310}-django{40,41,main},
|
py{38,39,310}-django{40,41,main},
|
||||||
black,flake8
|
pre-commit
|
||||||
|
|
||||||
[gh-actions]
|
[gh-actions]
|
||||||
python =
|
python =
|
||||||
|
@ -32,14 +32,8 @@ deps =
|
||||||
djangomain: https://github.com/django/django/archive/main.zip
|
djangomain: https://github.com/django/django/archive/main.zip
|
||||||
commands = {posargs:py.test --cov=graphene_django graphene_django examples}
|
commands = {posargs:py.test --cov=graphene_django graphene_django examples}
|
||||||
|
|
||||||
[testenv:black]
|
[testenv:pre-commit]
|
||||||
basepython = python3.9
|
skip_install = true
|
||||||
deps = -e.[dev]
|
deps = pre-commit
|
||||||
commands =
|
|
||||||
black --exclude "/migrations/" graphene_django examples setup.py --check
|
|
||||||
|
|
||||||
[testenv:flake8]
|
|
||||||
basepython = python3.9
|
|
||||||
deps = -e.[dev]
|
|
||||||
commands =
|
commands =
|
||||||
flake8 graphene_django examples setup.py
|
pre-commit run --all-files --show-diff-on-failure
|
||||||
|
|
Loading…
Reference in New Issue
Block a user