article

Showing posts with label Python-Django. Show all posts
Showing posts with label Python-Django. Show all posts

Thursday, June 30, 2022

Python Django Simple Blog with Summernote WYSIWYG Editor

Python Django Simple Blog with Summernote WYSIWYG Editor

Install django-summernote.

pip install django-summernote

django_summernote to INSTALLED_APP in settings.py.

INSTALLED_APPS += ('django_summernote', ) 

django_summernote.urls to urls.py.

from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [ 
    path('admin/', admin.site.urls), 
    path('summernote/', include('django_summernote.urls')),
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
 
Media settings
X_FRAME_OPTIONS = 'SAMEORIGIN'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')


To explore more configuration read the official documentation of the package, https://github.com/summernote/django-summernote


blogsite/settings.py
 
//blogsite/settings.py
    
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp', #add myapp
]

INSTALLED_APPS += ('django_summernote', ) 

X_FRAME_OPTIONS = 'SAMEORIGIN'
myapp/views.py
 
//myapp/views.py
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
from django.contrib import messages
from myapp.models import Category, Post

category_list = Category.objects.exclude(status = 2).all()
context = {
    'page_title' : 'Simple Blog Site',
    'category_list' : category_list,
    'category_list_limited' : category_list[:3]
}
# Create your views here.
#Logout
def logoutuser(request):
    logout(request)
    return redirect('/')

def home(request):
    context['page_title'] = 'Home'
    posts = Post.objects.filter(status = 1).all()
    context['posts'] = posts
    return render(request, 'home.html',context)

def view_post(request,pk=None):
    context['page_title'] = ""
    if pk is None:
        messages.error(request,"Unabale to view Post")
        return redirect('home-page')
    else:
        post = Post.objects.filter(id = pk).first()
        context['page_title'] = post.title
        context['post'] = post
    return render(request, 'view_post.html',context)

def post_by_category(request,pk=None):
    if pk is None:
        messages.error(request,"Unabale to view Post")
        return redirect('home-page')
    else:
        category = Category.objects.filter(id=pk).first()
        context['page_title'] = category.name
        context['category'] = category
        posts = Post.objects.filter(category = category).all()
        context['posts'] = posts
    return render(request, 'by_categories.html',context)

def categories(request):
    categories = Category.objects.filter(status = 1).all()
    context['page_title'] = "Category Management"
    context['categories'] = categories
    return render(request, 'categories.html',context)
blogsite/urls.py
 
//blogsite/urls.py
from django.contrib import admin
from django.urls import include, path
  
from django.conf import settings
from django.conf.urls.static import static
  
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('myapp.urls')),
    path('summernote/', include('django_summernote.urls')),
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
myspp/urls.py
 
//myspp/urls.py
from . import views
from django.contrib import admin
from django.urls import path, re_path
from django.contrib.auth import views as auth_views
from django.views.generic.base import RedirectView

urlpatterns = [
    path('redirect-admin', RedirectView.as_view(url="/admin"),name="redirect-admin"),
    path('', views.home, name="home-page"),
    path('logout',views.logoutuser,name='logout'),
    path(r'view_post/<int:pk>',views.view_post,name='view-post'),
    path(r'<int:pk>',views.post_by_category,name='category-post'),
    path('categories',views.categories,name='category-page'),
]
Make Migrations
Run the commands below to make migrations:
python manage.py makemigrations
python manage.py migrate
C:\django\blogsite>python manage.py makemigrations
C:\django\blogsite>python manage.py migrate
myapp/models.py
 
//myapp/models.py
from django.db import models
from unicodedata import category
from django.db import models
from django.contrib.auth.models import User

from django.utils import timezone

class Category(models.Model):
    name = models.CharField(max_length=250)
    description = models.TextField(blank=True, null=True)
    status = models.IntegerField(default = 1)
    date_added = models.DateTimeField(default=timezone.now)
    date_updated = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

class Post(models.Model):
    category=models.ForeignKey(Category,on_delete=models.CASCADE)
    title = models.TextField()
    author = models.ForeignKey(User,on_delete=models.CASCADE)
    blog_post = models.TextField()
    banner = models.ImageField(blank=True, null = True, upload_to= 'images/')
    status = models.IntegerField(default = 0)
    date_added = models.DateTimeField(default=timezone.now)
    date_updated = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.title + " - " + self.category.name
Bootstrap 5
https://getbootstrap.com/docs/5.0/getting-started/introduction/
https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css
myapp/templates/home.html
//myapp/templates/home.html
{% extends "base.html" %} 

{% block pageContent %}
<section class="text-center">
    <h4 class="mb-5"><strong>All Posts</strong></h4>
    <div class="row">
        {% for post in posts %}
        <div class="col-lg-4 col-md-6 mb-4">
            <div class="card shadow border">
                <div class="bg-image hover-overlay ripple" data-mdb-ripple-color="light">
                    <img src="{% if post.banner %}{{ post.banner.url }}{% else %}{{ MEDIA_URL}}/media/default/python-django.png{% endif %}" class="img-fluid post-banner bg-gradient bg-dark" />
                    <a href="#!">
                        <div class="mask" style="background-color: rgba(251, 251, 251, 0.15);"></div>
                    </a>
                </div>
                <div class="card-body">
                    <h5 class="card-title">{{ post.title }}</h5>
                    <div class="card-text truncate-3">{{ post.blog_post|safe }} </div>
                    <a href="{% url 'view-post' post.id %}" class="btn btn-primary">Read</a>
                </div>
            </div>
        </div>
        {% endfor %}


    </div>
    {% if not posts %}
    <center>No Bogs has been posted yet</center>
    {% endif %}
</section>
</div>  
{% endblock pageContent %}
myapp/templates/base.html
//myapp/templates/base.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
    {% if page_title %}
    <title>{{ page_title }} | Blog Site</title>
    {% else %}
    <title>Blog Site</title>
    {% endif %}
    <link rel="stylesheet" href="{% static 'blogApp/assets/bootstrap/css/bootstrap.min.css' %}">
</head>
<body>
    {% block TopNavigation %} {% include "TopNavigation.html" %} {% endblock TopNavigation %}
    <main class="my-5">
        <div class="container" style="padding-top: 50px;">
            {% block pageContent %} {% endblock pageContent %}
        </div>
    </main>
    {% block ScriptBlock %} {% endblock ScriptBlock %}
    <footer class="bg-light text-lg-start">
        <div class="text-center p-3" style="background-color: rgba(0, 0, 0, 0.2);">
            © {% now 'Y' %} Copyright:
            <a class="text-dark" href="#" target="_blank">Cairocoders</a>
        </div>
    </footer>
</body>
</html>
myapp/templates/TopNavigation.html
//myapp/templates/TopNavigation.html
{% load static %}
<header>
    <nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top">
        <div class="container">
            <a class="navbar-brand" target="_blank" href="#">Cairocoders</a>
            <button class="navbar-toggler" type="button" data-mdb-toggle="collapse" data-mdb-target="#navbarExample01" aria-controls="navbarExample01" aria-expanded="false" aria-label="Toggle navigation">
            <i class="fas fa-bars"></i>
            </button>
            <div class="collapse navbar-collapse" id="navbarExample01">
                <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                    <li class="nav-item active">
                        <a class="nav-link" aria-current="page" href="{% url 'home-page' %}">Home</a>
                    </li>
                    {% for category in category_list_limited %}
                    <li class="nav-item">
                        <a class="nav-link" href="{% url 'category-post' category.pk %}">{{ category.name }}</a>
                    </li>
                    {% endfor %}
                    <li class="nav-item">
                        <a class="nav-link" href="{% url 'category-page' %}">All Categories</a>
                    </li>
                </ul>

                <ul class="navbar-nav d-flex flex-row">
                    {% if user.id %}
                    <li class="nav-item me-3 me-lg-0">
                        Hello, {{ user.first_name }} {{user.last_name}}
                    </li>
                    <li class="nav-item me-3 me-lg-0">
                        <a class="nav-link" href="{% url 'logout' %}">Logout</a>
                    </li>
                    {% endif %}
                </ul>
            </div>
        </div>
    </nav>
</header>
myapp/templates/view_post.html
//myapp/templates/view_post.html
{% extends "base.html" %} 

{% block pageContent %}
<section class="text-center">
    <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
        <div class="row justify-content-center">
            <div class=" col-lg-12 col-md-12 col-sm-12 col-xs-12 card card-default rounded-0 shadow">
                <div class="card-body">
                    <center>
                        <img src="{% if post.banner %}{{ post.banner.url }}{% else %}{{ MEDIA_URL}}/media/default/python-django.png{% endif %}" alt="" class="img-fluid bg-gradient" id="view-post-banner">
                    </center>
                    <h4 class="fw-bolder mt-4 text-start">{{ post.title }}</h4>
                    <hr>
                    <div class="lh-1 text-start">
                        <span class="me-5"><small>Author: <b>{{ post.author }}</b></small></span>
                        <span class="me-5"><small>Category: <b>{{ post.category }}</b></small></span>
                        <span><small><i class="fa fa-calendar-day"></i> Published: <b>{{ post.date_added|date:"F d, Y h:i A" }}</b></small></span>

                    </div>
                    <div class="clear-fix py-3"></div>
                    <div>{{ post.blog_post|safe }}</div>
                </div>
            </div>
        </div>
    </div>
</section>
</div>
{% endblock pageContent %}
myapp/templates/by_categories.html
//myapp/templates/by_categories.html
{% extends "base.html" %} 

{% block pageContent %}
<section class="text-center">
    <h4 class="mb-5"><strong>'{{ category }}' Posts</strong></h4>

    <div class="row">
        {% for post in posts %}
        <div class="col-lg-4 col-md-6 mb-4">
            <div class="card shadow border">
                <div class="bg-image hover-overlay ripple" data-mdb-ripple-color="light">
                    <img src="{% if post.banner %}{{ post.banner.url }}{% else %}{{ MEDIA_URL}}/media/default/python-django.png{% endif %}" class="img-fluid post-banner bg-gradient bg-dark" />
                    <a href="#!">
                        <div class="mask" style="background-color: rgba(251, 251, 251, 0.15);"></div>
                    </a>
                </div>
                <div class="card-body">
                    <h5 class="card-title">{{ post.title }}</h5>
                    <div class="card-text truncate-3">{{ post.blog_post|safe }} </div>
                    <a href="{% url 'view-post' post.id %}" class="btn btn-primary">Read</a>
                </div>
            </div>
        </div>
        {% endfor %}


    </div>
    {% if not posts %}
    <center>No Bogs has been posted yet</center>
    {% endif %}

</section>
</div>
{% endblock pageContent %}
myapp/templates/categories.html
//myapp/templates/categories.html
{% extends 'base.html' %} {% block pageContent %}
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
    <div class="card card-default rounded-0 shadow ">
        <div class="card-header">
            <div class="d-flex w-100 align-items-center justify-content-between">
                <h4 class="card-title fw-bold">Category Management</h4>

            </div>
        </div>
        <div class="card-body">
            <div class="container-fluid">
                <div id="list" class="list-group">
                    {% for category in categories %}
                    <a href="{% url 'category-post' category.id %}" class="list-group-item list-group-item-action">
                        <h4><b>{{ category.name }}</b></h4>
                        <hr>
                        <p>{{ category.description }}</p>
                    </a>
                    {% endfor %}
                </div>
                {% if not categories %}
                <center>No Category Listed Yet</center>
                {% endif %}
            </div>
        </div>
    </div>
</div>
{% endblock pageContent %} 
myapp/admin.py
 
//myapp/admin.py
import django
from django.contrib import admin
from myapp.models import Category, Post
from django_summernote.admin import SummernoteModelAdmin

# Register your models here.
admin.site.register(Category)
#admin.site.register(Post)

class PostAdmin(SummernoteModelAdmin):
    summernote_fields = ('blog_post',)
  
admin.site.register(Post, PostAdmin)
Run : C:\django\blogsite>python manage.py runserver

Saturday, June 25, 2022

Python Django Image Crop and Upload Crop Image with javascript ajax

Python Django Image Crop and Upload Crop Image with javascript ajax

Register App myapp

devproject/settings.py
 
//devproject/settings.py
   
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp', #add myapp
]
Creating View
myapp/views.py
 
//myapp/views.py
from django.shortcuts import render
from .forms import ImageForm
from django.http import JsonResponse

def index(request):
    form = ImageForm(request.POST or None, request.FILES or None)
    if form.is_valid():
        form.save()
        return JsonResponse({'message': 'works'})
    context = {'form': form}
    return render(request, 'main.html', context)
devproject/urls.py
 
//devproject/urls.py
from django.contrib import admin
from django.urls import path, include

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('myapp.urls'))
]

urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
myapp/urls.py
 
//myapp/urls.py
from django.urls import path
 
from . import views
 
urlpatterns = [
    path('', views.index, name='index'),
]
Make Migrations
Run the commands below to make migrations:
python manage.py makemigrations
python manage.py migrate
C:\django\devproject>python manage.py makemigrations
C:\django\devproject>python manage.py migrate
myapp/models.py
 
//myapp/models.py
from django.db import models

class Image(models.Model):
    file = models.ImageField(upload_to='images')
    uploaded = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return str(self.pk)
myapp/forms.py
 
//myapp/forms.py
from django import forms
from .models import Image

class ImageForm(forms.ModelForm):
    class Meta:
        model = Image
        fields = ('file',) 
Bootstrap 5
https://getbootstrap.com/docs/5.0/getting-started/introduction/
https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css

Jquery
https://jquery.com/download/
CDN : jsDelivr CDN
https://www.jsdelivr.com/package/npm/jquery
https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js

Cropper
A simple jQuery image cropping plugin.
https://fengyuanchen.github.io/cropper/
CDN : https://cdnjs.com/libraries/cropper
myapp/templates/home.html
//myapp/templates/home.html
{% extends 'base.html' %}

{% block content %}
<div class="container py-5">
    <header class="text-white text-center">
        <h1 class="display-4">Python Django Image Crop and Upload Crop Image with javascript ajax</h1>
    </header>

    <div class="row py-4">
        <div class="col-lg-6 mx-auto">
            <div class="input-group mb-3 px-4 py-2 rounded-pill bg-white shadow-sm">
                <form action="" id="image-form" style="padding-top:10px;">
                    {% csrf_token %}
                    {{form.as_p}}
                </form>
            </div>
            <div id="alert-box"></div>
            <div class="image-area mb-3"><div id="image-box"></div></div>
            <button class="btn btn-primary mt-3 not-visible" id="confirm-btn">Confirm</button>
        </div>
    </div>
</div>
<style>
#upload {
    opacity: 0;
}
.image-area {
    border: 2px dashed rgba(255, 255, 255, 0.7);
    padding: 1rem;
}
body {
    min-height: 100vh;
    background-color: #7b9a75;
    background-image: linear-gradient(147deg, #7b9a75 0%, #d7dde8 100%);
}
</style>    
{% endblock content %}
myapp/templates/base.html
 
//myapp/templates/base.html
{% load static %}
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="shortcut icon" type="image/png" href="{% static 'favicon.ico' %}"/>
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"/>

    <!-- jquery -->
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>

    <!-- cropper -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/cropper/4.1.0/cropper.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropper/4.1.0/cropper.min.css">
    <title>Python Django Image Crop and Upload Crop Image with javascript ajax</title>
<style>
.not-visible {
    display: none;
}
</style>
</head>
<body>
    <div class="container">
        {% block content %}
        {% endblock content %}
    </div>

<script>
const alertBox = document.getElementById('alert-box')
const imageBox = document.getElementById('image-box')
const imageForm = document.getElementById('image-form')
const confirmBtn = document.getElementById('confirm-btn')
const input = document.getElementById('id_file')

const csrf = document.getElementsByName('csrfmiddlewaretoken')

input.addEventListener('change', ()=>{
    alertBox.innerHTML = ""
    confirmBtn.classList.remove('not-visible')
    const img_data = input.files[0]
    const url = URL.createObjectURL(img_data)

    imageBox.innerHTML = `<img src="${url}" id="image" width="700px">`
    var $image = $('#image')
    console.log($image)

    $image.cropper({
        aspectRatio: 16 / 9,
        crop: function(event) {
            console.log(event.detail.x);
            console.log(event.detail.y);
            console.log(event.detail.width);
            console.log(event.detail.height);
            console.log(event.detail.rotate);
            console.log(event.detail.scaleX);
            console.log(event.detail.scaleY);
        }
    });
    
    var cropper = $image.data('cropper');
    confirmBtn.addEventListener('click', ()=>{
        cropper.getCroppedCanvas().toBlob((blob) => {
            console.log('confirmed')
            const fd = new FormData();
            fd.append('csrfmiddlewaretoken', csrf[0].value)
            fd.append('file', blob, 'my-image.png');

            $.ajax({
                type:'POST',
                url: imageForm.action,
                enctype: 'multipart/form-data',
                data: fd,
                success: function(response){
                    console.log('success', response)
                    alertBox.innerHTML = `<div class="alert alert-success" role="alert">
                                            Successfully saved and cropped the selected image
                                        </div>`
                },
                error: function(error){
                    console.log('error', error)
                    alertBox.innerHTML = `<div class="alert alert-danger" role="alert">
                                            Ups...something went wrong
                                        </div>`
                },
                cache: false,
                contentType: false,
                processData: false,
            })
        })
    })
})
</script>
</body>
</html>
Run : C:\django\devsite>python manage.py runserver

Tuesday, June 21, 2022

Python Django Dependent Chained Dropdown List - Dynamic Dependent Select Box using jQuery Ajax

Python Django Dependent Chained Dropdown List - Dynamic Dependent Select Box using jQuery Ajax

Register App myapp
 
//devproject/settings.py
  
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp', #add myapp
]
Creating View
myapp/views.py
 
//myapp/views.py
  
from django.shortcuts import render, redirect, get_object_or_404

from .forms import MemberCreationForm
from .models import Member, City

def create_view(request):
    form = MemberCreationForm()
    if request.method == 'POST':
        form = MemberCreationForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('add')
    return render(request, 'home.html', {'form': form})

def update_view(request, pk):
    member = get_object_or_404(Member, pk=pk)
    form = MemberCreationForm(instance=member)
    if request.method == 'POST':
        form = MemberCreationForm(request.POST, instance=member)
        if form.is_valid():
            form.save()
            return redirect('change', pk=pk)
    return render(request, 'home.html', {'form': form})

# AJAX
def load_cities(request):
    country_id = request.GET.get('country_id')
    cities = City.objects.filter(country_id=country_id).all()
    return render(request, 'city_dropdown_list_options.html', {'cities': cities})
devproject/urls.py
 
//devproject/urls.py
  
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('myapp.urls'))
]
myapp/urls.py
 
//myapp/urls.py
  
from django.urls import path

from . import views

urlpatterns = [
    path('member/add/', views.create_view, name='add'),
    path('member/<int:pk>/', views.update_view, name='change'),

    path('member/ajax/load-cities/', views.load_cities, name='ajax_load_cities'), # AJAX
]
myapp/forms.py
 
//myapp/forms.py
  
from django import forms

from myapp.models import Member, City

class MemberCreationForm(forms.ModelForm):
    class Meta:
        model = Member
        fields = '__all__'
        widgets = { 'name': forms.TextInput(attrs={ 'class': 'form-control' }), 
            'email': forms.EmailInput(attrs={ 'class': 'form-control' }),
            'country': forms.Select(attrs={ 'class': 'form-select' }),
            'city': forms.Select(attrs={ 'class': 'form-select' }),
        }    

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['city'].queryset = City.objects.none()

        if 'country' in self.data:
            try:
                country_id = int(self.data.get('country'))
                self.fields['city'].queryset = City.objects.filter(country_id=country_id).order_by('name')
            except (ValueError, TypeError):
                pass  # invalid input from the client; ignore and fallback to empty City queryset
        elif self.instance.pk:
            self.fields['city'].queryset = self.instance.country.city_set.order_by('name')
Make Migrations
Run the commands below to make migrations:
python manage.py makemigrations
python manage.py migrate
C:\django\devproject>python manage.py makemigrations
C:\django\devproject>python manage.py migrate
myapp/models.py
 
//myapp/models.py
  
from django.db import models

class Country(models.Model):
    name = models.CharField(max_length=40)

    def __str__(self):
        return self.name

class City(models.Model):
    country = models.ForeignKey(Country, on_delete=models.CASCADE)
    name = models.CharField(max_length=40)

    def __str__(self):
        return self.name

class Member(models.Model):
    name = models.CharField(max_length=124)
    email = models.CharField(max_length=125)
    country = models.ForeignKey(Country, on_delete=models.SET_NULL, blank=True, null=True)
    city = models.ForeignKey(City, on_delete=models.SET_NULL, blank=True, null=True)

    def __str__(self):
        return self.name
myapp/admin.py
 
//myapp/admin.py
  
from django.contrib import admin

# Register your models here.
from myapp.models import City, Country, Member

admin.site.register(City)
admin.site.register(Country)
admin.site.register(Member)
Bootstrap 5
https://getbootstrap.com/docs/5.0/getting-started/introduction/
https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css

Jquery
https://jquery.com/download/
CDN : jsDelivr CDN
https://www.jsdelivr.com/package/npm/jquery
https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js

myapp/templates/home.html
//myapp/templates/home.html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Dependent Dropdown in Django</title>
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css">
</head>
<body>
<div class="container"> <p><h1>Python Django Dependent Chained Dropdown List - Dynamic Dependent Select Box using jQuery Ajax</h1></p> 
    <div class="card">
        <div class="card-header">
            Member Form
        </div>
        <div class="card-body">
            <form method="post" id="MemberForm" data-cities-url="{% url 'ajax_load_cities' %}" class="form-horizontal" role="form">
                {% csrf_token %}
                {{ form.as_p }}
                <input type="submit" value="Submit" class="btn btn-info">
            </form>
        </div>
      </div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
    $("#id_country").change(function () {
        const url = $("#MemberForm").attr("data-cities-url");  // get the url of the `load_cities` view
        const countryId = $(this).val();  // get the selected country ID from the HTML input

        $.ajax({                       // initialize an AJAX request
            url: url,                    // set the url of the request (= /members/ajax/load-cities/ )
            data: {
                'country_id': countryId       // GET parameters
            },
            success: function (data) {   
                $("#id_city").html(data); 
            }
        });

    });
</script>
</body>
</html>
myapp/templates/city_dropdown_list_options.html
//myapp/templates/city_dropdown_list_options.html
<option value="">---------</option>
{% for city in cities %}
<option value="{{ city.pk }}">{{ city.name }}</option>
{% endfor %}
Run : C:\django\devsite>python manage.py runserver

Sunday, June 19, 2022

Python Django Load More Data using jquery Ajax

Python Django Load More Data using jquery Ajax

Register App
 
//blogsite/settings.py
  
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp', #add myapp
]
Creating View
Bootstrap 4 
https://getbootstrap.com/docs/4.5/getting-started/introduction/
https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.cs

Jquery
https://jquery.com/download/
CDN : jsDelivr CDN
https://www.jsdelivr.com/package/npm/jquery
https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js
myapp/templates/base.html
 
#myapp/templates/base.html
{% load static %}
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
    <title>Python Django Load More Data using jquery Ajax</title>
</head>
<body>
<div class="container mt-3">
    <p><h1>Python Django Load More Data using jquery Ajax</h1></p>
    {% block content %}{% endblock content %}
</div>
<script>
const postsBox = document.getElementById('posts-box')
console.log(postsBox)
const spinnerBox = document.getElementById('spinner-box')
const loadBtn = document.getElementById('load-btn')
const loadBox = document.getElementById('loading-box')
let visible = 3 

const handleGetData = () => {
    $.ajax({
        type: 'GET',
        url: `/posts-json/${visible}/`,
        success: function(response){
            maxSize = response.max
            const data = response.data
            spinnerBox.classList.remove('not-visible')
            setTimeout(()=>{
                spinnerBox.classList.add('not-visible')
                data.map(post=>{
                    console.log(post.id)
                    postsBox.innerHTML += `<div class="card p-3 mt-3 mb-3">
                                                ${post.post_title}
                                                <br>
                                                ${post.post_content}
                                            </div>`
                })
                if(maxSize){
                    console.log('done')
                    loadBox.innerHTML = "<h4>No more posts to load</h4>"
                }
            }, 500)
        },
        error: function(error){
            console.log(error)
        }
    })
}

handleGetData()

loadBtn.addEventListener('click', ()=>{
    visible += 3
    handleGetData()
})
</script>
<style>
    .not-visible {
        display: none;
    }
</style>    
</body>
</html>
myapp/templates/main.html
#myapp/templates/main.html
{% extends "base.html" %}

{% block content %}
    <div id="posts-box"></div>
    <div id="spinner-box" class="not-visible">
        <div class="spinner-border text-primary" role="status"></div>
    </div>
    <div id="loading-box">
        <button class="btn btn-primary" id="load-btn">Load more</button>
    </div>
{% endblock content %}
Model
Make Migrations
Run the commands below to make migrations:
python manage.py makemigrations
python manage.py migrate
C:\django\blogsite>python manage.py makemigrations
C:\django\blogsite>python manage.py migrate
myapp/models.py
#myapp/models.py
from django.db import models

# Create your models here.
class Post(models.Model):
    post_title = models.CharField(max_length=200)
    post_content = models.TextField()
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return str(self.pk)

    class Meta:
        ordering = ('-created',)
myapp/views.py
 
#myapp/views.py
from django.shortcuts import render
from django.views.generic import View, TemplateView
from .models import Post
from django.http import JsonResponse

class MainView(TemplateView):
    template_name = 'main.html'

class PostJsonListView(View):
    def get(self, *args, **kwargs):
        print(kwargs)
        upper = kwargs.get('num_posts')
        lower = upper - 3 
        posts = list(Post.objects.values()[lower:upper])
        posts_size = len(Post.objects.all())
        max_size = True if upper >= posts_size else False
        return JsonResponse({'data': posts, 'max': max_size}, safe=False)	
blogsite/urls.py
 
#blogsite/urls.py
from django.contrib import admin
from django.urls import path

from myapp.views import MainView, PostJsonListView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', MainView.as_view(), name='main-view'),
    path('posts-json/<int:num_posts>/', PostJsonListView.as_view(), name='posts-json-view'),
]
Run : C:\django\blogsite>python manage.py runserver

Friday, June 17, 2022

Python Django Ajax Login Register User Authentication with Profile and Upload Photo

Python Django Ajax Login Register User Authentication with Profile and Upload Photo

Register App myapp and static file

 
//blogsite/settings.py
import os
 
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp', #add myapp
]
 
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.0/howto/static-files/
 
STATIC_URL = 'static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATICFILES_DIRS = (
    # location of your application, should not be public web accessible 
    './static',
)
 
LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/login'
Creating View
myapp/views.py
 
//myapp/views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.urls import reverse
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.decorators import login_required
import json
from django.contrib.auth.models import User
from django.contrib import messages

from myapp.models import UserProfile
from myapp.forms import UserRegistration, UpdateProfile, UpdateProfileMeta, UpdateProfileAvatar, AddAvatar

context = {
    'page_title' : 'Blog Site'
}

# Create your views here.
def home(request):
    context['page_title'] = 'Home'
    return render(request, 'home.html',context)

def login_user(request):
    logout(request)
    resp = {"status":'failed','msg':''}
    username = ''
    password = ''
    if request.POST:
        username = request.POST['username']
        password = request.POST['password']

        user = authenticate(username=username, password=password)
        if user is not None:
            if user.is_active:
                login(request, user)
                resp['status']='success'
            else:
                resp['msg'] = "Incorrect username or password"
        else:
            resp['msg'] = "Incorrect username or password"
    return HttpResponse(json.dumps(resp),content_type='application/json')

#Logout
def logoutuser(request):
    logout(request)
    return redirect('/')

def registerUser(request):
    user = request.user
    if user.is_authenticated:
        return redirect('home-page')
    context['page_title'] = "Register User"
    if request.method == 'POST':
        data = request.POST
        form = UserRegistration(data)
        if form.is_valid():
            form.save()
            newUser = User.objects.all().last()
            try:
                profile = UserProfile.objects.get(user = newUser)
            except:
                profile = None
            if profile is None:
                UserProfile(user = newUser, dob= data['dob'], contact= data['contact'], address= data['address'], avatar = request.FILES['avatar']).save()
            else:
                UserProfile.objects.filter(id = profile.id).update(user = newUser, dob= data['dob'], contact= data['contact'], address= data['address'])
                avatar = AddAvatar(request.POST,request.FILES, instance = profile)
                if avatar.is_valid():
                    avatar.save()
            username = form.cleaned_data.get('username')
            pwd = form.cleaned_data.get('password1')
            loginUser = authenticate(username= username, password = pwd)
            login(request, loginUser)
            return redirect('home-page')
        else:
            context['reg_form'] = form

    return render(request,'register.html',context)

@login_required
def profile(request):
    context = {
        'page_title':"My Profile"
    }

    return render(request,'profile.html',context)

@login_required
def update_profile(request):
    context['page_title'] = "Update Profile"
    user = User.objects.get(id= request.user.id)
    profile = UserProfile.objects.get(user= user)
    context['userData'] = user
    context['userProfile'] = profile
    if request.method == 'POST':
        data = request.POST
        form = UpdateProfile(data, instance=user)
        if form.is_valid():
            form.save()
            form2 = UpdateProfileMeta(data, instance=profile)
            if form2.is_valid():
                form2.save()
                messages.success(request,"Your Profile has been updated successfully")
                return redirect("profile")
            else:
                context['form2'] = form2
        else:
            context['form1'] = form
            form = UpdateProfile(instance=request.user)
    return render(request,'update_profile.html',context)


@login_required
def update_avatar(request):
    context['page_title'] = "Update Avatar"
    user = User.objects.get(id= request.user.id)
    context['userData'] = user
    context['userProfile'] = user.profile
    img = user.profile.avatar.url

    context['img'] = img
    if request.method == 'POST':
        form = UpdateProfileAvatar(request.POST, request.FILES,instance=user)
        if form.is_valid():
            form.save()
            messages.success(request,"Your Profile has been updated successfully")
            return redirect("profile")
        else:
            context['form'] = form
            form = UpdateProfileAvatar(instance=user)
    return render(request,'update_avatar.html',context)
blogsite/urls.py
 
//blogsite/urls.py
from django.contrib import admin
from django.urls import include, path
 
from django.conf import settings
from django.conf.urls.static import static
 
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('myapp.urls')),
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
myapp/urls.py
 
//myapp/urls.py
from . import views
from django.contrib import admin
from django.urls import path, re_path
from django.contrib.auth import views as auth_views
from django.views.generic.base import RedirectView

urlpatterns = [
    path('redirect-admin', RedirectView.as_view(url="/admin"),name="redirect-admin"),
    path('', views.home, name="home-page"),
    path('login',auth_views.LoginView.as_view(template_name="login.html",redirect_authenticated_user = True),name='login'),
    path('userlogin', views.login_user, name="login-user"),
    path('user-register', views.registerUser, name="register-user"),
    path('logout',views.logoutuser,name='logout'),
    path('profile',views.profile,name='profile'),
    path('update-profile',views.update_profile,name='update-profile'),
    path('update-avatar',views.update_avatar,name='update-avatar'),
]
Make Migrations
Run the commands below to make migrations:
python manage.py makemigrations
python manage.py migrate
C:\django\blogsite>python manage.py makemigrations
C:\django\blogsite>python manage.py migrate
myapp/models.py
 
//myapp/models.py
from django.db import models
from django.contrib.auth.backends import BaseBackend
from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE,related_name='profile')
    contact = models.CharField(max_length=250)
    dob = models.DateField(blank=True, null = True)
    address = models.TextField(blank=True, null = True)
    avatar = models.ImageField(blank=True, null = True, upload_to= 'images/')
    user_type = models.IntegerField(default = 2)


    def __str__(self):
        return self.user.username

def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)

def save_user_profile(sender, instance, **kwargs):
    print(instance)
    try:
        profile = UserProfile.objects.get(user = instance)
    except Exception as e:
        UserProfile.objects.create(user=instance)
    instance.profile.save()
myapp/forms.py
 
//myapp/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm

from django.contrib.auth.models import User
from myapp.models import UserProfile

class UserRegistration(UserCreationForm):
    email = forms.EmailField(max_length=250,help_text="The email field is required.")
    first_name = forms.CharField(max_length=250,help_text="The First Name field is required.")
    last_name = forms.CharField(max_length=250,help_text="The Last Name field is required.")

    class Meta:
        model = User
        fields = ('email', 'username', 'password1', 'password2', 'first_name', 'last_name')
    

    def clean_email(self):
        email = self.cleaned_data['email']
        try:
            user = User.objects.get(email = email)
        except Exception as e:
            return email
        raise forms.ValidationError(f"The {user.email} mail is already exists/taken")

    def clean_username(self):
        username = self.cleaned_data['username']
        try:
            user = User.objects.get(username = username)
        except Exception as e:
            return username
        raise forms.ValidationError(f"The {user.username} mail is already exists/taken")

class UpdateProfile(forms.ModelForm):
    username = forms.CharField(max_length=250,help_text="The Username field is required.")
    email = forms.EmailField(max_length=250,help_text="The Email field is required.")
    first_name = forms.CharField(max_length=250,help_text="The First Name field is required.")
    last_name = forms.CharField(max_length=250,help_text="The Last Name field is required.")
    current_password = forms.CharField(max_length=250)

    class Meta:
        model = User
        fields = ('email', 'username','first_name', 'last_name')

    def clean_current_password(self):
        if not self.instance.check_password(self.cleaned_data['current_password']):
            raise forms.ValidationError(f"Password is Incorrect")

    def clean_email(self):
        email = self.cleaned_data['email']
        try:
            user = User.objects.exclude(id=self.cleaned_data['id']).get(email = email)
        except Exception as e:
            return email
        raise forms.ValidationError(f"The {user.email} mail is already exists/taken")

    def clean_username(self):
        username = self.cleaned_data['username']
        try:
            user = User.objects.exclude(id=self.cleaned_data['id']).get(username = username)
        except Exception as e:
            return username
        raise forms.ValidationError(f"The {user.username} mail is already exists/taken")
       

class UpdateProfileMeta(forms.ModelForm):
    dob = forms.DateField(help_text="The Birthday field is required.")
    contact = forms.CharField(max_length=250,help_text="The Contact field is required.")
    address = forms.CharField(help_text="The Contact field is required.")

    class Meta:
        model = UserProfile
        fields = ('dob', 'contact', 'address')

class UpdateProfileAvatar(forms.ModelForm):
    avatar = forms.ImageField(help_text="The Avatar field is required.")
    current_password = forms.CharField(max_length=250)

    class Meta:
        model = UserProfile
        fields = ('avatar',)
    
    def __init__(self,*args, **kwargs):
        self.user = kwargs['instance']
        kwargs['instance'] = self.user.profile
        super(UpdateProfileAvatar,self).__init__(*args, **kwargs)

    def clean_current_password(self):
        if not self.user.check_password(self.cleaned_data['current_password']):
            raise forms.ValidationError("Password is Incorrect")


class AddAvatar(forms.ModelForm):
    avatar = forms.ImageField(help_text="The Avatar field is required.")
    class Meta:
        model = UserProfile
        fields = ('avatar',)
myapp/admin.py
 
//myapp/admin.py
import django
from django.contrib import admin
from myapp.models import UserProfile

# Register your models here.
admin.site.register(UserProfile)
myapp/templates/home.html
 
//myapp/templates/home.html
{% extends "base.html" %} 

{% block pageContent %}
<section class="text-center">
    <h4 class="mb-5"><strong>All Posts</strong></h4>
    <div class="row">
        <h1>Homepage - Python Django Ajax Login Register User Authentication with Profile and Upload Photo </h1>
    </div>
</section>
</div>  
{% endblock pageContent %}
myapp/templates/base.html
 
//myapp/templates/base.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
    {% if page_title %}
    <title>{{ page_title }} | Blog Site</title>
    {% else %}
    <title>Blog Site</title>
    {% endif %}
    <link rel="stylesheet" href="{% static 'blogApp/assets/bootstrap/css/bootstrap.min.css' %}">

    <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
</head>
<body>
    {% block TopNavigation %} {% include "TopNavigation.html" %} {% endblock TopNavigation %}
    <main class="my-5">
        <div class="container" style="padding-top: 50px;">
            {% block pageContent %} {% endblock pageContent %}
        </div>
    </main>
    {% block ScriptBlock %} {% endblock ScriptBlock %}
    <footer class="bg-light text-lg-start">
        <div class="text-center p-3" style="background-color: rgba(0, 0, 0, 0.2);">
            © {% now 'Y' %} Copyright:
            <a class="text-dark" href="#" target="_blank">Cairocoders</a>
        </div>
    </footer>

</body>
</html>
myapp/templates/login.html
//myapp/templates/login.html
{% extends 'base.html' %}

{% load static %}

{% block pageContent %} 
<div class="row justify-content-center">
    <div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
        <p><img src="{{ MEDIA_URL}}/media/images/banner1.png" class="img-fluid" /></p>
        <div class="card card-default rounded-0 shadow">
            <div class="card-header">
                <h4 class="card-title"><b>Login</b></h4>
            </div>
            <div class="card-body">
                <div class="container-fluid">
                    <form id="login-user">
                        {% csrf_token %}
                        <div class="mdc-layout-grid">
                            <div class="mdc-layout-grid__inner">
                                <div class="form-group mb-3">
                                    <label for="username" class="control-label">Username</label>
                                    <input type="text" class="form-control rounded-0" name="username" id="username" required="required">
                                </div>
                                <div class="form-group mb-3">
                                    <label for="password" class="control-label">Password</label>
                                    <input type="password" class="form-control rounded-0" name="password" id="password" required="required">
                                </div>
                                <div class="form-group mb-3">
                                    <div class="d-flex w-100 justify-content-between align-items-center">
                                        <div class="col-md-4"><a href="{% url 'register-user' %}">Signup</a></div>
                                        <button class="btn btn-sm rounded-0 btn-primary">Login</button>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock pageContent %} 

{% block ScriptBlock %}
<script>
    $(function() {
        $('#login-user').submit(function(e) {
            e.preventDefault();
            var _this = $(this)
            $('.err-msg').remove();
            var el = $('<div>')
            el.addClass("alert alert-danger err-msg")
            el.hide()
            if (_this[0].checkValidity() == false) {
                _this[0].reportValidity();
                return false;
            }
            $.ajax({
                headers: {
                    "X-CSRFToken": '{{csrf_token}}'
                },
                url: "{% url 'login-user' %}",
                data: new FormData($(this)[0]),
                cache: false,
                contentType: false,
                processData: false,
                method: 'POST',
                type: 'POST',
                dataType: 'json',
                error: err => {
                    console.log(err)
                    alert_toast("An error occured", 'error');
                },
                success: function(resp) {
                    if (typeof resp == 'object' && resp.status == 'success') {
                        el.removeClass("alert alert-danger err-msg")
                        location.href = "{% url 'home-page' %}"
                    } else if (resp.status == 'failed' && !!resp.msg) {
                        el.text(resp.msg)
                    } else {
                        el.text("An error occured", 'error');
                        console.err(resp)
                    }
                    _this.prepend(el)
                    el.show('slow')
                }
            })
        })
    })
</script>
{% endblock ScriptBlock %}
myapp/templates/TopNavigation.html
//myapp/templates/TopNavigation.html
{% load static %}
<header>
    <nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top">
        <div class="container">
            <a class="navbar-brand" target="_blank" href="#">Cairocoders</a>
            <button class="navbar-toggler" type="button" data-mdb-toggle="collapse" data-mdb-target="#navbarExample01" aria-controls="navbarExample01" aria-expanded="false" aria-label="Toggle navigation">
            <i class="fas fa-bars"></i>
            </button>
            <div class="collapse navbar-collapse" id="navbarExample01">
                <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                    <li class="nav-item active">
                        <a class="nav-link" aria-current="page" href="{% url 'home-page' %}">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#">All Categories</a>
                    </li>
                </ul>

                <ul class="navbar-nav d-flex flex-row">
                    {% if user.id %}
                    <li class="nav-item me-3 me-lg-0">
                        <a class="nav-link" href="{% url 'profile' %}">
                            <span class="me-1"><img src="{{ user.profile.avatar.url }}" width="30" height="30" alt="User Avatar" id="user-avatar" class="img-thumbnail rounded-circle"></span>Howdy, {{ user.first_name }} {{user.last_name}}
                        </a>
                    </li>
                    <li class="nav-item me-3 me-lg-0">
                        <a class="nav-link" href="{% url 'logout' %}">Logout</a>
                    </li>
                    {% else %}
                    <li class="nav-item me-3 me-lg-0">
                        <a class="nav-link" href="{% url 'login' %}">Login</a>
                    </li>
                    {% endif %}
                </ul>
            </div>
        </div>
    </nav>
</header>
myapp/templates/register.html
 
//myapp/templates/register.html
{% extends 'base.html' %}
{% load static %}

{% block pageContent %}
<div class="row justify-content-center">
    <div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
        <div class="card card-default rounded-0 shadow">
            <div class="card-header">
                <h4 class="card-title"><b>Create New User</b></h4>
            </div>
            <div class="card-body">
                <div class="container-fluid">
                    <form id="register-user" method="POST" action="{% url 'register-user' %}" enctype="multipart/form-data">
                        {% csrf_token %}
                        <div class="mdc-layout-grid">
                            <div class="mdc-layout-grid__inner">
                                <div class="form-group mb-3">
                                    <label for="first_name" class="control-label">First Name</label>
                                    <input type="text" class="form-control rounded-0" name="first_name" id="first_name" value="{{ reg_form.data.first_name }}" required="required">
                                </div>
                                <div class="form-group mb-3">
                                    <label for="last_name" class="control-label">Last Name</label>
                                    <input type="text" class="form-control rounded-0" name="last_name" id="last_name" value="{{ reg_form.data.last_name }}" required="required">
                                </div>
                                <div class="form-group mb-3">
                                    <label for="dob" class="control-label">Birthdate</label>
                                    <input type="date" class="form-control rounded-0" name="dob" id="dob" value="{{ reg_form.data.dob }}" required="required">
                                </div>
                                <div class="form-group mb-3">
                                    <label for="contact" class="control-label">Contact</label>
                                    <input type="text" class="form-control rounded-0" name="contact" id="contact" value="{{ reg_form.data.contact }}" required="required">
                                </div>
                                <div class="form-group mb-3">
                                    <label for="address" class="control-label">Address</label>
                                    <textarea rows="3" class="form-control rounded-0" name="address" id="address" required="required">{{ reg_form.data.address }}</textarea>
                                </div>
                                <div class="form-group mb-3">
                                    <label for="email" class="control-label">Email</label>
                                    <input type="email" class="form-control rounded-0" name="email" id="email" value="{{ reg_form.data.email }}" required="required">
                                </div>
                                <div class="form-group mb-3">
                                    <label for="username" class="control-label">Username</label>
                                    <input type="text" class="form-control rounded-0" name="username" id="username" value="{{ reg_form.data.username }}" required="required">
                                </div>
                                <div class="form-group mb-3">
                                    <label for="password1" class="control-label">Password</label>
                                    <input type="password" class="form-control rounded-0" name="password1" id="password1" value="{{ reg_form.data.password1 }}" required="required">
                                </div>
                                <div class="form-group mb-3">
                                    <label for="password2" class="control-label">Confirm Password</label>
                                    <input type="password" class="form-control rounded-0" name="password2" id="password2" value="{{ reg_form.data.password2 }}" required="required">
                                </div>

                                <div class="form-group mb-3">
                                    <label for="avatar" class="control-label">User Avatar</label>
                                    <input type="file" class="form-control rounded-0" name="avatar" id="avatar" accept="images/*" required="required">
                                </div>
                                {% for field in reg_form %} {% for error in field.errors %}
                                <div class="alert alert-danger my-2">
                                    <p>{{ error }}</p>
                                </div>
                                {% endfor %} {% endfor %}
                                <div class="form-group mb-3">
                                    <div class="d-flex w-100 justify-content-end">
                                        <button class="btn btn-sm rounded-0 btn-primary col-4">Sign Up</button>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock pageContent %}
myapp/templates/profile.html
//myapp/templates/profile.html
{% extends 'base.html' %} 

{% block pageContent%}
<div class="container">
    <div class="row justify-content-center">
        <div class="col-lg-7 col-md-10 col-sm-12 col-xs-12">
            <div class="card shadow rounded-0">
                <div class="card-header">
                    <div class="h5 card-title fw-bold">My Profile</div>
                </div>
                <div class="card-body">
                    <div class="container-fluid">
                        <div class="row">
                            <div class="col-md-4">
                                <img src="{{ user.profile.avatar.url }}" alt="User-image" id="user-img-profile" class="img-thumbnail img-fluid">
                                <center><a href="{% url 'update-avatar'%}">Update Avatar</a></center>
                            </div>
                            <div class="col-md-8">
                                <dl>
                                    <dt class="text-muted">Fullname</dt>
                                    <dd class="ps-4">{{ user.first_name }} {{ user.last_name }}</dd>
                                    <dt class="text-muted">Birthday</dt>
                                    <dd class="ps-4">{{ user.profile.dob|date:"F d, Y" }}</dd>
                                    <dt class="text-muted">Contact #</dt>
                                    <dd class="ps-4">{{ user.profile.contact }}</dd>
                                    <dt class="text-muted">Address</dt>
                                    <dd class="ps-4">{{ user.profile.address }}</dd>
                                    <dt class="text-muted">Email</dt>
                                    <dd class="ps-4">{{ user.email }}</dd>
                                    <dt class="text-muted">Username</dt>
                                    <dd class="ps-4">{{ user.username }}</dd>
                                </dl>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="card-footer">
                    <div class="d-flex w-100 text-end justify-content-end">
                        <a href="{% url 'update-profile' %}" class="btn btn btn-primary btn-sm bg-gradient rounded-0">Update Profile</a>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock pageContent%}
myapp/templates/update_profile.html
//myapp/templates/update_profile.html
{% extends 'base.html' %}

{% load static %}

{% block pageContent %}
<div class="row justify-content-center">
    <div class="col-lg-8 col-md-10 col-sm-12 col-xs-12">
        <div class="card card-default rounded-0 shadow">
            <div class="card-header">
                <h4 class="card-title"><b>Update Profile</b></h4>
            </div>
            <div class="card-body">
                <div class="container-fluid">
                    <form id="register-user" method="POST" action="{% url 'update-profile' %}" enctype="multipart/form-data">
                        {% csrf_token %}
                        <div class="mdc-layout-grid">
                            <div class="mdc-layout-grid__inner">
                                <div class="row">
                                    <div class="col-md-6">
                                        <div class="form-group mb-3">
                                            <label for="first_name" class="control-label">First Name</label>
                                            <input type="text" class="form-control rounded-0" name="first_name" id="first_name" value="{{ userData.first_name }}" required="required">
                                        </div>
                                        <div class="form-group mb-3">
                                            <label for="last_name" class="control-label">Last Name</label>
                                            <input type="text" class="form-control rounded-0" name="last_name" id="last_name" value="{{ userData.last_name }}" required="required">
                                        </div>
                                        <div class="form-group mb-3">
                                            <label for="dob" class="control-label">Birthdate</label>
                                            <input type="date" class="form-control rounded-0" name="dob" id="dob" value="{{ userProfile.dob|date:'Y-m-d' }}" required="required">
                                        </div>
                                        <div class="form-group mb-3">
                                            <label for="contact" class="control-label">Contact</label>
                                            <input type="text" class="form-control rounded-0" name="contact" id="contact" value="{{ userProfile.contact }}" required="required">
                                        </div>
                                        <div class="form-group mb-3">
                                            <label for="address" class="control-label">Address</label>
                                            <textarea rows="3" class="form-control rounded-0" name="address" id="address" required="required">{{ userProfile.address }}</textarea>
                                        </div>
                                    </div>
                                    <div class="col-md-6">
                                        <div class="form-group mb-3">
                                            <label for="email" class="control-label">Email</label>
                                            <input type="email" class="form-control rounded-0" name="email" id="email" value="{{ userData.email }}" required="required">
                                        </div>
                                        <div class="form-group mb-3">
                                            <label for="username" class="control-label">Username</label>
                                            <input type="text" class="form-control rounded-0" name="username" id="username" value="{{ userData.username }}" required="required">
                                        </div>
                                        <div class="form-group mb-3">
                                            <label for="current_password" class="control-label">Current Password</label>
                                            <input type="password" class="form-control rounded-0" name="current_password" id="current_password" required="required">
                                        </div>
                                    </div>
                                </div>

                                {% for field in form1 %} {% for error in field.errors %}
                                <div class="alert alert-danger my-2">
                                    <p>{{ error }}</p>
                                </div>
                                {% endfor %} {% endfor %} {% for field in form2 %} {% for error in field.errors %}
                                <div class="alert alert-danger my-2">
                                    <p>{{ error }}</p>
                                </div>
                                {% endfor %} {% endfor %}
                                <div class="form-group mb-3">
                                    <div class="d-flex w-100 justify-content-end">
                                        <button class="btn btn-sm rounded-0 btn-primary col-4">
                                                Update
                                            </button>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock pageContent %}
myapp/templates/update_avatar.html
//myapp/templates/update_avatar.html
{% extends 'base.html' %}

{% load static %}

{% block pageContent %}
<div class="row justify-content-center">
    <div class="col-lg-8 col-md-10 col-sm-12 col-xs-12">
        <div class="card card-default rounded-0 shadow">
            <div class="card-header">
                <h4 class="card-title"><b>Update Profile</b></h4>
            </div>
            <div class="card-body">
                <div class="container-fluid">
                    <form id="register-user" method="POST" action="{% url 'update-avatar' %}" enctype="multipart/form-data">
                        {% csrf_token %}
                        <div class="mdc-layout-grid">
                            <div class="mdc-layout-grid__inner">
                                <div class="row">
                                    <div class="col-md-6">
                                        <img src="{{ img }}" alt="User-image" id="user-img-profile" class="img-thumbnail img-fluid">
                                    </div>
                                    <div class="col-md-6">
                                        <div class="form-group mb-3">
                                            <label for="avatar" class="control-label">Avatar</label>
                                            <input type="file" class="form-control rounded-0" name="avatar" id="avatar" accept="image/*" onchange="DisplayImage(this)" required="required">
                                        </div>
                                        <div class="form-group mb-3">
                                            <label for="current_password" class="control-label">Current Password</label>
                                            <input type="password" class="form-control rounded-0" name="current_password" id="current_password" required="required">
                                        </div>
                                    </div>
                                </div>

                                {% for field in form %} {% for error in field.errors %}
                                <div class="alert alert-danger my-2">
                                    <p>{{ error }}</p>
                                </div>
                                {% endfor %} {% endfor %}
                                <div class="form-group mb-3">
                                    <div class="d-flex w-100 justify-content-end">
                                        <button class="btn btn-sm rounded-0 btn-primary col-4">
                                                Update
                                            </button>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock pageContent %} {% block ScriptBlock %}
<script>
    function DisplayImage(input) {
        console.log(input.files)
        if (event.target.files[0]) {
            var reader = new FileReader();
            reader.onload = function() {
                var output = $('#user-img-profile');
                output.attr('src', reader.result)
            };
            reader.readAsDataURL(input.files[0]);
        }

    };
</script>
{% endblock ScriptBlock %}
Run : C:\django\blogsite>python manage.py runserver

Sunday, June 5, 2022

Python Django Ajax Login Logout User Authentication

Python Django Ajax Login Logout User Authentication

Register App myapp and static file
 
//blogsite/settings.py
import os

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp', #add myapp
]

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.0/howto/static-files/

STATIC_URL = 'static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATICFILES_DIRS = (
    # location of your application, should not be public web accessible 
    './static',
)

LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/login'
Creating View
myapp/views.py
 
//myapp/views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.contrib.auth import authenticate, login, logout
import json

context = {
    'page_title' : 'Blog Site'
}

# Create your views here.
def home(request):
    context['page_title'] = 'Home'
    return render(request, 'home.html',context)

def login_user(request):
    logout(request)
    resp = {"status":'failed','msg':''}
    username = ''
    password = ''
    if request.POST:
        username = request.POST['username']
        password = request.POST['password']

        user = authenticate(username=username, password=password)
        if user is not None:
            if user.is_active:
                login(request, user)
                resp['status']='success'
            else:
                resp['msg'] = "Incorrect username or password"
        else:
            resp['msg'] = "Incorrect username or password"
    return HttpResponse(json.dumps(resp),content_type='application/json')

#Logout
def logoutuser(request):
    logout(request)
    return redirect('/')
blogsite/urls.py
 
//blogsite/urls.py
from django.contrib import admin
from django.urls import include, path

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('myapp.urls')),
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
myapp/urls.py
 
//myapp/urls.py
from . import views
from django.contrib import admin
from django.urls import path, re_path
from django.contrib.auth import views as auth_views
from django.views.generic.base import RedirectView

urlpatterns = [
    path('redirect-admin', RedirectView.as_view(url="/admin"),name="redirect-admin"),
    path('', views.home, name="home-page"),
    path('login',auth_views.LoginView.as_view(template_name="login.html",redirect_authenticated_user = True),name='login'),
    path('userlogin', views.login_user, name="login-user"),
    path('logout',views.logoutuser,name='logout'),
]
myapp/templates/home.html
//myapp/templates/home.html
{% extends "base.html" %} 

{% block pageContent %}
<section class="text-center">
    <h4 class="mb-5"><strong>All Posts</strong></h4>
    <div class="row">
        <h1>Homepage - Python Django Ajax Login Logout User Authentication </h1>
    </div>
</section>
</div>  
{% endblock pageContent %}
myapp/templates/base.html
 
//myapp/templates/base.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
    {% if page_title %}
    <title>{{ page_title }} | Blog Site</title>
    {% else %}
    <title>Blog Site</title>
    {% endif %}
    <link rel="stylesheet" href="{% static 'blogApp/assets/bootstrap/css/bootstrap.min.css' %}">

    <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
</head>
<body>
    {% block TopNavigation %} {% include "TopNavigation.html" %} {% endblock TopNavigation %}
    <main class="my-5">
        <div class="container">
            {% block pageContent %} {% endblock pageContent %}
        </div>
    </main>
    {% block ScriptBlock %} {% endblock ScriptBlock %}
    <footer class="bg-light text-lg-start">
        <div class="text-center p-3" style="background-color: rgba(0, 0, 0, 0.2);">
            © {% now 'Y' %} Copyright:
            <a class="text-dark" href="#" target="_blank">Cairocoders</a>
        </div>
    </footer>

</body>
</html>
myapp/templates/login.html
//myapp/templates/login.html
{% extends 'base.html' %}

{% load static %}

{% block pageContent %}
<div class="row justify-content-center" style="margin-top: 150px;">
    <div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
        <p><img src="{{ MEDIA_URL}}/media/images/banner1.png" class="img-fluid" /></p>
        <div class="card card-default rounded-0 shadow">
            <div class="card-header">
                <h4 class="card-title"><b>Login</b></h4>
            </div>
            <div class="card-body">
                <div class="container-fluid">
                    <form id="login-user">
                        {% csrf_token %}
                        <div class="mdc-layout-grid">
                            <div class="mdc-layout-grid__inner">
                                <div class="form-group mb-3">
                                    <label for="username" class="control-label">Username</label>
                                    <input type="text" class="form-control rounded-0" name="username" id="username" required="required">
                                </div>
                                <div class="form-group mb-3">
                                    <label for="password" class="control-label">Password</label>
                                    <input type="password" class="form-control rounded-0" name="password" id="password" required="required">
                                </div>
                                <div class="form-group mb-3">
                                    <div class="d-flex w-100 justify-content-between align-items-center">
                                        <div class="col-md-4"><a href="#">Signup</a></div>
                                        <button class="btn btn-sm rounded-0 btn-primary">Login</button>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock pageContent %} 

{% block ScriptBlock %}
<script>
    $(function() {
        $('#login-user').submit(function(e) {
            e.preventDefault();
            var _this = $(this)
            $('.err-msg').remove();
            var el = $('<div>')
            el.addClass("alert alert-danger err-msg")
            el.hide()
            if (_this[0].checkValidity() == false) {
                _this[0].reportValidity();
                return false;
            }
            $.ajax({
                headers: {
                    "X-CSRFToken": '{{csrf_token}}'
                },
                url: "{% url 'login-user' %}",
                data: new FormData($(this)[0]),
                cache: false,
                contentType: false,
                processData: false,
                method: 'POST',
                type: 'POST',
                dataType: 'json',
                error: err => {
                    console.log(err)
                    alert_toast("An error occured", 'error');
                },
                success: function(resp) {
                    if (typeof resp == 'object' && resp.status == 'success') {
                        el.removeClass("alert alert-danger err-msg")
                        location.href = "{% url 'home-page' %}"
                    } else if (resp.status == 'failed' && !!resp.msg) {
                        el.text(resp.msg)
                    } else {
                        el.text("An error occured", 'error');
                        console.err(resp)
                    }
                    _this.prepend(el)
                    el.show('slow')
                }
            })
        })
    })
</script>
{% endblock ScriptBlock %}
myapp/templates/TopNavigation.html
 
//myapp/templates/TopNavigation.html
{% load static %}
<header>
    <nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top">
        <div class="container">
            <a class="navbar-brand" target="_blank" href="#">Cairocoders</a>
            <button class="navbar-toggler" type="button" data-mdb-toggle="collapse" data-mdb-target="#navbarExample01" aria-controls="navbarExample01" aria-expanded="false" aria-label="Toggle navigation">
            <i class="fas fa-bars"></i>
            </button>
            <div class="collapse navbar-collapse" id="navbarExample01">
                <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                    <li class="nav-item active">
                        <a class="nav-link" aria-current="page" href="{% url 'home-page' %}">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#">All Categories</a>
                    </li>
                </ul>

                <ul class="navbar-nav d-flex flex-row">
                    {% if user.id %}
                    <li class="nav-item me-3 me-lg-0">
                        <a class="nav-link" href="#">
                            Hello, {{ user.first_name }} {{user.last_name}}
                        </a>
                    </li>
                    <li class="nav-item me-3 me-lg-0">
                        <a class="nav-link" href="{% url 'logout' %}">Logout</a>
                    </li>
                    {% else %}
                    <li class="nav-item me-3 me-lg-0">
                        <a class="nav-link" href="{% url 'login' %}">Login</a>
                    </li>
                    {% endif %}
                </ul>
            </div>
        </div>
    </nav>
</header>
Run : C:\django\blogsite>python manage.py runserver

Saturday, May 21, 2022

Python Django Ajax FullCalender CRUD (Create, Read, Update and Delete) Mysql Database

Python Django Ajax FullCalender CRUD (Create, Read, Update and Delete) Mysql Database

Register App myapp and
Connect to MySQL Database

devproject/settings.py
 
//devproject/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp', #add myapp
]
       
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': 'localhost',
        'PORT': '3306'
    }
}
Create Model
myapp/models.py
 
//myapp/models.py
from django.db import models

# Create your models here.
class Events(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=255,null=True,blank=True)
    start = models.DateTimeField(null=True,blank=True)
    end = models.DateTimeField(null=True,blank=True)

    class Meta:  
        db_table = "tblevents"
Make Migrations
Run the commands below to make migrations:
python manage.py makemigrations
python manage.py migrate
C:\django\devproject>python manage.py makemigrations
C:\django\devproject>python manage.py migrate

Creating View
myapp/views.py
 
//myapp/views.py
from django.shortcuts import render
from django.http import JsonResponse 
from myapp.models import Events 

# Create your views here.
def index(request):  
    all_events = Events.objects.all()
    context = {
        "events":all_events,
    }
    return render(request,'index.html',context)

def all_events(request):                                                                                                 
    all_events = Events.objects.all()                                                                                    
    out = []                                                                                                             
    for event in all_events:                                                                                             
        out.append({                                                                                                     
            'title': event.name,                                                                                         
            'id': event.id,                                                                                              
            'start': event.start.strftime("%m/%d/%Y, %H:%M:%S"),                                                         
            'end': event.end.strftime("%m/%d/%Y, %H:%M:%S"),                                                             
        })                                                                                                               
                                                                                                                     
    return JsonResponse(out, safe=False) 

def add_event(request):
    start = request.GET.get("start", None)
    end = request.GET.get("end", None)
    title = request.GET.get("title", None)
    event = Events(name=str(title), start=start, end=end)
    event.save()
    data = {}
    return JsonResponse(data)

def update(request):
    start = request.GET.get("start", None)
    end = request.GET.get("end", None)
    title = request.GET.get("title", None)
    id = request.GET.get("id", None)
    event = Events.objects.get(id=id)
    event.start = start
    event.end = end
    event.name = title
    event.save()
    data = {}
    return JsonResponse(data)

def remove(request):
    id = request.GET.get("id", None)
    event = Events.objects.get(id=id)
    event.delete()
    data = {}
    return JsonResponse(data)
Template

myapp/templates/index.html

Bootstrap 5
https://getbootstrap.com/docs/5.0/getting-started/introduction/
https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css

Jquery
https://jquery.com/download/
CDN : jsDelivr CDN
https://www.jsdelivr.com/package/npm/jquery
https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js

https://fullcalendar.io/
CND : https://cdnjs.com/libraries/fullcalendar/3.9.0

/myapp/templates/index.html
 
//myapp/templates/index.html
{% extends "base.html" %}
  
{% block title %}Python Django Ajax FullCalender CRUD (Create, Read, Update and Delete){% endblock title %}
  
{% block content %}
<div class="col-md-12">    
    <div id='calendar'></div> 
</div> 
{% endblock content %} 
myapp/templates/base.html
//myapp/templates/base.html
<!DOCTYPE html>
<html>
<head>
    <title>Laravel 9 Ajax FullCalender CRUD (Create, Read, Update and Delete)</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
     
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.js"></script>
</head>
<body>
<div class="container">
 <div class="row">
    <h4>Python Django Ajax FullCalender CRUD (Create, Read, Update and Delete)</h4> 
    {% block content %}{% endblock %}
 </div>
</div>
<script>
   $(document).ready(function () {
       var calendar = $('#calendar').fullCalendar({
           header: {
               left: 'prev,next today',
               center: 'title',
               right: 'month,agendaWeek,agendaDay'
           },
           events: '/all_events',
           selectable: true,
           selectHelper: true,
           editable: true,
           eventLimit: true,
           select: function (start, end, allDay) {
               var title = prompt("Enter Event Title");
               if (title) {
                   var start = $.fullCalendar.formatDate(start, "Y-MM-DD HH:mm:ss");
                   var end = $.fullCalendar.formatDate(end, "Y-MM-DD HH:mm:ss");
                   $.ajax({
                       type: "GET",
                       url: '/add_event',
                       data: {'title': title, 'start': start, 'end': end},
                       dataType: "json",
                       success: function (data) {
                           calendar.fullCalendar('refetchEvents');
                           alert("Added Successfully");
                       },
                       error: function (data) {
                           alert('There is a problem!!!');
                       }
                   });
               }
           },
           eventResize: function (event) {
               var start = $.fullCalendar.formatDate(event.start, "Y-MM-DD HH:mm:ss");
               var end = $.fullCalendar.formatDate(event.end, "Y-MM-DD HH:mm:ss");
               var title = event.title;
               var id = event.id;
               $.ajax({
                   type: "GET",
                   url: '/update',
                   data: {'title': title, 'start': start, 'end': end, 'id': id},
                   dataType: "json",
                   success: function (data) {
                       calendar.fullCalendar('refetchEvents');
                       alert('Event Update');
                   },
                   error: function (data) {
                       alert('There is a problem!!!');
                   }
               });
           },

           eventDrop: function (event) {
               var start = $.fullCalendar.formatDate(event.start, "Y-MM-DD HH:mm:ss");
               var end = $.fullCalendar.formatDate(event.end, "Y-MM-DD HH:mm:ss");
               var title = event.title;
               var id = event.id;
               $.ajax({
                   type: "GET",
                   url: '/update',
                   data: {'title': title, 'start': start, 'end': end, 'id': id},
                   dataType: "json",
                   success: function (data) {
                       calendar.fullCalendar('refetchEvents');
                       alert('Event Update');
                   },
                   error: function (data) {
                       alert('There is a problem!!!');
                   }
               });
           },

           eventClick: function (event) {
               if (confirm("Are you sure you want to remove it?")) {
                   var id = event.id;
                   $.ajax({
                       type: "GET",
                       url: '/remove',
                       data: {'id': id},
                       dataType: "json",
                       success: function (data) {
                           calendar.fullCalendar('refetchEvents');
                           alert('Event Removed');
                       },
                       error: function (data) {
                           alert('There is a problem!!!');
                       }
                   });
               }
           },

       });
   });

</script>
</body>
</html>
URL devproject/urls.py
//devproject/urls.py
from django.contrib import admin
from django.urls import path
from myapp import views  

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.index, name='index'), 
    path('all_events/', views.all_events, name='all_events'), 
    path('add_event/', views.add_event, name='add_event'), 
    path('update/', views.update, name='update'),
    path('remove/', views.remove, name='remove'),
]
Run : C:\django\devproject>python manage.py runserver

Related Post