Django is a very popular python web framework
To open the shell:
python manage.py shell
Import models and start working:
>>> from article.models import Article
>>> articles = Article.objects.all()
>>> print(articles)
imports
from django.urls import path, re_path
from django.conf import settings
from django.views.static import serve
urls.py
re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
re_path(r'^static/(?P<path>.*)$', serve, {'document_root': settings.STATIC_ROOT}),
Django routings
# Total number of books.
>>> Book.objects.count()
2452
# Total number of books with publisher=BaloneyPress
>>> Book.objects.filter(publisher__name='BaloneyPress').count()
73
# Average price across all books.
>>> from django.db.models import Avg
>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35}
# Max price across all books.
>>> from django.db.models import Max
>>> Book.objects.all().aggregate(Max('price'))
{'price__max': Decimal('81.20')}
# Difference between the highest priced book and the average price of all books.
>>> from django.db.models import FloatField
>>> Book.objects.aggregate(
... price_diff=Max('price', output_field=FloatField()) - Avg('price'))
{'price_diff': 46.85}
# All the following queries involve traversing the Book<->Publisher
# foreign key relationship backwards.
# Each publisher, each with a count of books as a "num_books" attribute.
>>> from django.db.models import Count
>>> pubs = Publisher.objects.annotate(num_books=Count('book'))
>>> pubs
<QuerySet [<Publisher: BaloneyPress>, <Publisher: SalamiPress>, ...]>
>>> pubs[0].num_books
73
# Each publisher, with a separate count of books with a rating above and below 5
>>> from django.db.models import Q
>>> above_5 = Count('book', filter=Q(book__rating__gt=5))
>>> below_5 = Count('book', filter=Q(book__rating__lte=5))
>>> pubs = Publisher.objects.annotate(below_5=below_5).annotate(above_5=above_5)
>>> pubs[0].above_5
23
>>> pubs[0].below_5
12
# The top 5 publishers, in order by number of books.
>>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5]
>>> pubs[0].num_books
1323
from django.db.models import Count, Exists, OuterRef
Category.objects.annotate(
num_products=Count('products'),
is_viewed=Exists(View.objects.filter(category=OuterRef('pk')))
)
from django.db.models import Sum
Buy.objects.filter(sell__buyer__isnull=True
).aggregate(sum_buy_price=Sum('buy_price'),
sum_sell_price=Sum('sell_price'))
urls.py
path('<int:report_quarter>/<int:report_year>/', FeedbackListView.as_view(), name='feedbacks_quarter_list')
views.py
def get_context_data(self, **kwargs):
report_quarter = self.kwargs['report_quarter']
report_year = self.kwargs['report_year']
class FixtureViewSet(viewsets.ModelViewSet):
serializer_class = FixtureSerializer
permission_classes = [permissions.IsAuthenticated]
filter_backends = [django_filters.rest_framework.DjangoFilterBackend]
filterset_fields = ('date', "home", "away",)
def get_queryset(self):
given_date = self.request.query_params.get('date')
queryset = Fixture.objects.filter(date__date=given_date).order_by('date')
return queryset
Override the context data
class ArticleListView(ListView):
model = Article
def get_context_data(self, *args, **kwargs):
context_data = super().get_context_data(*args, **kwargs)
if context_data['object_list']:
context_data['object_list'] = context_data['object_list'].order_by('-date')
return context_data
Setting Ordering of elements:
Need to set ordering
in Meta
of the model.
class Article(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
created_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('article_detail', args=[str(self.id)])
class Meta:
ordering = ['-created_date']
class Woman(models.Model):
name = models.CharField(max_length=100)
class Man(models.Model):
name = models.CharField(max_length=100)
wife = models.OneToOneField(Woman, related_name = 'husband', null=True, blank=True, on_delete=models.SET_NULL)
>>> john = Man.objects.create(name='John')
>>> alice = Woman.objects.create(name='Alice')
>>> susan = Woman.objects.create(name='Susan')
>>> john.wife = alice
>>> alice.husband # The marriage was brief...
>>> john.wife = None
>>> john.save()
>>> john.wife = susan
>>> john.save()
>>> susan.save()
>>> alice.save()
related_name:
The related_name attribute specifies the name of the reverse
relation from the Parent model back to child model.
If we don’t specify a related_name, Django automatically creates one using the name of child model with the suffix _set
, for instance User.article_set.all()
.
We can override save method in django model.
class ModelAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj.save(form=form)
class Model(model.Model):
description=models.CharField()
# this is not needed if small_image is created at set_image
def save(self, *args, **kwargs):
self.description = "my desc"
super(Model, self).save(*args, **kwargs)
When looking at the options in a Django model definition, it’s crucial to understand that they serve (at least) two purposes: defining the database tables, and defining the default format and validation of model forms. (I say “default” because the values can always be overridden by providing a custom form.) Some options affect the database, some options affect forms, and some affect both.
When it comes to null
and blank
, other answers have already made clear that the former affects the database table definition and the latter affects model validation. I think the distinction can be made even clearer by looking at the use cases for all four possible configurations:
null=False
, blank=False
: This is the default configuration and means that the value is required in all circumstances.null=True
, blank=True
: This means that the field is optional in all circumstances. (As noted below, though, this is not the recommended way to make string-based fields optional.)null=False
, blank=True
: This means that the form doesn’t require a value, but the database does. There are a number of use cases for this:
NULL
was also allowed you would end up with two different ways to indicate a missing value.save()
method, say). You don’t want the user to provide the value in a form (hence blank=True
), but you do want the database to enforce that a value is always provided (null=False
).ManyToManyField
is optional. Because this field is implemented as a separate table rather than a database column, null
is meaningless. The value of blank
will still affect forms, though, controlling whether or not validation will succeed when there are no relations.null=True
, blank=False
: This means that the form requires a value, but the database doesn’t. This may be the most infrequently used configuration, but there are some use cases for it:
ForeignKey
for which you don’t wish to allow cascade deletion. That is, in normal use the relation should always be there (blank=False
), but if the thing it points to happens to be deleted, you don’t want this object to be deleted too. In that case you can use null=True
and on_delete=models.SET_NULL
to implement a simple kind of soft deletion.Use forloop.counter provided by django:
{% for item in item_list %}
{{ forloop.counter }} # starting index 1
{{ forloop.counter0 }} # starting index 0
# do your stuff
{% endfor %}
pip install django-mathfilters
load mathfilters
item.min_count|div:2
Django Forms
Django Serializers
Dealing with admin panel
Validate using Ajax if username already exists while SignUp:
from django.contrib.auth.models import User
from django.http import JsonResponse
def validate_username(request):
username = request.GET.get('username', None)
data = {
'is_taken': User.objects.filter(username__iexact=username).exists()
}
if data['is_taken']:
data['error_message'] = 'A user with this username already exists.'
return JsonResponse(data)
{% extends 'base.html' %}
{% block javascript %}
<script>
$("#id_username").change(function () {
var form = $(this).closest("form");
$.ajax({
url: form.attr("data-validate-username-url"),
data: form.serialize(),
dataType: 'json',
success: function (data) {
if (data.is_taken) {
alert(data.error_message);
}
}
});
});
</script>
{% endblock %}
{% block content %}
<form method="post" data-validate-username-url="{% url 'validate_username' %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Sign up</button>
</form>
{% endblock %}
Getting JSON from API url:
from rest_framework.response import Response
from rest_framework.views import APIView
class FeedbackNetworkAPIView(APIView):
def get(self, request):
. . . . . .
# tuple to avoid: TypeError: unhashable type: 'list'
track_data = {
"nodes": tuple(nodes),
"edges": tuple(edges),
}
return Response(track_data)
<script>
$.getJSON('http://localhost:8000/feedback/network/api/', function (data) {
$nodes = data["nodes"];
$edges = data["edges"];
var nodes = new vis.DataSet($nodes);
var edges = new vis.DataSet($edges);
var container = document.getElementById('mynetwork');
var data = {nodes: nodes, edges: edges};
var options = {};
var network = new vis.Network(container, data, options);
});
</script>
In [1]: def good_function():
...: print 'I am a good function'
...:
...:
In [2]: def decorator(orig_func):
...: def bad_func():
...: print 'I am a bad function'
...: return bad_func
...:
In [3]: good_function = decorator(good_function)
In [4]: good_function()
I am a bad function
In [5]: @decorator
....: def good_function2():
....: print 'I am a good function'
....:
....:
In [6]: good_function2()
I am a bad function
import math
def is_val_positive_deco(orig_func):
def temp_func(val):
if val < 0:
return 0
else:
return orig_func(val)
return temp_func
@is_val_positive_deco
def sqrt(val):
return math.pow(val, (1.0/2))
print sqrt(-1)
print sqrt(4)
is_val_positive_deco
which will make functions return 0, if the argument passed is negative.__call__
method.class LogArgumentsDecorator(object):
def __init__(self, orig_func):
self.orig_func = orig_func
print 'started logging: %s' % orig_func.__name__
def __call__(self, *args, **kwargs):
print 'args: %s' % args
print 'kwargs:%s'% kwargs
return self.orig_func(*args, **kwargs)
@LogArgumentsDecorator
def sum_of_squares(a, b):
return a*a + b*b
print sum_of_squares(3, b=4)
Output:
started logging: sum_of_squares
args: 3
kwargs:{'b': 4}
25
class LoginRequiredDecorator(object):
def __init__(self, orig_func):
self.orig_func = orig_func
def __call__(self, request, *args, **kwargs):
if request.user.is_authenticated():
self.orig_func(request, *args, **kwargs)
else:
return HttpResponseRedirect(reverse('...'))
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware’,
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
SecurityMiddleware
, then SessionMiddleware
all the way until XFrameOptionsMiddleware
.XFrameOptionsMiddleware
, then MessageMiddleware
all the way until SecurityMiddleware
.DEBUG=True
.This is what our Middleware will look like:
Our view function throws an uncaught exception, the SOET Middleware process it, search for a solution on StackOverflow, and print the three most relevant results for the developer directly in this terminal window.
Cool right? We will see how easy it is to implement it.
class StackOverflowMiddleware(object):
def process_exception(self, request, exception):
return None
Now register the new Middleware in the MIDDLEWARE_CLASSES configuration:
MIDDLEWARE_CLASSES = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'soet.middleware.StackOverflowMiddleware',
]
I’ve registered it as the last one because the process_exception() method is only processed during the responsecycle, and I want my middleware to be executed first so no other Middleware supress the thrown exception.
At this point our brand new Middleware isn’t doing anything really. But it is already being executed. We can test it by putting a print statement inside the process_exception() method. Also it is important that our method always return None so to keep the flow of the Middlewares processing. We don’t want to affect the behavior of what is returned to the client.
Now also let’s make sure we are only executing this Middleware if the DEBUG=True:
from django.conf import settings
class StackOverflowMiddleware(object):
def process_exception(self, request, exception):
if settings.DEBUG:
print exception.__class__.__name__
print exception.message
return None
import requests
from django.conf import settings
class StackOverflowMiddleware(object):
def process_exception(self, request, exception):
if settings.DEBUG:
intitle = u'{}: {}'.format(exception.__class__.__name__, exception.message)
print intitle
url = 'https://api.stackexchange.com/2.2/search'
params = {
'order': 'desc',
'sort': 'votes',
'site': 'stackoverflow',
'pagesize': 3,
'tagged': 'python;django',
'intitle': intitle
}
r = requests.get(url, params=params)
questions = r.json()
print ''
for question in questions['items']:
print question['title']
print question['link']
print ''
return None