0. 목표
Django에서 관리하는 세션정보는 로그인한 user만을 관리(django_session)하므로 실제 접속자 카운트가 정밀하게 되지 않는다.
이에 브라우저로 최초 접속시 쿠키에 ses_id존재 여부를 확인하여 ses_id가 없다면 ses_id를 발번하고
최초 한번만 session정보를 누적하도록 App를 구현한다.
1. App생성
C:\Work\Software\eclipse-jee-2019-12-R-win32-x86_64\workspace\Blog>BlogVenv\Scripts\activate
(BlogVenv) C:\Work\Software\eclipse-jee-2019-12-R-win32-x86_64\workspace\Blog>python manage.py startapp userSession
PowerShell
2. apps.py 수정
from django.apps import AppConfig
class UserSessionConfig(AppConfig):
name = "userSession"
Python
3. models.py 수정
from __future__ import unicode_literals
from django.contrib.auth.models import User
from django.db import models
class UserSession(models.Model):
ses_id = models.CharField("Session ID", max_length=64, primary_key=True)
ses_ip = models.GenericIPAddressField("User IP", protocol="both", unpack_ipv4=True)
ses_ipGeo = models.TextField("IP GEO Location", null=True)
ses_agent = models.TextField("User Agent", null=True)
ses_referer = models.TextField("Referer URL", null=True)
ses_user = models.ForeignKey(User, on_delete=models.PROTECT, related_name="session_user", db_column="ses_user_id", null=True)
access_dt = models.DateTimeField("Access Datetime", db_index=True, auto_now_add=True)
exit_dt = models.DateTimeField("Exit Datetime", null=True)
class Meta:
verbose_name = "userSession"
verbose_name_plural = "userSessions"
db_table = "blog_userSession"
ordering = ["-access_dt"]
def __str__(self):
return self.ses_id
Python
4. settings.py 수정
INSTALLED_APPS = [
...
'userSession.apps.UserSessionConfig',
...
Python
5. makemigrations & migrate
(BlogVenv) C:\Work\Software\eclipse-jee-2019-12-R-win32-x86_64\workspace\Blog>python manage.py makemigrations --settings=Blog.settings.settings_dev
(BlogVenv) C:\Work\Software\eclipse-jee-2019-12-R-win32-x86_64\workspace\Blog>python manage.py migrate --settings=Blog.settings.settings_dev
PowerShell
6. views.py 수정
import urllib.request
from django.http.response import JsonResponse
from django.views.decorators.http import require_http_methods
from userSession.models import UserSession
class UserSessionAV():
@staticmethod
@require_http_methods(["POST"])
def access(request, **kwargs):
_result = {};
_result["status"] = False
_result["message"] = None
if request.is_ajax():
userSession = UserSession()
userSession.ses_id = kwargs["ses_id"]
userSession.ses_ip = request.META.get("REMOTE_ADDR")
userSession.ses_ipGeo = UserSessionAV.getIPGeo(userSession.ses_ip)
userSession.ses_agent = request.META.get("HTTP_USER_AGENT")
userSession.ses_referer = request.META.get("HTTP_REFERER")
userSession.save()
_result["status"] = True
else:
_result["status"] = False
_result["message"] = "Illegal access."
return JsonResponse({"result":_result})
# Designated as @classmethod so that it can be called from @staticmethod
# Of course, you can specify @staticmethod.
@classmethod
def getIPGeo(cls, ip):
_geoInfo = ""
try:
# https://ipapi.co/api/?python#introduction
_url = "https://ipapi.co/{}/json/".format(ip)
_response = urllib.request.urlopen(_url)
_geoInfo = _response.read().decode()
except:
pass
return _geoInfo
Python
7. urls.py 수정
from django.urls import path
from userSession.views import UserSessionAV
app_name = "userSession"
urlpatterns = [
path("access/<str:ses_id>/", UserSessionAV.access, name="access")
]
Python
8. ut.js 수정
var UT =
{
UUID : function()
{
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c)
{
var r = Math.random() * 16 | 0, v = c == "x" ? r : (r & 3 | 8);
return v.toString(16);
});
},
...
setCookie : function(cname, cvalue, exdays)
{
var d = new Date();
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
var expires = "";
if (UT.nvl(exdays, 0) > 0)
{
expires = ";expires=" + d.toUTCString();
}
document.cookie = cname + "=" + encodeURIComponent(cvalue) + expires + ";path=/";
},
...
JavaScript
9. ss.js 작성
var SS =
{
access : function()
{
if (UT.isEmpty(UT.getCookie("ses_id")))
{
var _ses_id = UT.UUID();
UT.setCookie("ses_id", _ses_id)
UT.ajax("POST", "/userSession/access/" + _ses_id + "/");
}
}
}
JavaScript
10. base.html 수정
<!DOCTYPE html>
<html lang="ko">
<head>
...
<script type="text/javascript" src="{% static "javascript/ss.js" %}"></script>
...
</head>
Markup
11. footer.html 수정
<script>
...
SS.access();
...
</script>
Markup
12. 접속테스트
13. 운영배포
- 관련파일 업로드하고
- DB반영
[root@linux blog.daonelab.com]# source BlogVenv/bin/activate
(BlogVenv) [root@linux blog.daonelab.com]# python manage.py makemigrations --settings=Blog.settings.settings_prd
(BlogVenv) [root@linux blog.daonelab.com]# python manage.py migrate --settings=Blog.settings.settings_prd
PowerShell