“Tweets” model:

  • we start a new app “tweets”: ```bash (reactjs) [root@localhost Twittme]# ./manage.py startapp tweets (reactjs) [root@localhost Twittme]# tree . ├── db.sqlite3 ├── manage.py ├── todo.md ├── tweets │ ├── admin.py │ ├── apps.py │ ├── init.py │ ├── migrations │ │ └── init.py │ ├── models.py │ ├── tests.py │ └── views.py └── Twittme ├── init.py ├── settings.py ├── urls.py └── wsgi.py

3 directories, 14 files

  1. (./manage.py startapp tweets<br />==<br />python manage.py startapp tweets)
  2. - modify /tweets/models.py:
  3. ```python
  4. from django.db import models
  5. class Tweet(models.Model):
  6. # id = models.AutoField(primary_key=True)
  7. content = models.TextField(blank=True, null=True)
  8. image = models.FileField(upload_to="images/", blank=True, null=True)
  9. # id is the primary key
  10. # blank=True -> not mandatory in django
  11. # null=True -> not mandatory in the database
  • then sign the new app in /Twittme/settings.py:

    1. # ...
    2. INSTALLED_APPS = [
    3. 'django.contrib.admin',
    4. 'django.contrib.auth',
    5. 'django.contrib.contenttypes',
    6. 'django.contrib.sessions',
    7. 'django.contrib.messages',
    8. 'django.contrib.staticfiles',
    9. 'tweets', # new
    10. ]
    11. # ...
  • make migrations for “tweets”: ```bash (reactjs) [root@localhost Twittme]# ./manage.py makemigrations Migrations for ‘tweets’: tweets/migrations/0001_initial.py

    • Create model Tweet (reactjs) [root@localhost Twittme]# tree . ├── db.sqlite3 ├── manage.py ├── todo.md ├── tweets │ ├── admin.py │ ├── apps.py │ ├── init.py │ ├── migrations │ │ ├── 0001initial.py │ │ └── init.py │ ├── models.py │ ├── tests.py │ └── views.py └── Twittme ├── _init.py ├── settings.py ├── urls.py └── wsgi.py

3 directories, 15 files

  1. and we have a migration model for tweets.
  2. - Finally, let manage.py apply that migrate:
  3. ```bash
  4. (reactjs) [root@localhost Twittme]# ./manage.py migrate
  5. Operations to perform:
  6. Apply all migrations: admin, auth, contenttypes, sessions, tweets
  7. Running migrations:
  8. Applying contenttypes.0001_initial... OK
  9. Applying auth.0001_initial... OK
  10. Applying admin.0001_initial... OK
  11. Applying admin.0002_logentry_remove_auto_add... OK
  12. Applying admin.0003_logentry_add_action_flag_choices... OK
  13. Applying contenttypes.0002_remove_content_type_name... OK
  14. Applying auth.0002_alter_permission_name_max_length... OK
  15. Applying auth.0003_alter_user_email_max_length... OK
  16. Applying auth.0004_alter_user_username_opts... OK
  17. Applying auth.0005_alter_user_last_login_null... OK
  18. Applying auth.0006_require_contenttypes_0002... OK
  19. Applying auth.0007_alter_validators_add_error_messages... OK
  20. Applying auth.0008_alter_user_username_max_length... OK
  21. Applying auth.0009_alter_user_last_name_max_length... OK
  22. Applying sessions.0001_initial... OK
  23. Applying tweets.0001_initial... OK

Store data from Django model:

  • use python shell to test model: ```bash (reactjs) [root@localhost Twittme]# ./manage.py shell Python 3.6.5 (default, Sep 10 2018, 09:39:42) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux Type “help”, “copyright”, “credits” or “license” for more information. (InteractiveConsole)

    from tweets.models import Tweet obj = Tweet() obj.abc = 123 obj.abc 123 obj.content = “Hello World” obj.content ‘Hello World’ obj.save() exit()

(reactjs) [root@localhost Twittme]# ./manage.py shell Python 3.6.5 (default, Sep 10 2018, 09:39:42) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux Type “help”, “copyright”, “credits” or “license” for more information. (InteractiveConsole)

from tweets.models import Tweet obj = Tweet.objects.get(id=1) obj.content ‘Hello World’ obj.abc Traceback (most recent call last): File ““, line 1, in AttributeError: ‘Tweet’ object has no attribute ‘abc’ ``` so we see that for objects, database only saves defined attributes.

URL Routing and Dynamic Routing:

to get rid of only have the default page, we need to create views and route browsers to those views.

  • create our first view, home_view in /tweets/views.py: ```python from django.http import HttpResponse # new from django.shortcuts import render

def home_view(request, args, *kwargs): # new return HttpResponse(“

Hello World

“)

  1. - for routing, modify /Twittme/urls.py:
  2. ```python
  3. from django.contrib import admin
  4. from django.urls import path
  5. from tweets.views import home_view # new
  6. urlpatterns = [
  7. path('admin/', admin.site.urls),
  8. path('', home_view), # new
  9. ]

to test, runserver

  1. (reactjs) [root@localhost Twittme]# ./manage.py runserver

and access localhost:8000
image.png
so this is URL routing

  • to expand, create another view in /tweets/views.py to receive url details: ```python from django.http import HttpResponse from django.shortcuts import render

def home_view(request, args, *kwargs): print(args, kwargs) return HttpResponse(“

Hello World

“)

def tweet_detail_view(request, tweet_id, args, *kwargs): # new print(args, kwargs) return HttpResponse(f”

Hello {tweet_id}

“)

  1. - new route in /Twittme/urls.py:
  2. ```python
  3. from django.contrib import admin
  4. from django.urls import path, re_path
  5. from tweets.views import home_view, tweet_detail_view # new
  6. urlpatterns = [
  7. path('admin/', admin.site.urls),
  8. path('', home_view),
  9. path('tweets/<int:tweet_id>', tweet_detail_view), # new
  10. ]

to test, runserver

  1. (reactjs) [root@localhost Twittme]# ./manage.py runserver

and access localhost:8000/tweets/(an integer)
for example we have localhost:8000/tweets/15 here:
image.png
so that “15” is “tweet_id” in urls.py,
and tweet_detail_view in views.py know what “tweet_id” is when they print
f”

Hello {tweet_id}

this is Dynamic routing
**

How to handle Dynamic Routing:

The routing case before is to just send an integer, but we actually need to get real exist objects

  • modify tweet_detail_view in /tweets/views.py ```python from django.http import HttpResponse from django.shortcuts import render

from .models import Tweet

def home_view(request, args, *kwargs): return HttpResponse(“

Hello World

“)

def tweet_detail_view(request, tweet_id, args, *kwargs): obj = Tweet.objects.get(id=tweet_id) # what we did in shell return HttpResponse(f”

Hello {tweet_id} - {obj.content}

“)

  1. to test, runserver, access localhost:8000/tweets/1<br />(we only have 1 object now):<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/1243266/1591206435623-f16e83f3-b540-4df0-90cf-6f2ee0a78152.png#align=left&display=inline&height=164&margin=%5Bobject%20Object%5D&name=image.png&originHeight=327&originWidth=504&size=10401&status=done&style=none&width=252)<br />and it's successful to get the object and print the content.
  2. also, we get DNE if there is no corresponding object:<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/1243266/1591206546204-ad62aba0-29a1-46ca-9464-7f5c088cab37.png#align=left&display=inline&height=399&margin=%5Bobject%20Object%5D&name=image.png&originHeight=797&originWidth=1067&size=119010&status=done&style=none&width=533.5)<br />we can redirect it to a simpler error
  3. - /tweets/views.py
  4. ```python
  5. from django.http import HttpResponse, Http404 # new
  6. from django.shortcuts import render
  7. from .models import Tweet
  8. def home_view(request, *args, **kwargs):
  9. return HttpResponse("<h1>Hello World</h1>")
  10. def tweet_detail_view(request, tweet_id, *args, **kwargs):
  11. try:
  12. obj = Tweet.objects.get(id=tweet_id)
  13. except: # if cannot get the object
  14. raise Http404
  15. return HttpResponse(f"<h1>Hello {tweet_id} - {obj.content}</h1>")

to test, run and access a tweet_id that not exists:
image.png

  • for further changes, we need to only pass JSON data from views.py
  • modify /tweets/views.py ```python from django.http import HttpResponse, Http404, JsonResponse # new from django.shortcuts import render

from .models import Tweet

def home_view(request, args, *kwargs): return HttpResponse(“

Hello World

“)

def tweet_detail_view(request, tweet_id, args, *kwargs): try: obj = Tweet.objects.get(id=tweet_id) except: raise Http404

  1. data = {
  2. "id" : tweet_id,
  3. "content" : obj.content,
  4. # "image_path" : obj.image.url # save for later
  5. } # new
  6. return JsonResponse(data) # new
  1. to test, runserver and access localhost:8000/tweets/1<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/1243266/1591209135341-d1db2762-1a09-4a0d-bdb3-25b923fb3a32.png#align=left&display=inline&height=149&margin=%5Bobject%20Object%5D&name=image.png&originHeight=297&originWidth=490&size=15210&status=done&style=none&width=245)<br />and we get some JSON format data.
  2. - we can also cut down Http404, and modify status to return by ourselves:
  3. - modify /tweets/views.py
  4. ```python
  5. from django.http import HttpResponse, JsonResponse # removed Http404
  6. from django.shortcuts import render
  7. from .models import Tweet
  8. def home_view(request, *args, **kwargs):
  9. return HttpResponse("<h1>Hello World</h1>")
  10. def tweet_detail_view(request, tweet_id, *args, **kwargs):
  11. # sequence changed
  12. data = {
  13. "id" : tweet_id,
  14. }
  15. status = 200 # normal
  16. try:
  17. obj = Tweet.objects.get(id=tweet_id)
  18. data['content'] = obj.content
  19. except:
  20. data['message'] = "Not found"
  21. status = 404 # not found
  22. return JsonResponse(data, status = status)

to test, runserver and access localhost:8000/tweets/1
image.png
then, access localhost:8000/tweets/2
image.png
and the server terminal log:

  1. [02/Jun/2020 18:38:15] "GET /tweets/1 HTTP/1.1" 200 35
  2. [02/Jun/2020 18:38:17] "GET /static/5aded14b87e017d32d080b686515f6a26be455f1/dist/serviceWorker.js HTTP/1.1" 404 1810
  3. Not Found: /tweets/2
  4. [02/Jun/2020 18:38:35] "GET /tweets/2 HTTP/1.1" 404 33
  5. [02/Jun/2020 18:38:37] "GET /static/5aded14b87e017d32d080b686515f6a26be455f1/dist/serviceWorker.js HTTP/1.1" 404 1810

Introduce templates:

we need templates to increase code reuse.

  • create a templates/ folder under Twittme/ ```bash (reactjs) [root@localhost Twittme]# tree . ├── db.sqlite3 ├── manage.py ├── templates ├── todo.md ├── tweets │ ├── admin.py │ ├── apps.py │ ├── init.py │ ├── migrations │ │ ├── 0001initial.py │ │ └── init.py │ ├── models.py │ ├── tests.py │ └── views.py └── Twittme ├── _init.py ├── settings.py ├── urls.py └── wsgi.py

4 directories, 15 files ```