@ -118,48 +118,50 @@ Now let's have django run any outstanding migrations that haven't been run yet:
python manage.py migrate
python manage.py migrate
```
```
enter into shell
Let's test that the migrations worked. There's a django terminal shell that will let us play around with the project without having to use the browser. Let's start it:
```
```
python manage.py shell
python manage.py shell
```
```
in shell
Once it's started, we can write python to play around with the models. In the shell run:
```python
```python
from contacts_api.models import Contact
from contacts_api.models import Contact
Contact.objects.all()
Contact.objects.all() # get all the contacts in the db
c = Contact(name="Matt", age=40)
c = Contact(name="Matt", age=40) # create a new contact. Note this isn't yet in the db
c.save()
c.save() # save the contact to the db
c.id #should return 1
c.id # check the id to make sure it's in the db
Contact.objects.all()
Contact.objects.all()
quit()
quit()
```
```
in terminal and follow prompts
Django has a really nice admin app that lets us interface with the database from the browser. In the terminal run the following and follow the prompts
```
```
python manage.py createsuperuser
python manage.py createsuperuser
```
```
add to contacts_api/admin.py
Now add the following to contacts_api/admin.py
```python
```python
from .models import Contact
from .models import Contact
admin.site.register(Contact)
admin.site.register(Contact)
```
```
in terminal
and in the terminal run
```
```
python manage.py runserver
python manage.py runserver
```
```
go to http://localhost:8000/admin/
Go to http://localhost:8000/admin/ in the browser and sign in with the credentials you created when running `python manage.py createsuperuser`
## Create api endpoints
## Create api endpoints
install djangorestframework:
Now let's start working on the public facing API. We'll use Django Rest Framework, which makes this job a little easier.
Install `djangorestframework`:
```
```
python -m pip install djangorestframework
python -m pip install djangorestframework
@ -180,67 +182,81 @@ INSTALLED_APPS = [
]
]
```
```
create contacts_api/serializers.py
Now we want to create a serializer for our Contact model. This will take the data in our database and convert it to JSON.
Create contacts_api/serializers.py and add
```python
```python
from rest_framework import serializers
from rest_framework import serializers
from .models import Contact
from .models import Contact
class ContactSerializer(serializers.HyperlinkedModelSerializer):
class ContactSerializer(serializers.HyperlinkedModelSerializer): # serializers.HyperlinkedModelSerializer just tells django to convert sql to JSON
class Meta:
class Meta:
model = Contact
model = Contact # tell django which model to use
fields = ('id', 'name', 'age',)
fields = ('id', 'name', 'age',) # tell django which fields to include
```
```
in django_rest_api/urls.py edit
Don't get thrown off by the nested class (`Meta`). This is just an organizational thing that python lets us do.
Now lets create views which will connect the `ContactSerializer` with the `Contact` model.
- `generics.ListCreateAPIView` will be inherited by `ContactList` so that it will either display all Contacts in the DB or create a new one, depending on the request url and method
- `generics.RetrieveUpdateDestroyAPIView` will be inherited by `ContactDetail` so that it will either update or delete a contact in the DB, depending on the request url and method
set contacts_api/views.py to
```python
```python
from django.contrib import admin
from rest_framework import generics
from django.urls import path
from .serializers import ContactSerializer
from django.conf.urls import include # add this
from .models import Contact
urlpatterns = [
class ContactList(generics.ListCreateAPIView):
path('', include('contacts_api.urls')), # add this
queryset = Contact.objects.all() # tell django how to retrieve all objects from the DB
path('admin/', admin.site.urls),
serializer_class = ContactSerializer # tell django what serializer to use
]
class ContactDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Contact.objects.all()
serializer_class = ContactSerializer
```
```
Now lets map request urls to the views we just created
path('api/contacts/<int:pk>', views.ContactDetail.as_view(), name='contact_detail'), # api/contacts will be routed to the ContactDetail view for handling
]
]
```
```
set contacts_api/views.py to
Finally register our contacts_api urls with django
```python
in django_rest_api/urls.py edit
from rest_framework import generics
from .serializers import ContactSerializer
from .models import Contact
class ContactList(generics.ListCreateAPIView):
```python
queryset = Contact.objects.all()
from django.contrib import admin
serializer_class = ContactSerializer
from django.urls import path
from django.conf.urls import include # add this
class ContactDetail(generics.RetrieveUpdateDestroyAPIView):
urlpatterns = [
queryset = Contact.objects.all()
path('', include('contacts_api.urls')), # add this
serializer_class = ContactSerializer
path('admin/', admin.site.urls),
]
```
```
## Add CORS
## Add CORS
Lastly, let's allow web apps on other origins to access this api. In the terminal, install the `django-cors-headers` package:
```
```
python -m pip install django-cors-headers
python -m pip install django-cors-headers
```
```
edit django_rest_api/settings.py
edit django_rest_api/settings.py to include the new package:
```python
```python
INSTALLED_APPS = [
INSTALLED_APPS = [
@ -256,7 +272,7 @@ INSTALLED_APPS = [
]
]
MIDDLEWARE = [
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # add this
'corsheaders.middleware.CorsMiddleware', # this makes the cors package run for all requests. A bit like app.use() in express