Tutorial para o projeto negros.dev - A Essência do Django

Overview

Negros Dev

Tutorial para o site negros.dev

Este projeto foi feito com:

Como rodar o projeto?

  • Clone esse repositório.
  • Crie um virtualenv com Python 3.
  • Ative o virtualenv.
  • Instale as dependências.
  • Rode as migrações.
git clone https://github.com/rg3915/django-negros-dev.git
cd django-negros-dev
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python contrib/env_gen.py
python manage.py migrate
python manage.py createsuperuser --username="admin" --email=""

Tutorial

O que é Django?

Segundo Django Brasil,

Django é um framework web de alto nível escrito em Python que estimula o desenvolvimento rápido e limpo.

  • adota o padrão MTV
  • possui ORM
  • admin
  • herança de templates e modelos
  • open source

Documentação oficial Django.

MVC x MTV

  • Model - é o modelo, a camada de abstração do banco de dados, onde acontece o ORM
  • View - é o controlador, onde acontece as regras de negócio e a comunicação entre a base de dados e o navegador
  • Templates - é a camada de apresentação, são as páginas html

image

mtv2.png

ORM

Object Relational Mapper (Mapeamento Objeto Relacional)

Usa orientação a objetos para abstrair as querys do banco de dados.

O exemplo a seguir retorna todos os usuários cujo email termina com gmail.com.

User.objects.filter(email__endswith='gmail.com')

No modelo a seguir Person será o nome da tabela no banco de dados e first_name será o nome do campo.

# models.py
class Person(models.Model):
    first_name = models.CharField('nome', max_length=100, unique=True)

O que é Virtualenv e Requirements?

Virtualenv é um ambiente virtual que isola seu projeto junto com suas dependências.

E requirements é um arquivo (requirements.txt) que lista todas as bibliotecas que você precisa usar no seu projeto, por exemplo:

# requirements.txt
Django==3.1.8
dj-database-url==0.5.0
python-decouple==3.4
django-extensions==3.1.2

Qual é a essência do Django?

  • ORM - abstrair as querys SQL.
  • Admin - O painel de Admin facilita a nossa vida com um CRUD básico.
  • Herança de templates e modelos

Iniciando um projeto

  • Instale o Python na sua versão mais recente.

Crie uma virtualenv

python -m venv .venv

Ative a virtualenv

# Linux
source .venv/bin/activate
# Windows
.venv\Scripts\activate.bat

Instale as dependências

pip install -U pip
pip install Django==3.1.8 dj-database-url python-decouple django-extensions

Importante: crie um arquivo requirements.txt

pip freeze

pip freeze | grep Django==3.1.8 >> requirements.txt
pip freeze | grep dj-database-url >> requirements.txt
pip freeze | grep python-decouple >> requirements.txt
pip freeze | grep django-extensions >> requirements.txt

cat requirements.txt

Criando um .gitignore

Veja no repositório do projeto.

Gere um arquivo .env

Copiar o conteúdo de env_gen.py

https://github.com/rg3915/django-negros-dev/blob/main/contrib/env_gen.py

mkdir contrib
touch contrib/env_gen.py

python contrib/env_gen.py

cat .env

Criando um projeto

django-admin.py startproject myproject .

Criando uma app

cd myproject
python ../manage.py startapp core

Edite o settings.py

# settings.py
INSTALLED_APPS = [
    ...
    'django_extensions',
    'myproject.core',
]

Rodando as migrações para criar um banco de dados local

cd ..
python manage.py migrate

Criando um super usuário

python manage.py createsuperuser

Rodando a aplicação (nível 0)

python manage.py runserver

A aplicação roda na porta 8000.

Projeto mínimo

Veja a estrutura do projeto

├── .gitignore
├── contrib
│   └── env_gen.py
├── db.sqlite3
├── manage.py
├── myproject
│   ├── asgi.py
│   ├── core
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── models.py
│   │   ├── tests.py
│   │   └── views.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── README.md
└── requirements.txt

Nível 1

Editar settings.py

# settings.py
from pathlib import Path

from decouple import Csv, config
from dj_database_url import parse as dburl

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = config('SECRET_KEY')

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = config('DEBUG', default=False, cast=bool)

ALLOWED_HOSTS = config('ALLOWED_HOSTS', default=[], cast=Csv())

...

# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases

default_dburl = 'sqlite:///' + str(BASE_DIR / 'db.sqlite3')
DATABASES = {
    'default': config('DATABASE_URL', default=default_dburl, cast=dburl),
}

...

LANGUAGE_CODE = 'pt-br'

TIME_ZONE = 'America/Sao_Paulo'

...

STATIC_ROOT = BASE_DIR.joinpath('staticfiles')

Editar urls.py

# urls.py
from django.contrib import admin
from django.http import HttpResponse
from django.urls import path


def index(request):
    return HttpResponse('<h1>Django Tutorial</h1>')


urlpatterns = [
    path('', index, name='index'),
    path('admin/', admin.site.urls),
]

Nível 2

Editar core/urls.py

touch myproject/core/urls.py
# core/urls.py
from django.urls import path

from .views import index

app_name = 'core'

urlpatterns = [
    path('', index, name='index'),
]

Editar urls.py

# urls.py
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('', include('myproject.core.urls', namespace='core')),
    path('admin/', admin.site.urls),
]

Editar core/views.py

touch myproject/core/views.py
# core/views.py
from django.http import HttpResponse


def index(request):
    return HttpResponse('<h1>Django Tutorial</h1>')

Nível 3

Editar core/views.py

# core/views.py
from django.shortcuts import render


def index(request):
    template_name = 'index.html'
    return render(request, template_name)

Editar core/templates/index.html

mkdir myproject/core/templates
touch myproject/core/templates/index.html
<!-- index -->
<h1>Django Tutorial</h1>
<h2>Negros Dev</h2>

Projeto mais completo

Instalando e usando PostgreSQL

sudo apt-get install -y postgresql-12 postgresql-contrib-12

Criar database

sudo su - postgres
psql -U postgres -c "CREATE ROLE myuser ENCRYPTED PASSWORD 'mypass' LOGIN;"
psql -U postgres -c "CREATE DATABASE mydb OWNER myuser;"

Editar o settings.py

# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': config('POSTGRES_DB', 'postgres'),
        'USER': config('POSTGRES_USER', 'postgres'),
        'PASSWORD': config('POSTGRES_PASSWORD', ''),
        'HOST': config('DB_HOST', ''),
        'PORT': '5432',
    }
}

Editar o .env

# .env
POSTGRES_DB=
POSTGRES_USER=
POSTGRES_PASSWORD=
DB_HOST=localhost

Instalando psycopg2-binary

django.core.exceptions.ImproperlyConfigured: Error loading psycopg2 module: No module named 'psycopg2'
pip install psycopg2-binary

pip freeze | grep psycopg2-binary >> requirements.txt

Criando um novo app

cd myproject
python ../manage.py startapp expense
cd ..

models.png

Edite o settings.py

# settings.py
INSTALLED_APPS = [
    ...
    'myproject.core',
    'myproject.expense',
]

Editar core/models.py

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


class TimeStampedModel(models.Model):
    created = models.DateTimeField(
        'criado em',
        auto_now_add=True,
        auto_now=False
    )
    modified = models.DateTimeField(
        'modificado em',
        auto_now_add=False,
        auto_now=True
    )

    class Meta:
        abstract = True

Editar expense/models.py

https://docs.djangoproject.com/en/3.2/ref/models/fields/

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

from myproject.core.models import TimeStampedModel


class Customer(models.Model):
    first_name = models.CharField('nome', max_length=50)
    last_name = models.CharField('sobrenome', max_length=50, null=True, blank=True)  # noqa E501
    email = models.EmailField(null=True, blank=True)

    class Meta:
        ordering = ('first_name',)
        verbose_name = 'cliente'
        verbose_name_plural = 'clientes'

    @property
    def full_name(self):
        return f'{self.first_name} {self.last_name or ""}'.strip()

    def __str__(self):
        return self.full_name


class Expense(TimeStampedModel):
    description = models.CharField('descrição', max_length=100)
    payment_date = models.DateField('data de pagamento', null=True, blank=True)
    customer = models.ForeignKey(
        Customer,
        on_delete=models.SET_NULL,
        verbose_name='pago a',
        related_name='expenses',
        null=True,
        blank=True
    )
    value = models.DecimalField('valor', max_digits=7, decimal_places=2)
    paid = models.BooleanField('pago', default=False)

    class Meta:
        ordering = ('-payment_date',)
        verbose_name = 'despesa'
        verbose_name_plural = 'despesas'

    def __str__(self):
        return self.description

    # def get_absolute_url(self):
    #     return reverse_lazy('_detail', kwargs={'pk': self.pk})

Editar expense/admin.py

# expense/admin.py
from django.contrib import admin

from .models import Customer, Expense

# admin.site.register(Customer)


@admin.register(Customer)
class CustomerAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'email')
    search_fields = ('first_name', 'last_name', 'email')


@admin.register(Expense)
class ExpenseAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'customer', 'value', 'payment_date', 'paid')
    search_fields = ('description', 'customer__first_name', 'customer__last_name')  # noqa E501
    list_filter = ('paid',)
    date_hierarchy = 'payment_date'

Atualizando o banco

Gerar arquivo de migração.

python manage.py makemigrations

Executar a migração.

python manage.py migrate

ORM

python manage.py shell_plus

Criando alguns registros

customers = ['Huguinho', 'Zezinho', 'Luizinho']
for customer in customers:
    Customer.objects.create(first_name=customer)

customers = ['Prático', 'Heitor', 'Cícero']
items = []
for customer in customers:
    obj = Customer(first_name=customer)
    items.append(obj)

Customer.objects.bulk_create(items)

Criar despesas pelo Admin.

Alterando a data das despesas não pagas.

python manage.py shell_plus

# Selecionar as despesas não pagas.
expenses = Expense.objects.filter(paid=False)

# Alterando a data de pagamento para uma data futura.
from datetime import date

future = date(2021, 5, 2)

for expense in expenses:
    expense.payment_date = future

Expense.objects.bulk_update(expenses, ['payment_date'])

Cuidado ao deletar

expense = Expense.objects.get(pk=1)
expense.delete()

Templates

mkdir -p myproject/core/templates/includes

touch myproject/core/templates/base.html
touch myproject/core/templates/includes/nav.html


mkdir -p myproject/core/static/{css,img,js}

touch myproject/core/static/css/style.css
touch myproject/core/static/js/main.js

mkdir -p myproject/expense/templates/expense

touch myproject/expense/templates/expense/expense_{list,detail,form}.html

tree

Editar base.html

<!-- 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, shrink-to-fit=no">
  <link rel="shortcut icon" href="https://www.djangoproject.com/favicon.ico">
  <title>Django</title>

  <!-- Bootstrap core CSS -->
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">

  <!-- Font-awesome -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">

  <link rel="stylesheet" href="{% static 'css/style.css' %}">

  {% block css %}{% endblock css %}

</head>

<body>
  <div class="container">
    {% include "includes/nav.html" %}
    {% block content %}{% endblock content %}
  </div>

  <!-- jQuery -->
  <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  <!-- Bootstrap core JS -->
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
</body>

</html>

Editar includes/nav.html

<!-- includes/nav.html -->
<!-- https://getbootstrap.com/docs/4.0/examples/starter-template/ -->
<!-- https://github.com/JTruax/bootstrap-starter-template/blob/master/template/start.html -->
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
  <a class="navbar-brand" href="{% url 'core:index' %}">Navbar</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarsExampleDefault">
    <ul class="navbar-nav mr-auto">
      <li class="nav-item active">
        <a class="nav-link" href="{% url 'core:index' %}">Home <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="">Despesas</a>
      </li>
    </ul>
  </div>
</nav>

Editar index.html

<!-- index.html -->
{% extends "base.html" %}

{% block content %}
  <div class="jumbotron">
    <h1>Django Tutorial</h1>
    <a href="https://negros.dev/" target="_blank">negros.dev</a>
  </div>
{% endblock content %}

Editar style.css

cat << EOF > myproject/core/static/css/style.css
body {
  margin-top: 60px;
}

label.required:after {
  content: ' *';
  color: red;
}

.no {
  color: red;
}
EOF

Rodar a aplicação

Editar expense_list.html

<!-- expense_list.html -->
{% extends "base.html" %}

{% block content %}
  Lista de Despesas
{% endblock content %}

Editar expense_detail.html

<!-- expense_detail.html -->
{% extends "base.html" %}

{% block content %}
  Detalhes de Despesa
{% endblock content %}

Editar expense_form.html

<!-- expense_form.html -->
{% extends "base.html" %}

{% block content %}
  Adicionar Despesa
{% endblock content %}

Editar expense/views.py

# expense/views.py
from django.shortcuts import render


def expense_list(request):
    template_name = 'expense/expense_list.html'
    return render(request, template_name)


def expense_detail(request, pk):
    template_name = 'expense/expense_detail.html'
    return render(request, template_name)


def expense_create(request):
    template_name = 'expense/expense_form.html'
    return render(request, template_name)

Editar expense/urls.py

touch myproject/expense/urls.py
# expense/urls.py
from django.urls import path

from myproject.expense import views as v

app_name = 'expense'

urlpatterns = [
    path('', v.expense_list, name='expense_list'),
    path('<int:pk>/', v.expense_detail, name='expense_detail'),
    path('create/', v.expense_create, name='expense_create'),
]

Editar urls.py

# urls.py
...
path('expense/', include('myproject.expense.urls', namespace='expense')),
...

Editar includes/nav.html

...
<a class="nav-link" href="{% url 'expense:expense_list' %}">Despesas</a>
...

Rodar a aplicação e navegar pelas urls.

CRUD

Lista

Editar expense/views.py

# expense/views.py
from .models import Expense


def expense_list(request):
    template_name = 'expense/expense_list.html'
    object_list = Expense.objects.all()
    context = {'object_list': object_list}
    return render(request, template_name, context)

Editar expense_list.html

<!-- expense_list.html -->
{% extends "base.html" %}

{% block content %}
  <h1>
    Lista de Despesas
    <a class="btn btn-primary" href="{% url 'expense:expense_create' %}">Adicionar</a>
  </h1>
  <table class="table">
    <thead>
      <tr>
        <th>Descrição</th>
        <th>Pago a</th>
        <th>Valor</th>
        <th>Data de pagamento</th>
      </tr>
    </thead>
    <tbody>
      {% for object in object_list %}
        <tr>
          <td>
            <a href="{{ object.get_absolute_url }}">{{ object.description }}</a>
          </td>
          <td>{{ object.customer|default:'---' }}</td>
          <td>{{ object.value }}</td>
          <td>{{ object.payment_date|date:'d/m/Y'|default:'---' }}</td>
        </tr>
      {% endfor %}
    </tbody>
  </table>
{% endblock content %}

Editar expense/models.py

# expense/models.py
from django.urls import reverse_lazy

    ...
    def get_absolute_url(self):
        return reverse_lazy('expense:expense_detail', kwargs={'pk': self.pk})

Detalhes

Editar expense_detail.html

<!-- expense_detail.html -->
{% extends "base.html" %}

{% block content %}
  <h1>Detalhes de Despesa</h1>

  <ul>
    <li><b>Descrição:</b> {{ object.description }}</li>
    <li><b>Cliente:</b> {{ object.customer|default:'---' }}</li>
    <li><b>Valor:</b> {{ object.value }}</li>
    <li><b>Data de pagamento:</b> {{ object.payment_date|date:'d/m/Y'|default:'---' }}</li>
  </ul>
{% endblock content %}

Editar expense/views.py

# expense/views.py
def expense_detail(request, pk):
    template_name = 'expense/expense_detail.html'
    _object = Expense.objects.get(pk=pk)
    context = {'object': _object}
    return render(request, template_name, context)

Adicionar

Editar expense_form.html

<!-- expense_form.html -->
{% extends "base.html" %}

{% block content %}
  <h1>Despesa</h1>
  <div class="cols-6">
    <form class="form-horizontal" action="." method="POST" enctype="multipart/form-data">
      <div class="col-sm-6">
        {% csrf_token %}
        {{ form.as_p }}
        <div class="form-group">
          <button type="submit" class="btn btn-primary">Salvar</button>
        </div>
      </div>
    </form>
  </div>
{% endblock content %}

Editar expense/forms.py

touch myproject/expense/forms.py
# expense/forms.py
from django import forms

from .models import Expense


class ExpenseForm(forms.ModelForm):
    required_css_class = 'required'

    payment_date = forms.DateField(
        label='Data de pagamento',
        widget=forms.DateInput(
            format='%Y-%m-%d',
            attrs={
                'type': 'date',
            }),
        input_formats=('%Y-%m-%d',),
        required=False,
    )

    class Meta:
        model = Expense
        # fields = '__all__'
        fields = ('description', 'payment_date', 'customer', 'value')
        # exclude = ('paid',)

    def __init__(self, *args, **kwargs):
        super(ExpenseForm, self).__init__(*args, **kwargs)
        for field_name, field in self.fields.items():
            field.widget.attrs['class'] = 'form-control'

Editar expense/views.py

# expense/views.py
from django.shortcuts import redirect, render

from .forms import ExpenseForm
from .models import Expense


def expense_create(request):
    template_name = 'expense/expense_form.html'
    form = ExpenseForm(request.POST or None)

    if request.method == 'POST':
        if form.is_valid():
            form.save()
            return redirect('expense:expense_list')

    context = {'form': form}
    return render(request, template_name, context)

Editar

Editar expense_list.html

<!-- expense_list.html -->

<th>Ações</th>

  <td>
    <a href="{% url 'expense:expense_update' object.pk %}">
      <i class="fa fa-edit"></i>
    </a>
  </td>

Editar expense/urls.py

# expense/urls.py
...
path('<int:pk>/update/', v.expense_update, name='expense_update'),

Editar expense/views.py

# expense/views.py
def expense_update(request, pk):
    template_name = 'expense/expense_form.html'
    instance = Expense.objects.get(pk=pk)
    form = ExpenseForm(request.POST or None, instance=instance)

    if request.method == 'POST':
        if form.is_valid():
            form.save()
            return redirect('expense:expense_list')

    context = {'form': form}
    return render(request, template_name, context)

Deletar

Editar expense_list.html

<a href="{% url 'expense:expense_delete' object.pk %}" style="padding-left: 7px">
  <i class="fa fa-close no"></i>
</a>

Editar expense/urls.py

# expense/urls.py
...
path('<int:pk>/delete/', v.expense_delete, name='expense_delete'),

Editar expense/views.py

# expense/views.py
def expense_delete(request, pk):
    template_name = 'expense/expense_confirm_delete.html'
    obj = Expense.objects.get(pk=pk)

    if request.method == 'POST':
        obj.delete()
        return redirect('expense:expense_list')

    context = {'object': obj}
    return render(request, template_name, context)

Editar expense/expense_confirm_delete.html

touch myproject/expense/templates/expense/expense_confirm_delete.html
<!-- expense_confirm_delete.html -->
{% extends "base.html" %}

{% block content %}
  <h1>Deletar Despesa</h1>
  <div class="cols-6">
    <form action="." method="POST">
      <div class="col-sm-6">
        {% csrf_token %}
        <p>Deseja deletar {{ object }} ?</p>
        <p>Valor: {{ object.value }}</p>
        <div class="form-group">
          <button type="submit" class="btn btn-primary">Sim</button>
          <a class="btn btn-danger" href="{% url 'expense:expense_list' %}">Não</a>
        </div>
      </div>
    </form>
  </div>
{% endblock content %}

Class Based View

https://ccbv.co.uk/

Editar expense/urls.py

# expense/urls.py
from django.urls import path

from myproject.expense import views as v

app_name = 'expense'

urlpatterns = [
    # path('', v.expense_list, name='expense_list'),
    # path('<int:pk>/', v.expense_detail, name='expense_detail'),
    # path('create/', v.expense_create, name='expense_create'),
    # path('<int:pk>/update/', v.expense_update, name='expense_update'),
    # path('<int:pk>/delete/', v.expense_delete, name='expense_delete'),
    path('', v.ExpenseListView.as_view(), name='expense_list'),
    path('<int:pk>/', v.ExpenseDetailView.as_view(), name='expense_detail'),
    path('create/', v.ExpenseCreateView.as_view(), name='expense_create'),
    path('<int:pk>/update/', v.ExpenseUpdateView.as_view(), name='expense_update'),
    path('<int:pk>/delete/', v.ExpenseDeleteView.as_view(), name='expense_delete'),
]

Editar expense/views.py

# expense/views.py
from django.shortcuts import redirect, render
from django.urls import reverse_lazy
from django.views.generic import (
    CreateView,
    DeleteView,
    DetailView,
    ListView,
    UpdateView
)

...

class ExpenseListView(ListView):
    model = Expense


class ExpenseDetailView(DetailView):
    model = Expense


class ExpenseCreateView(CreateView):
    model = Expense
    form_class = ExpenseForm


class ExpenseUpdateView(UpdateView):
    model = Expense
    form_class = ExpenseForm


class ExpenseDeleteView(DeleteView):
    model = Expense
    success_url = reverse_lazy('expense:expense_list')

Assista: Python-triangulo: Django: FBV vs CBV

Links

Owner
Regis Santos
Python developer and newcomer at VueJS. #django #flask #jQuery #VueJS
Regis Santos
Location field and widget for Django. It supports Google Maps, OpenStreetMap and Mapbox

django-location-field Let users pick locations using a map widget and store its latitude and longitude. Stable version: django-location-field==2.1.0 D

Caio Ariede 481 Dec 29, 2022
A web app which allows user to query the weather info of any place in the world

weather-app This is a web app which allows user to get the weather info of any place in the world as soon as possible. It makes use of OpenWeatherMap

Oladipo Adesiyan 3 Sep 20, 2021
This is a sample Django Form.

Sample FORM Installation guide Clone repository git clone https://github.com/Ritabratadas343/SampleForm.git cd to repository. Create a virtualenv by f

Ritabrata Das 1 Nov 05, 2021
Easily share data across your company via SQL queries. From Grove Collab.

SQL Explorer SQL Explorer aims to make the flow of data between people fast, simple, and confusion-free. It is a Django-based application that you can

Grove Collaborative 2.1k Dec 30, 2022
A Django chatbot that is capable of doing math and searching Chinese poet online. Developed with django, channels, celery and redis.

Django Channels Websocket Chatbot A Django chatbot that is capable of doing math and searching Chinese poet online. Developed with django, channels, c

Yunbo Shi 8 Oct 28, 2022
Twitter Bootstrap for Django Form

Django bootstrap form Twitter Bootstrap for Django Form. A simple Django template tag to work with Bootstrap Installation Install django-bootstrap-for

tzangms 557 Oct 19, 2022
open source online judge based on Vue, Django and Docker

An onlinejudge system based on Python and Vue

Qingdao University(青岛大学) 5.2k Jan 09, 2023
Basic implementation of Razorpay payment gateway 💳 with Django

Razorpay Payment Integration in Django 💥 In this project Razorpay payment gateway 💳 is integrated with Django by breaking down the whole process int

ScaleReal 12 Dec 12, 2022
A package to handle images in django

Django Image Tools Django Image Tools is a small app that will allow you to manage your project's images without worrying much about image sizes, how

The Bonsai Studio 42 Jun 02, 2022
A fresh approach to autocomplete implementations, specially for Django.

A fresh approach to autocomplete implementations, specially for Django. Status: v3 stable, 2.x.x stable, 1.x.x deprecated. Please DO regularely ping us with your link at #yourlabs IRC channel

YourLabs 1.6k Dec 22, 2022
Helps working with singletons - things like global settings that you want to edit from the admin site.

Django Solo +---------------------------+ | | | | | \ | Django Solo helps

Sylvain Toé 726 Jan 08, 2023
Money fields for Django forms and models.

django-money A little Django app that uses py-moneyed to add support for Money fields in your models and forms. Django versions supported: 1.11, 2.1,

1.4k Jan 06, 2023
Add Chart.js visualizations to your Django admin using a mixin class

django-admincharts Add Chart.js visualizations to your Django admin using a mixin class. Example from django.contrib import admin from .models import

Dropseed 22 Nov 22, 2022
A simple Django dev environment setup with docker for demo purposes for GalsenDev community

GalsenDEV Docker Demo This is a basic Django dev environment setup with docker and docker-compose for a GalsenDev Meetup. The main purposes was to mak

3 Jul 03, 2021
Rosetta is a Django application that eases the translation process of your Django projects

Rosetta Rosetta is a Django application that facilitates the translation process of your Django projects. Because it doesn't export any models, Rosett

Marco Bonetti 909 Dec 26, 2022
It takes time to start a Django Project and make it almost production-ready.

It takes time to start a Django Project and make it almost production-ready. A developer needs to spend a lot of time installing required libraries, setup a database, setup cache as well as hiding se

Khan Asfi Reza 1 Jan 01, 2022
Django Audit is a simple Django app that tracks and logs requests to your application.

django-audit Django Audit is a simple Django app that tracks and logs requests to your application. Quick Start Install django-audit pip install dj-au

Oluwafemi Tairu 6 Dec 01, 2022
Django Simple Spam Blocker is blocking spam by regular expression.

Django Simple Spam Blocker is blocking spam by regular expression.

Masahiko Okada 23 Nov 29, 2022
WeatherApp - Simple Python Weather App

Weather App Please star this repo if you like ⭐ It's motivates me a lot! Stack A

Ruslan Shvetsov 3 Apr 18, 2022
Visual DSL framework for django

Preface Processes change more often than technic. Domain Rules are situational and may differ from customer to customer. With diverse code and frequen

Dmitry Kuksinsky 165 Jan 08, 2023