article

Saturday, July 18, 2020

How to Use Chart-js with Django using jquery Ajax Bar Chart Example


How to Use Chart-js with Django using jquery Ajax Bar Chart Example

Chart.js is a open source JavaScript library that helps you render HTML5 charts.

In this tutorial we are going to a Bar chart using jquery ajax based on data extracted from our models.

You can download it from Chart.js official website and use it locally, or you can use it from a CDN using the URL above.

https://www.chartjs.org/

npm CDN Files https://www.jsdelivr.com/package/npm/chart.js?path=dist

view.py

 
#view.py
from django.shortcuts import render
from django.db.models import Sum
from django.http import JsonResponse
from myapp.models import City

def home(request):
    return render(request, 'home.html')

def population_chart(request):
    labels = []
    data = []

    queryset = City.objects.values('name').annotate(population=Sum('population')).order_by('-population') 
    for entry in queryset:
        labels.append(entry['name'])
        data.append(entry['population'])
    
    return JsonResponse(data={
        'labels': labels,
        'data': data,
    })
urls.py
 
#urls.py
from django.contrib import admin  
from myapp import views  
from django.conf.urls import url
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.home, name='home'),
    path('population-chart/', views.population_chart, name='population-chart'),
]
models.py
 
#models.py
from django.db import models
 
class City(models.Model):
    name = models.CharField(max_length=30)
    population = models.PositiveIntegerField()
  
    def __str__(self):
        return self.name
    
    class Meta:
        db_table = 'myapp_city'
templates/home.html
//templates/home.html
{% extends 'base.html' %}

{% block content %}
  <div id="container" style="width: 75%;">
    <canvas id="population-chart" data-url="{% url 'population-chart' %}"></canvas>
  </div>
  <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.3/dist/Chart.min.js"></script>
  <script>
    $(function () {
      var $populationChart = $("#population-chart");
      $.ajax({
        url: $populationChart.data("url"),
        success: function (data) {

          var ctx = $populationChart[0].getContext("2d");

          new Chart(ctx, {
            type: 'bar',
            data: {
              labels: data.labels,
              datasets: [{
                label: 'Population',
                backgroundColor: '#6fae3f',
                data: data.data
              }]          
            },
            options: {
              responsive: true,
              legend: {
                position: 'top',
              },
              title: {
                display: true,
                text: 'Population Bar Chart'
              }
            }
          });

        }
      });

    });

  </script>
{% endblock %}
templates/base.html
//templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1"/>
 <title>{% block title %}Django Highcharts {% endblock %}</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="#">Cairocoders</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
    <div class="navbar-nav">
   <a class="nav-item nav-link active" href="">Home</a>
    </div>
  </div>
</nav>
 <div class="container" style="padding:20px;">
    <div class="col-md-12 well">
        <h3 class="text-primary">How to Use Chart-js with Django using jquery Ajax Bar Chart Example</h3> 
        <hr style="border-top:1px dotted #ccc;"/>
  {% block content %} {% endblock %}
    </div>
    </div> 
</body>
</html>

Tuesday, June 23, 2020

How to Use Chart-js with Django Example Pie Chart


How to Use Chart-js with Django Example Pie Chart

Chart.js is a open source JavaScript library that helps you render HTML5 charts.

In this tutorial we are going to Pie Chart based on data extracted from our models.

You can download it from Chart.js official website and use it locally, or you can use it from a CDN using the URL above.


https://www.chartjs.org/ myapp/models.py
#models.py
from django.db import models
 
class City(models.Model):
    name = models.CharField(max_length=30)
    population = models.PositiveIntegerField()
 
    def __str__(self):
        return self.name
   
    class Meta:
        db_table = 'myapp_city'
python manage.py makemigrations myapp
python manage.py migrate

New database table added

CREATE TABLE myapp_city (
id INTEGER NOT NULL
PRIMARY KEY AUTOINCREMENT,
name VARCHAR (30) NOT NULL,
population INTEGER

); devproject/urls.py
#urls.py
from django.contrib import admin  
from myapp import views  
from django.conf.urls import url
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.home, name='home'),
    path('pie-chart/', views.pie_chart, name='pie-chart'),
]
myapp/views.py
#views.py
from django.shortcuts import render, redirect

from myapp.models import City

def home(request):
    return render(request, 'home.html')

def pie_chart(request):
    labels = []
    data = []

    queryset = City.objects.order_by('-population')[:9]
    for city in queryset:
        labels.append(city.name)
        data.append(city.population)

    return render(request, 'pie_chart.html', {
        'labels': labels,
        'data': data,
    })
myapp/templates/home.html
//templates/home.html
{% extends 'base.html' %}
{% block title %}Home {% endblock %}


{% block content %}
<h1>Pie Chart Population</h1>
 <div id="container" style="width: 75%;">
    <canvas id="pie-chart"></canvas>
 </div>
  <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.3/dist/Chart.min.js"></script><script>
    var config = {
      type: 'pie',
      data: {
        datasets: [{
          data: [1780000, 1630000, 582602, 416522, 411634, 318332, 318332, 306659, 233040],
          backgroundColor: [
            '#ff0000', '#0000ff', '#ff0080', '#73ffff', '#5c26ff', '#002db3', '#ffff26', '#4cff4c', '#ff00ff'
          ],
          label: 'Population'
        }],
        labels: ['Manila City', 'Davao City', 'Makati', 'Pasay City', 'Angeles City', 'Tarlac City', 'Malolos', 'San Fernando', 'Olongapo City']
      },
      options: {
        responsive: true
      }
    };

    window.onload = function() {
      var ctx = document.getElementById('pie-chart').getContext('2d');
      window.myPie = new Chart(ctx, config);
    };
  </script>
{% endblock %}
myapp/templates/pie_chart.html
//templates/pie_chart.html
{% extends 'base.html' %}

{% block title %}Django Highcharts - Pie Chart{% endblock %}

{% block content %}
<h1>Pie Chart Population</h1>
 <div id="container" style="width: 75%;">
    <canvas id="pie-chart"></canvas>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.3/dist/Chart.min.js"></script><script>
    var config = {
      type: 'pie',
      data: {
        datasets: [{
          data: {{ data|safe }},
          backgroundColor: [
            '#ff0000', '#0000ff', '#ff0080', '#73ffff', '#5c26ff', '#002db3', '#ffff26', '#4cff4c', '#ff00ff'
          ],
          label: 'Population'
        }],
        labels: {{ labels|safe }}
      },
      options: {
        responsive: true
      }
    };

    window.onload = function() {
      var ctx = document.getElementById('pie-chart').getContext('2d');
      window.myPie = new Chart(ctx, config);
    };
  </script>
{% endblock %}
myapp/templates/base.html
//templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1"/>
 <title>{% block title %}Django Highcharts {% endblock %}</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="#">Cairocoders</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
    <div class="navbar-nav">
   <a class="nav-item nav-link active" href="">Home</a>
    </div>
  </div>
</nav>
 <div class="container" style="padding:20px;">
    <div class="col-md-12 well">
        <h3 class="text-primary">How to Use Chart-js with Django Example Pie Chart</h3> 
        <hr style="border-top:1px dotted #ccc;"/>
  {% block content %} {% endblock %}
    </div>
    </div> 
</body>
</html>

Sunday, June 21, 2020

Django Simple Email Contact Form


Django Simple Email Contact Form

Create a simple contact form that sends email website.

Update urls.py


devproject/urls.py
 
#urls.py
from django.contrib import admin  
from myapp import views  
from django.conf.urls import url
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('myapp.urls')),
]
Next create a new myapp/urls.py file in our app. myapp/urls.py
 
#urls.py
from django.contrib import admin
from django.urls import path

from myapp.views import contactView, successView

urlpatterns = [
    path('contact/', contactView, name='contact'),
    path('success/', successView, name='success'),
]
demoapp/forms.py
 
#forms.py
from django import forms

class ContactForm(forms.Form):
    from_email = forms.EmailField(required=True)
    subject = forms.CharField(required=True)
    message = forms.CharField(widget=forms.Textarea, required=True)
demoapp/views.py
 
#views.py
from django.shortcuts import render, redirect

from django.core.mail import send_mail, BadHeaderError
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect
from myapp.forms import ContactForm

def contactView(request):
    if request.method == 'GET':
        form = ContactForm()
    else:
        form = ContactForm(request.POST)
        if form.is_valid():
            subject = form.cleaned_data['subject']
            from_email = form.cleaned_data['from_email']
            message = form.cleaned_data['message']
            try:
                send_mail(subject, message, from_email, ['fidelbandoy622@gmail.com'])
            except BadHeaderError:
                return HttpResponse('Invalid header found.')
            return redirect('success')
    return render(request, "email.html", {'form': form})

def successView(request):
    return HttpResponse('Success! Thank you for your message.')

myapp/templates/email.html
//templates/email.html
{% extends 'base.html' %}

{% block title %}Contact Us{% endblock %}
{% load crispy_forms_tags %}

{% block content %}
<h3>Contact Us</h3>
<form method="post">
    {% csrf_token %}
    {{ form|crispy }}
    <div class="form-actions">
      <button type="submit" class="btn btn-success">Send</button>
    </div>
</form>
{% endblock %}
myapp/templates/base.html
//templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1"/>
 <title>{% block title %}Django Email Contact Form {% endblock %}</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="#">Cairocoders</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
    <div class="navbar-nav">
   <a class="nav-item nav-link active" href="">Home</a>
    </div>
  </div>
</nav>
 <div class="container" style="padding:20px;">
    <div class="col-md-12 well">
        <h3 class="text-primary">Django Simple Email Contact Form</h3>
        <hr style="border-top:1px dotted #ccc;"/>
  {% block content %} {% endblock %}
    </div>
    </div> 
</body>
</html>
add 'crispy_forms', #pip install django-crispy-forms to settings.py INSTALLED_APPS

How to use Django Slug Field


How to use Django Slug Field

In this tutorial we will add slugs to a Django website.

A slug is a short label for something, containing only letters, numbers, underscores or hyphens. They’re generally used in URLs.


models.py
#models.py
from django.db import models

from django.urls import reverse
from django.utils.text import slugify

class Article(models.Model):
    title = models.CharField(max_length=255)
    body = models.TextField()
    slug = models.SlugField(max_length=200, unique=True)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('article_detail', kwargs={'slug': self.slug})
  
    def save(self, *args, **kwargs):
        value = self.title
        self.slug = slugify(value, allow_unicode=True)
        super().save(*args, **kwargs)
create a migrations file for this change, then add it to our database via migrate.

python manage.py makemigrations myapp
python manage.py migrate

New database table added
CREATE TABLE myapp_article (
    id    INTEGER       NOT NULL
                        PRIMARY KEY AUTOINCREMENT,
    title VARCHAR (255) NOT NULL,
    body  TEXT          NOT NULL,
    slug  VARCHAR (50)  UNIQUE
); urls.py
#urls.py
from django.contrib import admin  
from django.urls import path
from myapp import views  
from django.conf.urls import url

from myapp.views import ArticleListView, ArticleDetailView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', ArticleDetailView.as_view(), name='article_detail'),
    path('', ArticleListView.as_view(), name='article_list'),
]
admins.py
#admin.py
from django.contrib import admin

from myapp.models import Article

class ArticleAdmin(admin.ModelAdmin):
    list_display = ('title', 'body',)
    prepopulated_fields = {'slug': ('title',)}

admin.site.register(Article, ArticleAdmin)
views.py
#views.py
from django.shortcuts import render, redirect

from django.views.generic import ListView, DetailView

from myapp.models import Article

class ArticleListView(ListView):
    model = Article
    template_name = 'article_list.html'


class ArticleDetailView(DetailView):
    model = Article
    template_name = 'article_detail.html'
templates/article_list.html
#templates/article_list.html
{% extends 'base.html' %}

{% block pagetitle %}Blog{% endblock %}

{% block content %}
<h1>Articles</h1>
{% for article in object_list %}
  <ul>
    <li><a href="{{ article.get_absolute_url }}">{{ article.title }}</a></li>
  </ul>
{% endfor %}
{% endblock %}
templates/article_detail.html
//templates/article_detail.html
{% extends 'base.html' %}

{% block pagetitle %}Blog{% endblock %}

{% block content %}
<div>
  <h2>{{ object.title }}</h2>
  <p>{{ object.body }}</p>
</div>
{% endblock %}
templates/base.html
//templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1"/>
 <title>{% block title %}How to use Django Slug Field {% endblock %}</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="#">Cairocoders</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
    <div class="navbar-nav">
   <a class="nav-item nav-link active" href="">Home</a>
    </div>
  </div>
</nav>
 <div class="container" style="padding:20px;">
    <div class="col-md-12 well">
        <h3 class="text-primary">How to use Django Slug Field</h3>
        <hr style="border-top:1px dotted #ccc;"/>
  {% block content %} {% endblock %}
    </div>
    </div> 
</body>
</html>

Friday, June 19, 2020

Django Basic Search


Django Basic Search

In this tutorial we will implement basic search in a Django website models.py
 
#models.py
from django.db import models

class Book(models.Model):
    FANTASY = 1
    MYSTERY = 2
    ROMANCE = 3
    BOOK_TYPES = (
        (FANTASY, 'Fantasy'),
        (MYSTERY, 'Mystery'),
        (ROMANCE, 'Romance'),
    )
    title = models.CharField(max_length=50)
    publication_date = models.DateField(null=True)
    author = models.CharField(max_length=30, blank=True)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    pages = models.IntegerField(blank=True, null=True)
    book_type = models.PositiveSmallIntegerField(choices=BOOK_TYPES)
  
    def __str__(self):
        return self.title
  
    class Meta:
        db_table = 'books'  
admin.py
 
#admin.py
from django.contrib import admin

from myapp.models import Book

class BookAdmin(admin.ModelAdmin):
    list_display = ['title', 'publication_date', 'author', 'price', 'book_type']
 
admin.site.register(Book, BookAdmin)
urls.py
 
#urls.py
from django.contrib import admin  
from django.urls import path
from myapp import views  
from django.conf.urls import url

from myapp.views import HomePageView, SearchResultsView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('search/', SearchResultsView.as_view(), name='search_results'),
    path('', HomePageView.as_view(), name='home'),
]
views.py
 
#views.py
from django.shortcuts import render, redirect

from django.views.generic import TemplateView, ListView
from myapp.models import Book
from django.db.models import Q 

class HomePageView(TemplateView):
    template_name = 'home.html'

# class SearchResultsView(ListView):
    # model = Book
    # template_name = 'search_results.html'
 
class SearchResultsView(ListView):
    model = Book
    template_name = 'search_results.html'
    #queryset = Book.objects.filter(title__icontains='The Hobbit') 
    
 #def get_queryset(self): # new
       # return Book.objects.filter(title__icontains='The Hobbit')
  
    # def get_queryset(self): 
        # return Book.objects.filter(
            # Q(title__icontains='The Hobbit') | Q(author__icontains='Cairocoders Ednalan')
        # )
  
    def get_queryset(self): 
        query = self.request.GET.get('q')
        object_list = Book.objects.filter(
            Q(title__icontains=query) | Q(author__icontains=query)
        )
        return object_list
templates/home.html
//templates/home.html
{% extends 'base.html' %}
{% block title %}Home {% endblock %}

{% block content %}
  <h2>Django Search</h2>
  <form action="{% url 'search_results' %}" method="get">
  <p><input name="q" type="text" placeholder="Search..." class="form-control"></p>
  <p><button type="submit" class="btn btn-success">Submit</button></p>
</form>
{% endblock %}
templates/base.html
//templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1"/>
 <title>{% block title %}Django Search {% endblock %}</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="{% url 'home' %}">Cairocoders</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
    <div class="navbar-nav">
   <a class="nav-item nav-link active" href="">Home</a>
    </div>
  </div>
</nav>
 <div class="container" style="padding:20px;">
    <div class="col-md-12 well">
        <h3 class="text-primary">Django Basic Search</h3>
        <hr style="border-top:1px dotted #ccc;"/>
  {% block content %} {% endblock %}
    </div>
    </div> 
</body>
</html>
templates/search_results.html
//templates/search_results.html
{% extends 'base.html' %}
{% block title %}Search Result {% endblock %}

{% block content %}
<h3>Search Results</h3>

<ul>
  {% for books in object_list %}
    <li>
      {{ books.title }}, {{ books.author }}
    </li>
  {% endfor %}
</ul>
{% endblock %}

Thursday, June 18, 2020

Django Crispy Forms Advanced Form Rendering


Django Crispy Forms Advanced Form Rendering

Install it using pip:

pip install django-crispy-forms

Add it to your INSTALLED_APPS and select which styles to use:

settings.py

INSTALLED_APPS = [
    'crispy_forms',
]


CRISPY_TEMPLATE_PACK = 'bootstrap4' views.py
#views.py
from django.shortcuts import render, redirect

from myapp.forms import RegsitrationForm

def home(request):
    if request.method == 'POST':
        form = RegsitrationForm(request.POST)
        if form.is_valid():
            #form.save()
            messages.success(request, 'New success!')
            return redirect('/home')
        else:
            messages.error(request, 'Invalid Please try again.')
    else:
        form = RegsitrationForm()
    return render(request, 'home.html', {'form': form})
 
def form2(request):
    if request.method == 'POST':
        form = RegsitrationForm(request.POST)
        if form.is_valid():
            #form.save()
            messages.success(request, 'New success!')
            return redirect('/form2')
        else:
            messages.error(request, 'Invalid Please try again.')
    else:
        form = RegsitrationForm()
    return render(request, 'form2.html', {'form': form})
settings.py settings.py
#settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    
    'crispy_forms', #pip install django-crispy-forms
    'myapp',
]

CRISPY_TEMPLATE_PACK = 'bootstrap4'
#forms.py
from django import forms

STATES = (
    ('', 'Choose...'),
    ('CA', 'California'),
    ('AK', 'Alaska'),
    ('AZ', 'Arizona')
)

class RegsitrationForm(forms.Form):
    email = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Email'}))
    password = forms.CharField(widget=forms.PasswordInput())
    address_1 = forms.CharField(
        label='Address',
        widget=forms.TextInput(attrs={'placeholder': '1234 Main St'})
    )
    address_2 = forms.CharField(
        widget=forms.TextInput(attrs={'placeholder': 'Apartment, studio, or floor'})
    )
    city = forms.CharField()
    state = forms.ChoiceField(choices=STATES)
    zip_code = forms.CharField(label='Zip')
    check_me_out = forms.BooleanField(required=False)
urls.py
#urls.py
from django.contrib import admin  
from django.urls import path
from myapp import views  
from django.conf.urls import url

urlpatterns = [
    path('admin/', admin.site.urls),
    path('home/', views.home, name='home'),
    path('form2/', views.form2, name='form2'),
]
templates/home.html
//templates/home.html
{% extends 'base.html' %}
{% block title %}Form Example 1 - Basic Crispy Form Rendering {% endblock %}

{% load crispy_forms_tags %}

{% block content %}
  <h2>Form Example 1 - Basic Crispy Form Rendering</h2>
  <form method="post" novalidate>
    {% csrf_token %}
    {{ form|crispy }}
    <button type="submit">Register</button>
  </form>
{% endblock %}
templates/home.html
//templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1"/>
 <title>{% block title %}Django Crispy Forms Advanced Form Rendering {% endblock %}</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="{% url 'home' %}">Cairocoders</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
    <div class="navbar-nav">
   <a class="nav-item nav-link active" href="">Home <span class="sr-only">(current)</span></a>
      <a class="nav-item nav-link" href="">Form 1</a>
      <a class="nav-item nav-link" href="">Form 2</a>
    </div>
  </div>
</nav>
 <div class="container" style="padding:20px;">
    <div class="col-md-12 well">
        <h3 class="text-primary">Django Crispy Forms Advanced Form Rendering</h3>
        <hr style="border-top:1px dotted #ccc;"/>
  {% block content %} {% endblock %}
    </div>
    </div> 
</body>
</html>
//templates/form2.html
{% extends 'base.html' %}
{% block title %}Form Example 2 - Custom Fields Placement {% endblock %}

{% load crispy_forms_tags %}

{% block content %}
  <h2>Form Example 2 - Custom Fields Placement</h2>
  <form method="post">
    {% csrf_token %}
    <div class="form-row">
      <div class="form-group col-md-6 mb-0">
        {{ form.email|as_crispy_field }}
      </div>
      <div class="form-group col-md-6 mb-0">
        {{ form.password|as_crispy_field }}
      </div>
    </div>
    {{ form.address_1|as_crispy_field }}
    {{ form.address_2|as_crispy_field }}
    <div class="form-row">
      <div class="form-group col-md-6 mb-0">
        {{ form.city|as_crispy_field }}
      </div>
      <div class="form-group col-md-4 mb-0">
        {{ form.state|as_crispy_field }}
      </div>
      <div class="form-group col-md-2 mb-0">
        {{ form.zip_code|as_crispy_field }}
      </div>
    </div>
    {{ form.check_me_out|as_crispy_field }}
    <button type="submit" class="btn btn-primary">Sign in</button>
  </form>
{% endblock %}

Wednesday, June 17, 2020

How to Implement Token Authentication using Django REST Framework


How to Implement Token Authentication using Django REST Framework

In this tutorial you are going to learn how to implement Token-based authentication using Django REST Framework (DRF).

Install Django REST Framework DRF:


pip install djangorestframework


settings.py
 
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    
    'rest_framework', #pip install djangorestframework
    'rest_framework.authtoken',
    'myapp',
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',  
    ],
}
migrate the database python manage.py migrate
views.py
 
#views.py
from django.shortcuts import render, redirect

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated

class HelloView(APIView):
    permission_classes = (IsAuthenticated,) #Generated token c4fe47947247e684dd0e065ea674e1645525d891 for user ednalan23

    def get(self, request):
        content = {'message': 'Hello, World!'}
        return Response(content)
urls.py
 
#urls.py
from django.contrib import admin  
from django.urls import path
from myapp import views  
from django.conf.urls import url
from django.urls import include, path
from rest_framework.authtoken.views import obtain_auth_token

urlpatterns = [
    path('admin/', admin.site.urls),
    path('hello/', views.HelloView.as_view(), name='hello'),
    path('api-token-auth/', obtain_auth_token, name='api_token_auth'),
]

I use HTTPie https://httpie.org/ Python command line tool:

http http://127.0.0.1:8000/hello/

http post http://127.0.0.1:8000/api-token-auth/ username=ednalan23 password=ednalan23

http GET http://127.0.0.1:8000/hello/ "Authorization: Token c4fe47947247e684dd0e065ea674e1645525d891"

Sunday, June 14, 2020

Django Authentication Sign Up, Login, Logout and Protecting Views


Django Authentication Sign Up, Login, Logout and Protecting Views


In this tutorial  we are going to explore Django’s authentication system by implementing sign up, login, logout, and protected views from non-authenticated users.

Official documentation information: Using the Django authentication system https://docs.djangoproject.com/en/2.1/topics/auth/default/

views.py
 
#views.py
from django.shortcuts import render, redirect
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.decorators import login_required
from django.views.generic import TemplateView
from django.contrib.auth.mixins import LoginRequiredMixin

def home(request):
    count = User.objects.count()
    return render(request, 'home.html', {
        'count': count
    })

def signup(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('home')
    else:
        form = UserCreationForm()
    return render(request, 'registration/signup.html', {
        'form': form
    })
 
@login_required
def secret_page(request):
    return render(request, 'secret_page.html')
 
class SecretPage(LoginRequiredMixin, TemplateView):
    template_name = 'secret_page2.html'
urls.py
 
#urls.py
from django.contrib import admin  
from django.urls import path
from myapp import views  
from django.conf.urls import url
from django.urls import include, path

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.home, name='home'),
    path('signup/', views.signup, name='signup'),
    path('secret/', views.secret_page, name='secret'),
    path('secret2/', views.SecretPage.as_view(), name='secret2'),
    path('accounts/', include('django.contrib.auth.urls')),
]
templates/home.html
#templates/home.html
{% extends 'base.html' %}

{% block content %}
  <h2>Homepage</h2>
  <p>Welcome to My Site, {% if user.is_authenticated %}{{ user.username }}{% else %}visitor{% endif %}!</p>
  <p>
    <strong>Total users registered: </strong> {{ count }}
  </p>
{% endblock %}
templates/base.html
//templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
    <meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1"/>
 <title>{% block title %}Django Authentication Sign Up, Login, Logout and Protecting Views{% endblock %}</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="{% url 'home' %}">Cairocoders</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
    <div class="navbar-nav">
      {% if user.is_authenticated %}
   <a class="nav-item nav-link active" href="{% url 'home' %}">Home <span class="sr-only">(current)</span></a>
      <a class="nav-item nav-link" href="{% url 'home' %}">Hello : {{ user.username }}</a>
      <a class="nav-item nav-link" href="{% url 'logout' %}">Log out</a>
   {% else %}
      <a class="nav-item nav-link" href="{% url 'login' %}">Log in</a>
      <a class="nav-item nav-link" href="{% url 'signup' %}">Sign up</a>
   {% endif %}
    </div>
  </div>
</nav>
 <div class="container" style="padding:20px;">
    <div class="col-md-12 well">
        <h3 class="text-primary">Django Authentication Sign Up, Login, Logout and Protecting Views</h3>
        <hr style="border-top:1px dotted #ccc;"/>
  {% block content %} {% endblock %}
    </div>
    </div>
 <style type="text/css">
    .asteriskField {
      display: none;
    }

    form .alert ul li {
      list-style: none;
    }

    form .alert ul {
      padding: 0;
      margin: 0;
    }
  </style> 
</body>
</html>
templates/signup.html
//templates/signup.html
{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
  <div class="row justify-content-center">
    <div class="col-8">
      <div class="card">
        <div class="card-body">
          <h2>Sign Up</h2>
          <form method="post">
            {% csrf_token %}
            {{ form|crispy }}
            <button type="submit" class="btn btn-primary">Sign up</button>
          </form>
        </div>
      </div>
    </div>
  </div>
{% endblock %}
templates/registration/login.html
//templates/registration/login.html
{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
  <div class="row justify-content-center">
    <div class="col-6">
      <div class="card">
        <div class="card-body">
          <h2>Log in</h2>
          <form method="post" novalidate>
            {% csrf_token %}
            {{ form|crispy }}
            <button type="submit" class="btn btn-primary">Log in</button>
          </form>
        </div>
      </div>
    </div>
  </div>
{% endblock %}
templates/secret_page.html
//templates/secret_page.html
{% extends 'base.html' %}

{% block content %}
  <p>This is a Protected Page!</p>
{% endblock %}
templates/secret_page2.html
//templates/secret_page2.html
{% extends 'base.html' %}

{% block content %}
  <p>This is a Protected Page 2!</p>
{% endblock %}
settings.py add to setting.py 'crispy_forms', INSTALLED_APPS

Friday, June 12, 2020

Atom RSS Feed Generator with Python Flask


Atom RSS Feed Generator with Python Flask

An Atom feed is very similar to an RSS feed in that it is a lightweight XML format allowing for easy syndication of web content. In fact, most RSS readers and news aggregators will be able to read Atom feeds just fine, as it is becoming a widely-used alternative to RSS feeds.

In this post we will generate feeds using python module called werkzeug.

feed_url = URL Route of Published Feed. Example : http://www.example.com/feeds
url = Root URL of Blog. Example : http://www.example.com

Once feed object is created we would call feed.add()
title = Post Title
summary = Blog post summary.
content_type = html Example : http://www.example.com
author = Name of author.
url = Absolute URL for the blog post. http://www.example.com/my-post
updated = Last updated date and time in UTC format.

published = Created date and time in UTC format.
 
#app.py
from flask import Flask, render_template, request
from werkzeug.contrib.atom import AtomFeed
from urllib.parse import urljoin
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///devdb.db' 
app.config['SECRET_KEY'] = 'cairocoders-ednalan'

db = SQLAlchemy(app) 

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(140))
    content = db.Column(db.String(140))
    author_name = db.Column(db.String(140))
    url = db.Column(db.String(140))
    mod_date = db.Column(db.DateTime, default=datetime.utcnow)
    created_date = db.Column(db.DateTime, default=datetime.utcnow)

def get_abs_url(url):
    """ Returns absolute url by joining post url with base url """
    return urljoin(request.url_root, url)
 
@app.route('/feeds/')
def feeds():
    # feed = AtomFeed(title='Last 10 Posts from My Blog',
               # feed_url="https://tutorial101.blogspot.com/feeds/",
               # url="https://tutorial101.blogspot.com/")
    feed = AtomFeed(title='Last 10 Posts from My Blog',
                    feed_url=request.url, url=request.url_root)
  
    posts = Post.query.filter().all() 
 
    for post in posts:
        feed.add(post.title, post.content,
                 content_type='html',
                 author= post.author_name,
                 url=get_abs_url(post.url),
                 updated=post.mod_date,
                 published=post.created_date)
     
    return feed.get_response()
 
if __name__ == '__main__':
 app.run(debug=True)

Thursday, June 11, 2020

How to add ReCaptcha to Python Flask App without Extension


How to add ReCaptcha to Python Flask App without Extension

In this article we will learn to integrate Google ReCaptcha into flask web application without using any flask extension to prevent bots from submitting spam.

When you register for recaptcha it provides you two keys.

Site Key : For Client Side Integration
Secret Key : For Server Side Integration


Implementing ReCaptcha with python and flask
app.py
 
#app.py
from flask import Flask, render_template, request, flash, redirect, url_for, json
import requests #pip install requests

app = Flask(__name__)

app.config['SECRET_KEY'] = 'cairocoders-ednalan'

def is_human(captcha_response):
    """ Validating recaptcha response from google server
        Returns True captcha test passed for submitted form else returns False.
    """
    secret = "6LeKOaMZAAAAAKw9nhAjnpzrzrC3R0YYRf-kKDH1"
    payload = {'response':captcha_response, 'secret':secret}
    response = requests.post("https://www.google.com/recaptcha/api/siteverify", payload)
    response_text = json.loads(response.text)
    return response_text['success']
 
@app.route("/contact/", methods=["GET", "POST"])
def contact():
    sitekey = "6LeKOaMZAAAAAI7L6TVsZa9A2t6-9LDVYSVqX9ZP"

    if request.method == "POST":
        name = request.form['name']
        email = request.form['email']
        msg = request.form['message']
        captcha_response = request.form['g-recaptcha-response']
        
        if is_human(captcha_response):
            # Process request here
            status = "Detail submitted successfully."
        else:
             # Log invalid attempts
            status = "Sorry ! Please Check Im not a robot."

        flash(status)
        return redirect(url_for('contact'))

    return render_template("contact.html", sitekey=sitekey)
  
if __name__ == '__main__':
 app.run(debug=True)
templates/contact.html
//templates/contact.html
<html>
<head> 
<title>Contact Us</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">
<script src="https://www.google.com/recaptcha/api.js"></script>
</head>
<body>
<div class="container"> <center><h3>How to add ReCaptcha to Python Flask App without Extension</h3></center> 
<div class="row main" style="padding-top:50px;">
 <div class="main-login main-center">
 <h5>Contact us Feel free to contact us</h5>
        <p>
         {% with messages = get_flashed_messages() %}
           {% if messages %}
          {% for message in messages %}
            <div class="alert alert-primary">
             <strong>{{ message }}</strong>
           </div>
          {% endfor %}
           {% endif %}
         {% endwith %}
        </p>
<form method="POST" action="{{ url_for('contact') }}"> 
    <div class="form-group">
  <label for="name" class="cols-sm-2 control-label">Your Name</label>
  <div class="cols-sm-10">
   <div class="input-group">
    <span class="input-group-addon"><i class="fa fa-user fa" aria-hidden="true"></i></span>
    <input type="text" class="form-control" name="name" id="name"  placeholder="Enter your Name"/>
   </div>
  </div>
 </div>
 <div class="form-group">
  <label for="email" class="cols-sm-2 control-label">Your Email</label>
  <div class="cols-sm-10">
   <div class="input-group">
    <span class="input-group-addon"><i class="fa fa-envelope fa" aria-hidden="true"></i></span>
    <input type="text" class="form-control" name="email" id="email"  placeholder="Enter your Email"/>
   </div>
  </div>
 </div>
 <div class="form-group">
  <label for="email" class="cols-sm-2 control-label">Message</label>
  <div class="cols-sm-10">
   <div class="input-group">
    <span class="input-group-addon"><i class="fa fa-envelope fa" aria-hidden="true"></i></span>
    <textarea name="message" id="message" class="form-control" rows="3" cols="15" required="required"
                                placeholder="Enter your Message"></textarea>
   </div>
  </div>
 </div> 
    <div class="g-recaptcha" data-sitekey="{{ sitekey }}"></div> <br/> 
    <input type="submit" value="submit" class="btn btn-primary btn-lg btn-block login-button">
</form>
</div>
</div>
</div>
<style>
.form-group{
 margin-bottom: 15px;
}

label{
 margin-bottom: 15px;
}
input,
input::-webkit-input-placeholder {
    font-size: 11px;
    padding-top: 3px;
}
.main-login{
  background-color: #f5f5f5;
    padding:50px;width:600px;
    -moz-border-radius: 2px;
    -webkit-border-radius: 2px;
    border-radius: 2px;
    -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
    -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
    box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);

}
span.input-group-addon i {
    color: #009edf;
    font-size: 17px;padding:10px;
}
.form-control {
    height: auto!important;
padding: 8px 12px !important;
}
.input-group {
    -webkit-box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.21)!important;
    -moz-box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.21)!important;
    box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.21)!important;
}
.main-center{
  margin-top: 30px;
  margin: 0 auto;
    padding: 10px 40px;
    text-shadow: none;
 -webkit-box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.31);
-moz-box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.31);
box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.31);

}
</style>
</body>
</html> 

How to add ReCaptcha to Flask App using Flask-reCaptcha


How to add ReCaptcha to Flask App using Flask-reCaptcha

In this article we will learn to integrate Google ReCaptcha into flask web application using flask extension to prevent bots from submitting spam.

First install Flask-reCaptcha

pip install Flask-reCaptcha

https://pypi.org/project/Flask-reCaptcha/

Register Google ReCaptcha API

When you register for recaptcha it provides you two keys.

Site Key : For Client Side Integration
Secret Key : For Server Side Integration


Implementing ReCaptcha with python and flask


app.py
 
#app.py
from flask import Flask, render_template, request, flash, redirect, url_for
from flask_recaptcha import ReCaptcha

app = Flask(__name__)
recaptcha = ReCaptcha(app=app)

app.config.update(dict(
    RECAPTCHA_ENABLED = True,
    RECAPTCHA_SITE_KEY = "6LeKOaMZAAAAAI7L6TVsZa9A2t6-9LDVYSVqX9ZP",
    RECAPTCHA_SECRET_KEY = "6LeKOaMZAAAAAKw9nhAjnpzrzrC3R0YYRf-kKDH1",
))

recaptcha = ReCaptcha()
recaptcha.init_app(app)

app.config['SECRET_KEY'] = 'cairocoders-ednalan'


@app.route('/register')
def register():
    return render_template("form.html")    

@app.route('/submit', methods=['POST'])
def submit():
    if recaptcha.verify():
        flash('New Device Added successfully')
        return redirect(url_for('register'))
    else:
        flash('Error ReCaptcha')
        return redirect(url_for('register'))
  
if __name__ == '__main__':
 app.run(debug=True)
templates/form.html
//templates/form.html
<html>
<head> 
<title>Register</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">
</head>
<body>
<div class="container"> <center><h3>How to add ReCaptcha to Flask App using Flask-reCaptcha</h3></center> 
<div class="row main" style="padding-top:50px;">
 <div class="main-login main-center">
 <h5>Sign up once and watch demos.</h5>
        <p>
         {% with messages = get_flashed_messages() %}
           {% if messages %}
          {% for message in messages %}
            <div class="alert alert-primary">
             <strong>{{ message }}</strong>
           </div>
          {% endfor %}
           {% endif %}
         {% endwith %}
        </p>
<form method="POST" action="{{ url_for('submit') }}"> 
    <div class="form-group">
  <label for="name" class="cols-sm-2 control-label">Your Name</label>
  <div class="cols-sm-10">
   <div class="input-group">
    <span class="input-group-addon"><i class="fa fa-user fa" aria-hidden="true"></i></span>
    <input type="text" class="form-control" name="name" id="name"  placeholder="Enter your Name"/>
   </div>
  </div>
 </div>
 <div class="form-group">
  <label for="email" class="cols-sm-2 control-label">Your Email</label>
  <div class="cols-sm-10">
   <div class="input-group">
    <span class="input-group-addon"><i class="fa fa-envelope fa" aria-hidden="true"></i></span>
    <input type="text" class="form-control" name="email" id="email"  placeholder="Enter your Email"/>
   </div>
  </div>
 </div>     
    {{ recaptcha }} <br/>
    <input type="submit" value="submit" class="btn btn-primary btn-lg btn-block login-button">
</form>
</div>
</div>
</div>
<style>
.form-group{
 margin-bottom: 15px;
}

label{
 margin-bottom: 15px;
}
input,
input::-webkit-input-placeholder {
    font-size: 11px;
    padding-top: 3px;
}
.main-login{
  background-color: #f5f5f5;
    padding:50px;
    -moz-border-radius: 2px;
    -webkit-border-radius: 2px;
    border-radius: 2px;
    -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
    -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
    box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);

}
span.input-group-addon i {
    color: #009edf;
    font-size: 17px;padding:10px;
}
.form-control {
    height: auto!important;
padding: 8px 12px !important;
}
.input-group {
    -webkit-box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.21)!important;
    -moz-box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.21)!important;
    box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.21)!important;
}
.main-center{
  margin-top: 30px;
  margin: 0 auto;
  max-width: 400px;
    padding: 10px 40px;
    text-shadow: none;
 -webkit-box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.31);
-moz-box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.31);
box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.31);

}
</style>
</body>
</html> 

Tuesday, June 9, 2020

How to Use RESTful APIs with Django


How to Use RESTful APIs with Django

The REST acronym stands for Representational State Transfer, which is an architectural design.
Usually when we use the term RESTful

API stands for Application Programming Interface, which is a software application that we interact programmatically, instead of using a graphical interface.


RESTful API available the information you store in your databases using a common format, such as XML or JSON.

Example ipstack Location API https://ipstack.com/

urls.py
urlpatterns = [ 
    path('admin/', admin.site.urls), 
    path('',views.index),

] views.py
 
#views.py
from django.shortcuts import render, redirect

import requests

# def index(request):
    # response = requests.get('http://api.ipstack.com/110.54.244.203?access_key=7f851d241fee253a7abbbdd1ca27f73a')
    # geodata = response.json()
    # return render(request, 'home.html', {
        # 'ip': geodata['ip'],
        # 'country': geodata['country_name']
    # })
 
def index(request):
    response = requests.get('http://api.ipstack.com/110.54.244.203?access_key=7f851d241fee253a7abbbdd1ca27f73a')
    geodata = response.json()
    return render(request, 'home.html', {
        'ip': geodata['ip'],
        'country': geodata['country_name'],
        'latitude': geodata['latitude'],
        'longitude': geodata['longitude'],
  'api_key': 'AIzaSyB6QBZAvLhPI-e-U8k3rT0MDBn2-w8lqAw',
    }) 
templates/home.html
//templates/home.html
{% extends 'base.html' %}

{% block content %}
  <h2>GEO API</h2>
  <p>Your ip address is <strong>{{ ip }}</strong>, and you are probably in <strong>{{ country }}</strong> right now.</p>

  <iframe width="900"
          height="430"
          frameborder="0"
          style="border:0"
          src="https://www.google.com/maps/embed/v1/view?center={{ latitude }},{{ longitude }}&zoom=8&key={{ api_key }}"
          allowfullscreen></iframe>
{% endblock %}
templates/base.html
/templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    {% load static %}
    <link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.css' %}"/>
    <meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1"/>
 <title>{% block title %}How to Use RESTful APIs with Django{% endblock %}</title>
</head>
<body>
    <nav class="navbar navbar-default">
        <div class="container-fluid">
            <a class="navbar-brand">Cairocoders</a>
        </div>
    </nav>
 
 <div class="container">
    <div class="col-md-12 well">
        <h3 class="text-primary">How to Use RESTful APIs with Django</h3>
        <hr style="border-top:1px dotted #ccc;"/>

  {% block content %} {% endblock %}

    </div>
    </div> 
</body>
</html>

Monday, June 8, 2020

How to Create Django Admin List Actions - Apply 10% discount and Export to csv


How to Create Django Admin List Actions - Apply 10% discount and Export to csv

All Django Admin list views already a default action Delete selected.

In this short tutorial I will show how create your own list actions.

Database Table
CREATE TABLE books (
id INTEGER PRIMARY KEY,
title VARCHAR (50),
publication_date DATE,
author VARCHAR (30),
price DECIMAL,
pages INTEGER (11),
book_type INTEGER
);


models.py
 
#models.py
from django.db import models

class Book(models.Model):
    FANTASY = 1
    MYSTERY = 2
    ROMANCE = 3
    BOOK_TYPES = (
        (FANTASY, 'Fantasy'),
        (MYSTERY, 'Mystery'),
        (ROMANCE, 'Romance'),
    )
    title = models.CharField(max_length=50)
    publication_date = models.DateField(null=True)
    author = models.CharField(max_length=30, blank=True)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    pages = models.IntegerField(blank=True, null=True)
    book_type = models.PositiveSmallIntegerField(choices=BOOK_TYPES)
  
    class Meta:
        db_table = 'books'  
admin.py
 
#admin.py
from django.contrib import admin

import decimal, csv

from django.http import HttpResponse
from django.db.models import F

from myapp.models import Book


def export_books(modeladmin, request, queryset):
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="books.csv"'
    writer = csv.writer(response)
    writer.writerow(['Title', 'Publication Date', 'Author', 'Price', 'Pages', 'Book Type'])
    books = queryset.values_list('title', 'publication_date', 'author', 'price', 'pages', 'book_type')
    for book in books:
        writer.writerow(book)
    return response
export_books.short_description = 'Export to csv'


class BookAdmin(admin.ModelAdmin):
    list_display = ['title', 'publication_date', 'author', 'price', 'book_type']
    actions = ['apply_discount', export_books]

    def apply_discount(self, request, queryset):
        queryset.update(price=F('price') * decimal.Decimal('0.9'))
    apply_discount.short_description = 'Apply 10%% discount'

admin.site.register(Book, BookAdmin)

Saturday, June 6, 2020

Django Chained Dropdown List - Select Box using jQuery Ajax Country City

Django Chained Dropdown List - Select Box using jQuery Ajax Country City
In this tutorial we are going to learn dynamic dependent select box using jquery, ajax Country and City.

This type of feature mostly use if you have use Country State City or you have working with Category
and you want to load Sub Category of particular category. models.py
 
#models.py
from django.db import models

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

    def __str__(self):
        return self.name

    class Meta:
        # managed = True
        db_table = 'myapp_country'
  
class City(models.Model):
    country = models.ForeignKey(Country, on_delete=models.CASCADE)
    name = models.CharField(max_length=30)

    def __str__(self):
        return self.name
  
    class Meta:
        # managed = True
        db_table = 'myapp_city'

class Person(models.Model):
    name = models.CharField(max_length=100)
    birthdate = models.DateField(null=True, blank=True)
    country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True)
    city = models.ForeignKey(City, on_delete=models.SET_NULL, null=True)

    def __str__(self):
        return self.name

    class Meta:
        # managed = True
        db_table = 'myapp_person'

Database Table

CREATE TABLE myapp_country (
    id   INTEGER      NOT NULL
                      PRIMARY KEY AUTOINCREMENT,
    name VARCHAR (30) NOT NULL
);

INSERT INTO myapp_country (id, name) VALUES (1, 'Philippines');
INSERT INTO myapp_country (id, name) VALUES (2, 'United States');
INSERT INTO myapp_country (id, name) VALUES (3, 'Russia');
INSERT INTO myapp_country (id, name) VALUES (4, 'Brazil');
INSERT INTO myapp_country (id, name) VALUES (5, 'United Kingdom');


CREATE TABLE myapp_city (
    id         INTEGER      NOT NULL
                            PRIMARY KEY AUTOINCREMENT,
    name       VARCHAR (30) NOT NULL,
    country_id INTEGER      NOT NULL
                            REFERENCES myapp_country (id) DEFERRABLE INITIALLY DEFERRED
);

INSERT INTO myapp_city (id, name, country_id) VALUES (1, 'Olongapo City', 1);
INSERT INTO myapp_city (id, name, country_id) VALUES (2, 'Angeles City', 1);
INSERT INTO myapp_city (id, name, country_id) VALUES (3, 'Davao City', 1);
INSERT INTO myapp_city (id, name, country_id) VALUES (4, 'Pasay City', 1);
INSERT INTO myapp_city (id, name, country_id) VALUES (5, 'Manila City', 1);
INSERT INTO myapp_city (id, name, country_id) VALUES (6, 'New York', 2);
INSERT INTO myapp_city (id, name, country_id) VALUES (7, 'San Francisco', 2);
INSERT INTO myapp_city (id, name, country_id) VALUES (8, 'Los Angeles', 2);
INSERT INTO myapp_city (id, name, country_id) VALUES (9, 'Chicago', 2);
INSERT INTO myapp_city (id, name, country_id) VALUES (10, 'Seattle', 2);
INSERT INTO myapp_city (id, name, country_id) VALUES (11, 'Moscow', 3);
INSERT INTO myapp_city (id, name, country_id) VALUES (12, 'Saint Petersburg', 3);
INSERT INTO myapp_city (id, name, country_id) VALUES (13, 'Yekaterinburg', 3);
INSERT INTO myapp_city (id, name, country_id) VALUES (14, 'Kazan', 3);
INSERT INTO myapp_city (id, name, country_id) VALUES (15, 'Krasnodar', 3);
INSERT INTO myapp_city (id, name, country_id) VALUES (16, 'Sao Paulo', 4);
INSERT INTO myapp_city (id, name, country_id) VALUES (17, 'Rio de Janeiro', 4);
INSERT INTO myapp_city (id, name, country_id) VALUES (18, 'Belo Horizonte', 4);
INSERT INTO myapp_city (id, name, country_id) VALUES (19, 'Curitiba', 4);
INSERT INTO myapp_city (id, name, country_id) VALUES (20, 'Recife', 4);
INSERT INTO myapp_city (id, name, country_id) VALUES (21, 'London', 5);
INSERT INTO myapp_city (id, name, country_id) VALUES (22, 'Huddersfield', 5);
INSERT INTO myapp_city (id, name, country_id) VALUES (23, 'Glasgow', 5);
INSERT INTO myapp_city (id, name, country_id) VALUES (24, 'Edinburgh', 5);
INSERT INTO myapp_city (id, name, country_id) VALUES (25, 'Cambridge', 5);

CREATE TABLE myapp_person (
    id         INTEGER       NOT NULL
                             PRIMARY KEY AUTOINCREMENT,
    name       VARCHAR (100) NOT NULL,
    birthdate  DATE,
    city_id    INTEGER       REFERENCES myapp_city (id) DEFERRABLE INITIALLY DEFERRED,
    country_id INTEGER       REFERENCES myapp_country (id) DEFERRABLE INITIALLY DEFERRED
);

urls.py
 
#urls.py
from django.contrib import admin  
from django.urls import path
from myapp import views  
from django.conf.urls import url
from django.urls import include, path

urlpatterns = [  
    path('admin/', admin.site.urls),  
    path('', views.PersonListView.as_view(), name='person_changelist'),
    path('add/', views.PersonCreateView.as_view(), name='person_add'),
    path('/', views.PersonUpdateView.as_view(), name='person_change'),
    path('ajax/load-cities/', views.load_cities, name='ajax_load_cities'),
]
views.py
 
#views.py
from django.shortcuts import render, redirect
from django.views.generic import ListView, CreateView, UpdateView
from django.urls import reverse_lazy
from myapp.models import Person, City
from myapp.forms import PersonForm

 
class PersonListView(ListView):
    model = Person
    context_object_name = 'people'
    template_name = 'person_list.html'

class PersonCreateView(CreateView):
    model = Person
    form_class = PersonForm
    template_name = 'person_form.html'
    success_url = reverse_lazy('person_changelist')


class PersonUpdateView(UpdateView):
    model = Person
    form_class = PersonForm
    template_name = 'person_form.html'
    success_url = reverse_lazy('person_changelist')


def load_cities(request):
    country_id = request.GET.get('country')
    cities = City.objects.filter(country_id=country_id).order_by('name')
    return render(request, 'city_dropdown_list_options.html', {'cities': cities})
def load_cities(request): This view will be used via AJAX requests.
forms.py
 
#forms.py
from django import forms

from myapp.models import Person, City

class PersonForm(forms.ModelForm): 
    class Meta:
        model = Person
        fields = ('name', 'birthdate', 'country', 'city')

    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')
templates/person_list.html
//templates/person_list.html
{% extends 'base.html' %}

{% block title %}Django Chained Dropdown List - Select Box using jQuery Ajax Country City{% endblock %}

{% block content %}
  <table class="table table-striped custab">
    <thead>
  <a href="{% url 'person_add' %}" class="btn btn-primary btn-xs pull-right"><b>+</b> Add new Person</a>
        <tr>
        <th>Name</th>
        <th>Birthdate</th>
        <th>Country</th>
        <th>City</th>
  <th class="text-center">Action</th>
      </tr>
    </thead>
    <tbody>
      {% for person in people %}
        <tr>
          <td><a href="{% url 'person_change' person.pk %}">{{ person.name }}</a></td>
          <td>{{ person.birthdate }}</td>
          <td>{{ person.country.name }}</td>
          <td>{{ person.city.name }}</td>
    <td class="text-center"><a class='btn btn-info btn-xs' href="#"><span class="glyphicon glyphicon-edit"></span> Edit</a> <a href="#" class="btn btn-danger btn-xs"><span class="glyphicon glyphicon-remove"></span> Del</a></td>
        </tr>
      {% empty %}
        <tr>
          <td colspan="4">No person in the database. <a href="{% url 'person_add' %}">Add the first person</a>.</td>
        </tr>
      {% endfor %}
    </tbody>
  </table>
{% endblock %}
templates/person_form.html
//templates/person_form.html
{% extends 'base.html' %}

{% block content %}
{% load widget_tweaks %}
  <h2>Person Form</h2>

  <form method="post" id="personForm" data-cities-url="{% url 'ajax_load_cities' %}" novalidate>
    {% csrf_token %}
    <table>
      <!-- {{ form.as_table }} -->
    </table>
 {% for field in form.visible_fields %}
   <div class="form-group">
  <label for="{{ field.id_for_label }}">{{ field.label }}</label>
  {{ field|add_class:'form-control' }}
  {% for error in field.errors %}
    <span class="help-block">{{ error }}</span>
  {% endfor %}
   </div>
 {% endfor %}
    <button type="submit" class="btn btn-success">Save</button>
    <a href="{% url 'person_changelist' %}">Home</a>
  </form>

  <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
  <script>
    $("#id_country").change(function () {
      var url = $("#personForm").attr("data-cities-url");
      var countryId = $(this).val();

      $.ajax({
        url: url,
        data: {
          'country': countryId
        },
        success: function (data) {
          $("#id_city").html(data);
        }
      });

    });
  </script>

{% endblock %}
templates/city_dropdown_list_options.html
//templates/city_dropdown_list_options.html
<option value="">---------</option>
{% for city in cities %}
<option value="{{ city.pk }}">{{ city.name }}</option>
{% endfor %}
templates/base.html
//templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    {% load static %}
    <link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.css' %}"/>
    <meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1"/>
 <title>{% block title %}Django Chained Dropdown List - Select Box using jQuery Ajax Country City{% endblock %}</title>
</head>
<body>
    <nav class="navbar navbar-default">
        <div class="container-fluid">
            <a class="navbar-brand">Cairocoders</a>
        </div>
    </nav>
 
 <div class="container">
    <div class="col-md-12 well">
        <h3 class="text-primary">Django Chained Dropdown List - Select Box using jQuery Ajax Country City</h3>
        <hr style="border-top:1px dotted #ccc;"/>

  {% block content %} {% endblock %}

    </div>
    </div>
<style>
.custab{
    border: 1px solid #ccc;
    padding: 5px;
    margin: 5% 0;
    box-shadow: 3px 3px 2px #ccc;
    transition: 0.5s;
    }
.custab:hover{
    box-shadow: 3px 3px 0px transparent;
    transition: 0.5s;
    }
</style>
</body>
</html>
settings.py
INSTALLED_APPS = [
    'myapp',
    'widget_tweaks', #pip install django-widget-tweaks https://pypi.org/project/django-widget-tweaks/
]

Friday, June 5, 2020

Django How to Add reCAPTCHA to a Django Site


Django How to Add reCAPTCHA to a Django Site

Google’s reCAPTCHA is a very popular solution to protect your application or website against bots and spam.

In this tutorial I will show how to How to Add reCAPTCHA to a Django Site

First, register your application in the reCAPTCHA admin. https://www.google.com/recaptcha/admin



settings.py
 
#settings.py
from django.contrib.messages import constants as messages
MESSAGE_TAGS = {
    messages.DEBUG: 'alert-info',
    messages.INFO: 'alert-info',
    messages.SUCCESS: 'alert-success',
    messages.WARNING: 'alert-warning',
    messages.ERROR: 'alert-danger',
}

GOOGLE_RECAPTCHA_SECRET_KEY = '6LelrwAVAAAAAPDmyx9HFbLaPdvf4ZkhfjLsm_q8'
views.py
 
#views.py
import json
import urllib

from django.shortcuts import render, redirect
from django.conf import settings
from django.contrib import messages

from myapp.models import Comment
from myapp.forms import CommentForm


def comments(request):
    comments_list = Comment.objects.order_by('-created_at')

    if request.method == 'POST':
        form = CommentForm(request.POST)
        if form.is_valid():

            recaptcha_response = request.POST.get('g-recaptcha-response')
            url = 'https://www.google.com/recaptcha/api/siteverify'
            values = {
                'secret': settings.GOOGLE_RECAPTCHA_SECRET_KEY,
                'response': recaptcha_response
            }
            data = urllib.parse.urlencode(values).encode()
            req =  urllib.request.Request(url, data=data)
            response = urllib.request.urlopen(req)
            result = json.loads(response.read().decode())

            if result['success']:
                form.save()
                messages.success(request, 'New comment added with success!')
            else:
                messages.error(request, 'Invalid reCAPTCHA. Please try again.')

            return redirect('comments')
    else:
        form = CommentForm()

    return render(request, 'comments.html', {'comments': comments_list, 'form': form})
models.py
 
#models.py
from django.db import models

class Comment(models.Model):
    text = models.TextField(max_length=1000)
    created_at = models.DateTimeField(auto_now_add=True)

  
    class Meta:  
        db_table = "comments"
forms.py
 
#forms.py
from django import forms

from myapp.models import Comment


class CommentForm(forms.ModelForm):
    text = forms.CharField(
        widget=forms.Textarea(attrs={'class': 'form-control', 'rows': '3'}),
        required=True,
        max_length=1000
    )

    class Meta:
        model = Comment
        fields = ('text', )
urls.py
 
#urls.py
from django.contrib import admin  
from django.urls import path
from myapp import views  
from django.conf.urls import url


urlpatterns = [  
    path('admin/', admin.site.urls),  
    url(r'^comments/$', views.comments, name='comments'), 
]
templates/comments.html
//templates/comments.html
{% extends 'base.html' %}

{% block javascript %}
  <script src='https://www.google.com/recaptcha/api.js'></script>
{% endblock %}

{% block content %}
  <h1 class="page-header">Comments</h1>
  <ul>
    {% for comment in comments %}
      <li><small>({{ comment.created_at }})</small> {{ comment.text }}</li>
    {% endfor %}
  </ul>
  
  {% if messages %}
  <ul class="messages">
    {% for message in messages %}
      <li class="{{ message.tags }}">{{ message }}</li>
    {% endfor %}
  </ul>
{% endif %}
  <hr>
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <div class="g-recaptcha" data-sitekey="6LelrwAVAAAAAMKd-jsIvtpFJNkVD0jJF6BhQEJP"></div>
    <button type="submit" class="btn btn-primary">Post</button>
  </form>
{% endblock %}
templates/base.html
//templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    {% load static %}
    <link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.css' %}"/>
    <meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1"/>
 <title>{% block title %}Django How to Add reCAPTCHA to a Django Site{% endblock %}</title>
 <link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
</head>
<body>
    <nav class="navbar navbar-default">
        <div class="container-fluid">
            <a class="navbar-brand">Cairocoders</a>
        </div>
    </nav>
 
 <div class="container">
    <div class="col-md-12 well">
        <h3 class="text-primary">Django How to Add reCAPTCHA to a Django Site</h3>
        <hr style="border-top:1px dotted #ccc;"/>
        {% block content %}
  
        {% endblock %}
    </div>
    </div>
{% block javascript %} {% endblock %}

<style>
ul {list-style:none;}
.alert-success, .alert-warning, .alert-info, .alert-danger {
 background-repeat: no-repeat;
 background-position: 10px center;
 height: 40px;
 text-transform: uppercase;
 font-size: 11px;
 line-height: 22px;
 margin-bottom: 20px;
 padding-top: 10px;
 padding-right: 10px;
 padding-bottom: 10px;
 padding-left: 50px;
  
}
.alert-success     {
 background-color: #EBF8D6;
 border: 1px solid #A6DD88;
 color: #539B2D;
 background-image: url({% static 'img/accept00.png' %});
}
.alert-warning      {
 background-color: #FFECE6;
 border: 1px solid #FF936F;
 color: #842100;
 background-image: url({% static 'img/delete00.png' %});
}
.alert-info    {
 background-color: #D3EEF1;
 border: 1px solid #81CDD8;
 color: #369CAB;
 background-image: url({% static 'img/info0000.png' %});
}
.alert-danger   {
 background-color: #FFFBCC;
 border: 1px solid #FFF35E;
 color: #C69E00;
 background-image: url({% static 'img/warning0.png' %});
}
.close-notification     {
 width: 16px;
 height: 16px;
 position: absolute;
 background: url({% static 'img/close000.png' %}) no-repeat;
 top: 4px;
 right: 4px;
 cursor: pointer;
}
</style>
</body>
</html>

Thursday, June 4, 2020

Django How to Filter QuerySets Dynamically using django-filter


Django How to Filter QuerySets Dynamically using django-filter

This tutorial is about how to use the django-filter to add a filtering to your views

I will implement a view to search for users.

Installation
install it with pip:


pip install django-filter settings.py
 
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp',
    'widget_tweaks',
    'django_filters',# pip install django-filter https://django-filter.readthedocs.org/en/latest/ 
]
filters.py
 
#filters.py
from django.contrib.auth.models import User
import django_filters

class UserFilter(django_filters.FilterSet):
    class Meta:
        model = User
        fields = ['username', 'first_name', 'last_name', ]
views.py
 
#views.py
from django.shortcuts import render, redirect

from django.contrib.auth.models import User
from myapp.filters import UserFilter

def search(request):
    user_list = User.objects.all()
    user_filter = UserFilter(request.GET, queryset=user_list)
    return render(request, 'user_list.html', {'filter': user_filter})
urls.py
 
#urls.py
from django.contrib import admin  
from django.urls import path
from myapp import views  
from django.conf.urls import url


urlpatterns = [  
    path('admin/', admin.site.urls),  
    url(r'^search/$', views.search, name='search'),
]
user_list.html
//templates/user_list.html
{% extends 'base.html' %}

{% load widget_tweaks %}

{% block content %}
  <form method="get">
    <div class="well">
      <h4 style="margin-top: 0">Filter</h4>
      <div class="row">
        <div class="form-group col-sm-4 col-md-3">
          {{ filter.form.username.label_tag }}
          {% render_field filter.form.username class="form-control" %}
        </div>
        <div class="form-group col-sm-4 col-md-3">
          {{ filter.form.first_name.label_tag }}
          {% render_field filter.form.first_name class="form-control" %}
        </div>
        <div class="form-group col-sm-4 col-md-3">
          {{ filter.form.last_name.label_tag }}
          {% render_field filter.form.last_name class="form-control" %}
        </div>
      </div>
      <button type="submit" class="btn btn-primary">
        <span class="glyphicon glyphicon-search"></span> Search
      </button>
    </div>
  </form>
  <table class="table table-bordered">
    <thead>
      <tr>
        <th>Username</th>
        <th>First name</th>
        <th>Last name</th>
        <th>Date joined</th>
      </tr>
    </thead>
    <tbody>
      {% for user in filter.qs %}
        <tr>
          <td>{{ user.username }}</td>
          <td>{{ user.first_name }}</td>
          <td>{{ user.last_name }}</td>
          <td>{{ user.date_joined }}</td>
        </tr>
      {% empty %}
        <tr>
          <td colspan="5">No data</td>
        </tr>
      {% endfor %}
    </tbody>
  </table>
{% endblock %}
templates/base.html
//templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    {% load static %}
    <link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.css' %}"/>
    <meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1"/>
 <title>{% block title %}Django How to Filter QuerySets Dynamically using django-filter{% endblock %}</title>
 <link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
</head>
<body>
    <nav class="navbar navbar-default">
        <div class="container-fluid">
            <a class="navbar-brand">Cairocoders</a>
        </div>
    </nav>
 
 <div class="container">
    <div class="col-md-12 well">
        <h3 class="text-primary">Django How to Filter QuerySets Dynamically using django-filter</h3>
        <hr style="border-top:1px dotted #ccc;"/>
        {% block content %}
  
        {% endblock %}
    </div>
    </div>
    <script src="{% static 'js/jquery-3.1.1.min.js' %}"></script>
    <script src="{% static 'js/bootstrap.min.js' %}"></script>
</body>
</html>

Saturday, May 30, 2020

Django How to Add User Profile To Admin


Django How to Add User Profile To Admin

You want to store a few more data related to User. This is how to extend the the default Django User model User Profile admin

Database Table
CREATE TABLE myapp_profile (
id INTEGER PRIMARY KEY,
user_id INTEGER,
location STRING (200),
birthdate DATE,
role INTEGER

);


models.py
 
#models.py
from django.db import models

from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

class Profile(models.Model):
    STUDENT = 1
    TEACHER = 2
    SUPERVISOR = 3
    ROLE_CHOICES = (
        (STUDENT, 'Student'),
        (TEACHER, 'Teacher'),
        (SUPERVISOR, 'Supervisor'),
    )
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    location = models.CharField(max_length=30, blank=True)
    birthdate = models.DateField(null=True, blank=True)
    role = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, null=True, blank=True)

    def __str__(self):  # __unicode__ for Python 2
        return self.user.username
  
    class Meta:  
        db_table = "myapp_profile"

@receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
    instance.profile.save()
admins.py
 
#admin.py
from django.contrib import admin

from myapp.models import Profile
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User

class ProfileInline(admin.StackedInline): #StackedInline normally is used for formsets
    model = Profile
    can_delete = False
    verbose_name_plural = 'Profile'
    fk_name = 'user'
 
class CustomUserAdmin(UserAdmin):
    inlines = (ProfileInline, )
    list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff', 'get_location') #Add Profile Fields to List View
    list_select_related = ('profile', )

    def get_location(self, instance):
        return instance.profile.location
    get_location.short_description = 'Location'
 
    def get_inline_instances(self, request, obj=None): #get_inline_instances display the inlines only in the edit form
        if not obj:
            return list()
        return super(CustomUserAdmin, self).get_inline_instances(request, obj)


admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)

Related Post