Browse Source

Add tests

pull/11782/head
Patrick Arminio 1 year ago
parent
commit
a9465600af
Failed to extract signature
  1. 88
      docs/en/docs/advanced/django-orm.md
  2. 0
      docs_src/django_orm/mysite/__init__.py
  3. 10
      docs_src/django_orm/mysite/settings.py
  4. 1
      docs_src/django_orm/mysite/urls.py
  5. 0
      docs_src/django_orm/polls/__init__.py
  6. 36
      docs_src/django_orm/polls/migrations/0001_initial.py
  7. 0
      docs_src/django_orm/polls/migrations/__init__.py
  8. 29
      docs_src/django_orm/polls/models.py
  9. 37
      docs_src/django_orm/tutorial001.py
  10. 0
      tests/test_tutorial/test_django_orm/__init__.py
  11. 42
      tests/test_tutorial/test_django_orm/test_tutorial001.py

88
docs/en/docs/advanced/django-orm.md

@ -22,41 +22,29 @@ pip install fastapi
## Step 2: Set up a basic FastAPI application
Create a `main.py` file:
Let's create a basic FastAPI application in a new file called `main.py`:
```python
from fastapi import FastAPI
=== "Python 3.8+"
app = FastAPI()
```
```Python
{!> ../../../docs_src/django_orm/tutorial001.py[ln:5,13]!}
```
In the next steps we'll import the `Question` model from Django, and create a FastAPI endpoint to list all questions.
## Step 3: Import Django models
In your `main.py` file, let's import the `Question` model:
```python
from polls.models import Question
```
Make sure to replace `polls` with the name of your Django app.
## Step 3: Import and use Django models
## Step 4: Create a FastAPI endpoint
In your `main.py` file, let's import the `Question` model and create a FastAPI endpoint to list all questions:
Now let's create a FastAPI endpoint to list all questions:
=== "Python 3.8+"
```python
@app.get("/questions")
def get_questions():
questions = Question.objects.all()
```Python
{!> ../../../docs_src/django_orm/tutorial001.py[ln:10,16-20]!}
```
return [{"question": question.question_text} for question in questions]
```
## Step 5: Run the FastAPI application
## Step 4: Run the FastAPI application
No we can run the FastAPI application:
Now, let's run the FastAPI application:
```bash
fastapi dev main.py
@ -64,62 +52,40 @@ fastapi dev main.py
If you go to `http://localhost:8000/questions` we should see the list of questions, right? 🤔
Unfortunately, we'll get an error:
Unfortunately, we'll get this error:
```text
django.core.exceptions.ImproperlyConfigured: Requested setting INSTALLED_APPS, but settings are not configured.
You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
```
This error happens because Django settings are not configured before importing the Django models.
This error happens because Django needs to be configured before importing the models.
## Step 6: Configure Django settings
## Step 5: Configure Django settings
To fix this error, we need to configure Django settings before importing the Django models.
In the `main.py` add the following code **before** importing the Django models:
```python
import os
import django
=== "Python 3.8+"
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
django.setup()
```
```Python
{!> ../../../docs_src/django_orm/tutorial001.py[ln:1,7-10]!}
```
This will configure Django settings before importing the Django models.
Now, if you run the FastAPI application again, you should see the list of questions at `http://localhost:8000/questions`! 🎉
## Step 7: Run the FastAPI application (again)
## Conclusion
Now you can run the FastAPI application:
```bash
fastapi dev main.py
```
And now if we go to `http://localhost:8000/questions` we should see a list of questions! 🎉
In this guide, we learned how to use Django's ORM with FastAPI. This can be extremely useful when migrating from Django to FastAPI, as you can reuse your existing Django models and queries.
## Using the ORM in async routes
Django's support for async is currently limited, if you need to do run any query in an async route (or function),
you need to either use the async equivalent of the query or use `sync_to_async` from `asgiref.sync` to run the query:
```python
from asgiref.sync import sync_to_async
@app.get("/questions")
async def get_questions():
def _fetch_questions():
return list(Question.objects.all())
questions = await sync_to_async(_fetch_questions)()
=== "Python 3.8+"
return [{"question": question.question_text} for question in questions]
@app.get("/questions/{question_id}")
async def get_question(question_id: int):
question = await Question.objects.filter(id=question_id).afirst()
return {"question": question.question_text}
```
```Python
{!> ../../../docs_src/django_orm/tutorial001.py[ln:23-37]!}
```

0
docs_src/django_orm/mysite/__init__.py

10
docs_src/django_orm/mysite/settings.py

@ -0,0 +1,10 @@
INSTALLED_APPS = ["polls"]
ROOT_URLCONF = "mysite.urls"
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": ":memory:",
},
}

1
docs_src/django_orm/mysite/urls.py

@ -0,0 +1 @@
urlpatterns = []

0
docs_src/django_orm/polls/__init__.py

36
docs_src/django_orm/polls/migrations/0001_initial.py

@ -0,0 +1,36 @@
# Generated by Django 2.1 on 2018-08-08 21:45
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Choice',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('choice_text', models.CharField(max_length=200)),
('votes', models.IntegerField(default=0)),
],
),
migrations.CreateModel(
name='Question',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('question_text', models.CharField(max_length=200)),
('pub_date', models.DateTimeField(verbose_name='date published')),
],
),
migrations.AddField(
model_name='choice',
name='question',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='polls.Question'),
),
]

0
docs_src/django_orm/polls/migrations/__init__.py

29
docs_src/django_orm/polls/models.py

@ -0,0 +1,29 @@
import datetime
from django.db import models
from django.utils import timezone
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.question_text
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
was_published_recently.admin_order_field = 'pub_date'
was_published_recently.boolean = True
was_published_recently.short_description = 'Published recently?'
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text

37
docs_src/django_orm/tutorial001.py

@ -0,0 +1,37 @@
import os
import django
from asgiref.sync import sync_to_async
from fastapi import FastAPI
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
django.setup()
from polls.models import Question # noqa: I001
app = FastAPI()
@app.get("/questions")
def get_questions():
questions = Question.objects.all()
return [{"question": question.question_text} for question in questions]
@app.get("/questions-async")
async def get_questions_async():
def _fetch_questions():
return list(Question.objects.all())
questions = await sync_to_async(_fetch_questions)()
return [{"question": question.question_text} for question in questions]
@app.get("/questions/{question_id}")
async def get_question(question_id: int):
question = await Question.objects.filter(id=question_id).afirst()
return {"question": question.question_text}

0
tests/test_tutorial/test_django_orm/__init__.py

42
tests/test_tutorial/test_django_orm/test_tutorial001.py

@ -0,0 +1,42 @@
import pytest
from django.core.management.color import no_style
from django.core.management.sql import sql_flush
from django.db import connection
from django.utils import timezone
from fastapi.testclient import TestClient
from docs_src.django_orm.tutorial001 import Question, app
client = TestClient(app)
@pytest.fixture(scope="session", autouse=True)
def django_db_setup():
connection.creation.create_test_db(verbosity=0, autoclobber=True)
yield
connection.creation.destroy_test_db("default", verbosity=0)
@pytest.fixture(autouse=True)
def flush_db():
sql_list = sql_flush(no_style(), connection, allow_cascade=False)
connection.ops.execute_sql_flush(sql_list)
def test_get_questions():
Question.objects.create(question_text="there goes my hero", pub_date=timezone.now())
response = client.get("/questions")
assert response.status_code == 200, response.text
assert response.json() == [{"question": "there goes my hero"}]
def test_question_empty():
response = client.get("/questions")
assert response.status_code == 200, response.text
assert response.json() == []
Loading…
Cancel
Save