[PYTHON] Django memorandum

I wrote a little app in Django about a year ago, but I forgot it, so I will remember it while leaving it as a memorandum. I compared the latest tutorials in the official documentation because the Japanese translation of the tutorial is only 1.4, which is a fairly old release, but the article here I remember it was very helpful.

1.8 has already come out, but since I did it last time in 1.7, it will come in 1.7.

Environment in this article

[sayamada@~]$cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=12.04
DISTRIB_CODENAME=precise
DISTRIB_DESCRIPTION="Ubuntu 12.04.5 LTS"
[sayamada@~]$uname -a
Linux XXXXXX 3.13.0-65-generic #106~precise1-Ubuntu SMP Fri Oct 2 22:07:14 UTC 2015 i686 i686 i386 GNU/Linux
[sayamada@~]$python -V
Python 2.7.9 :: Anaconda 2.0.1 (32-bit)
[sayamada@~]$pip list |grep -i django
Django (1.7.1)
django-bootstrap-form (3.1)

I can't get root on my company PC, so I use Anaconda to make the tea muddy. Ordinary people

$ pip install django==1.7.1

Isn't it okay?

Create a project

Is one website equivalent to one project? First of all, I made a project.

[sayamada@git]$django-admin.py startproject demoPrj
[sayamada@git]$tree demoPrj/
demoPrj/
├── demoPrj
│   ├── __init__.py
│   ├── settings.py --The guy who writes the settings
│   ├── urls.py  --The guy who writes the top routing
│   └── wsgi.py
└── manage.py --Execution script for management commands

Backend DB changes

It seems to work with sqlite by default, but I like the occupational pattern PostgreSQL, so I will change it. ** pyscopg2 ** I feel like I had to add it. If you don't like PostgreSQL, you can just use sqlite.

settings.py


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'DB name',
        'USER': 'username',
        'PASSWORD': '',
        'HOST': 'localhost',
        'PORT': '5432'
    }
}

Change locale

I'm Japanese so I'll change it.

settings.py


# LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'ja'

# TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Tokyo'

Creating an application

It seems that the site (project) consists of multiple ** applications **. Feeling like creating an app for each function and adding it? What is it?

[sayamada@git]$cd demoPrj/
[sayamada@demoPrj]$python manage.py startapp demoApp
[sayamada@demoPrj]$tree 
.
├── demoApp --This directory has increased
│   ├── __init__.py
│   ├── admin.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py --The one that defines the model
│   ├── tests.py 
│   └── views.py --A guy who writes VIEW or logic entry points?
├── demoPrj
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── settings.py
│   ├── settings.pyc
│   ├── urls.py
│   └── wsgi.py
└── manage.py

3 directories, 13 files

By the way, although it is not created by default, it seems that a large routing is defined in demoPrj / urls.py and the routing for each application is set individually, so ** demoApp / urls.py ** is created manually. ..

User authentication

django defines a model (** User **) for account management in advance. Middleware for authentication is also available. This time, I created the authentication process in an application called ** Auth **, so I will add it to INSTALLED_APPS as well.

settings.py


INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',★ With this
    'django.contrib.contenttypes',★ I need this
:
    'Authctl',★ This was made with startapp
:
LOGIN_URL = '/auth/login'
LOGIN_REDIRECT_URL = '/auth/home'
:
AUTHENTICATION_BACKENDS = (
    'Authctl.AuthLogic.AuthBackEnd',
    'django.contrib.auth.backends.ModelBackend',
)

It is included when the project is created. After that, specify the authentication logic in AUTHENTICATION_BACKENDS. Above is the authentication logic I made. I forgot why there are two. The view side of the page that requires authentication is as follows. This time, I created AuthLogic.py under Auth and decided to define a function called AuthBackend in it.

demoApp/views.py


# coding:utf-8
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required

@login_required
def index(request):
    return HttpResponse(u'index')

Methods with the login_required decorator are checked in advance to see if they are logged in. If you are not logged in, you will be redirected to ** LOGIN_URL ** in settings.py. This time it is / authctl / login, so you need to configure the routing to resolve it.

If you have a field excluded in forms.ModelForm

At the time of form.save, there is usually an error with NOT NULL constraint. You can pass an instance of Model with attributes excluded by ** instance = ** to the form constructor.

views.py


any_model_inst = AnyModel()
any_model_inst.excluded_any_ked = u"hoge"
form = AnyForm(request.POST, instance=any_model_inst)
form.save()

View the request object in the decorator

I don't know where the request object is.

#Decorator for checking if API access has permission
def check_access_permission(func):
    import functools
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        #The first argument is the request object
        request = args[0]
        print request.user
        if check_any_func():
            return HttpResponseForbidden()
        # OK
        return func(*args, **kwargs)
    return wrapper

I wanted to see the Authorization header

I wanted to see the header when I threw something like this

curl localhost:8000/api/ \
-H "Authorization: demo token" \
-X GET 

It was like this

def check_access_permission(func):
    import functools
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        #The first argument is the request object
        request = args[0]
        #You can get it with this
        print request.META.get('HTTP_AUTHORIZATION')
        if False:
            return HttpResponseForbidden()

        return func(*args, **kwargs)
    return wrapper

I wanted to do something like ENUM on a Form

When I wanted to narrow down the value specified by REST, I made a Form just for Validation and Choice Fileld was just right.

forms.py


    contact_choice = (
        ("TEL", "TEL"),
        ("Email", "Email"),
        ("FAX", "FAX"),
        ("Web", "Web"),
    )
    contact_way = forms.ChoiceField(label=u"Inquiry method", choices=contact_choice,required=False, initial=None)

With this, if you enter hoge in contact_way, you will die with is_valid ().

I want to know why valid failed in Form

It was written properly in the Manual. It seems that there are various ways to display it after 1.7.

if form.is_valid():

    something doing..
else:
        # FromClass.There are errors in errors
        # as_json()Can be retrieved in JSON format with
        print  form.errors.as_json()

Form initial is not retrieved with cleaned_data

sender_name = forms.CharField(label=u'Sender name', required=False, initial=u"default sender")

So, if you do this

sender_name = form.cleaned_data["sender_name"] # -> I expect "default sender" but None

It has become.

Looking at here, initial is the initial data on the display, and it seems that it cannot be obtained with cleaned_data. It looks like you need to override form.clean. There was a part that didn't move a little, so I finally replaced it with the following.

class DisplaySharerForm(forms.Form):
...
    def clean(self):
        cleaned_data = super(DisplaySharerForm, self).clean()
        for key, value in cleaned_data.items():
            if not value:
                cleaned_data[key] = self.fields[key].initial

        return cleaned_data

Recommended Posts

Django memorandum
Django
Matplotlib memorandum
django update
Django note 4
linux memorandum
jinja2 memorandum
Python memorandum
django search
Django installation
Command memorandum
Django Summary
Django test
Python Memorandum 2
[Django] Memorandum of environment construction procedure
plotly memorandum
Slackbot memorandum (1)
multiprocessing memorandum
Memorandum MetaTrader 5
[Linux/LPIC] Memorandum
Django # 2 (template)
ShellScript memorandum
Django Note 5
Django hands-on
Touch django
django notes
Django Summary
Django basics
pip memorandum
Django Shoho
Python memorandum
Django defaults
pydoc memorandum
Django + Docker
python memorandum
Pandas memorandum
python memorandum
DjangoGirls memorandum
Django Glossary
Django search
Install Django
Command memorandum
Django: References
Python memorandum
Django Note 1
pandas memorandum
python memorandum
Django note 3
Django note 2
Python memorandum
Django startup
Django notes
Django NullCharField
Django environment construction
Python basics memorandum
RAID type memorandum
Django Heroku Deploy 1
Django HTML Template # 2
Django Contact Form 2
Django begins part 1
Python pathlib memorandum