In models.py
from django.contrib import auth
# Create your models here.
class User(auth.models.User,auth.models.PermissionsMixin):
def __str__(self):
return "@{}".format(self.username)
In forms.py
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm
class UserCreateForm(UserCreationForm):
class Meta:
model = get_user_model()
fields = ('username','email','password1','password2')
#Changing the labels for the fields
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.fields['username'].label = 'Display Name'
self.fields['email'].label = 'Email Address'
In views.py
# Create your views here.
#accounts/signup/
class SignUp(CreateView):
form_class = forms.UserCreateForm
success_url = reverse_lazy('login')
template_name = 'accounts/signup.html'
Install
pip install django-bootstrap4
In settings.py
INSTALLED_APPS = [ ... 'bootstrap4', ... ]
Using them in templates : accounts/signup.html
{% extends "base.html" %}
<!-- using django-bootstrap -->
{% load bootstrap4 %}
{% block content %}
<div class="jumbotron">
<h1>Sign up</h1>
</div>
<div class="container">
<form method="post">
{% csrf_token %}
<!-- loading bootstrap styles -->
{% bootstrap_form form %}
<input type="submit" class="btn btn-primary" value="Sign Up">
</form>
</div>
{% endblock %}
In urls.py
from django.contrib.auth import views as auth_views
path('login/',auth_views.LoginView.as_view(template_name='accounts/login.html'),name='login'),
path('logout/',auth_views.LogoutView.as_view(),name='logout'),
Set up redirect urls in settings.py
LOGIN_REDIRECT_URL = '/loginsuccess' LOGOUT_REDIRECT_URL = '/thanks'
Very useful documentation https://docs.djangoproject.com/en/2.1/ref/models/
Sub heading in this documentation
Model field reference (list of model Fields and their options)
Field attribute reference
Model index reference
Model _meta API
Related objects reference
Model class reference
Model Meta options (Model metadata is “anything that’s not a field”)
Model instance reference
QuerySet API reference
Lookup API reference
Query Expressions
Conditional Expressions
Database Functions
Model Meta options
Model metadata is “anything that’s not a field”, such as ordering options (ordering), database table name (db_table),
usage example
class GroupMember(models.Model):
group = models.ForeignKey(Group,on_delete=models.CASCADE,related_name='memberships')
user = models.ForeignKey(User,on_delete=models.CASCADE,related_name='user_group')
def __str__(self):
return self.user.username
#For list of model Meta options:
# ref: https://docs.djangoproject.com/en/dev/ref/models/options/
class Meta:
#Sets of field names that, taken together, must be unique:
unique_together = (group,user)
SlugField
A slug is a for something, containing only letters, numbers, underscores or hyphens (ie chars accepted in url).
#allow_unicode : If True, the field accepts Unicode letters in addition to ASCII letters. Defaults to False.
#ref: https://docs.djangoproject.com/en/2.1/ref/models/fields/
slug = models.SlugField(allow_unicode=True.unique=True)
This is useful while sending strings as parameters to url
usage example
#Helps in passing strings as parameters to url
from django.utils.text import slugify
#helps in using markdown inside of the post
#pip install misaka
import misaka
# Create your models here.
class Group(models.Model):
name = models.CharField(max_length=255,unique=True)
# A slug is a for something, containing only letters, numbers, underscores or hyphens (ie chars user in url).
#allow_unicode : If True, the field accepts Unicode letters in addition to ASCII letters. Defaults to False.
#ref: https://docs.djangoproject.com/en/2.1/ref/models/fields/
slug = models.SlugField(allow_unicode=True.unique=True)
description = models.TextField(blank=True,default='')
#Used in case we want html version of our description
#editable (option available for all fields):
#If False, the field will not be displayed in the admin or any other ModelForm. They are also skipped during model validation. Default is True.
description_html = models.TextField(editable=False,default='',blank=True)
# Django will automatically generate a table to manage many-to-many relationships.
# However, if you want to manually specify the intermediary table,
# you can use the through option to specify the Django model that represents the intermediate table that you want to use.
members = models.ManyToManyField(User,through='GroupMember')
def __str__(self):
return self.name
#Funtion in models.Model that saves model to db
def save(self,*args,**kwargs):
#we set slug as the name(unique) of the group
self.slug = slugify(self.name)
#processes markdown
self.description_html = misaka.html(self.description)
super().save(*args,**kwargs)
def get_absolute_url(self):
#app_name = group
#path("posts/in/<slug>",views.SingleGroup.as_view(),name="single")
return reverse('groups:single',kwargs={'slug':self.slug})
Getting model of current User session
When User is implemented in another application of same project. we can get that object as follows,
from django.contrib.auth import get_user_model
#get model of the current user session
User = get_user_model()
#This User is used as Foreign key in GroupMembers class. User is implemented in another application of same project
By default, Django adds a Manager with the name objects to every Django model class.
A Manager is the interface through which database query operations are provided to Django models. At least one Manager exists for every model in a Django application.
The way Manager classes work is documented in Making queries
Getting all objects
all_obj_list = Post.objects.all()
Getting specif object
self.post_user = User.objects.get(username__iexact=self.request.user.username)
Filtering
#members is a field in Group model
context["groups_of_user"] = Group.objects.filter(members__in=[self.request.user])
Another way to get
membership = GroupMember.objects.filter(user=self.request.user,group__slug=self.kwargs.get('slug')).get()
The following code grabs all Post object from database
class PostList(generic.ListView):
model = models.Post
But sometimes we want just the objects that match certain criteria. For example, to get Post object having a logged in username
def get_queryset(self):
queryset = super().get_queryset()
#post.user.username
return queryset.filter(user__username__iexact=self.request.user.username)
NOTE: Do not use request.user without login check
To get Post object of any specific user
from django.http import Http404
#Under class UserPost
def get_queryset(self):
try:
self.post_user = User.objects.get(username__iexact=self.kwargs.get("username"))
except User.DoesNotExist:
#executed when there is exception
raise Http404
else:
#this statement will be executed when there is no exception
return self.post_user.posts.all()
self.kwargs is available for url
##posts/by/<username>
path('by/<username>',views.UserPost.as_view(),name='user_post')
Using reverse instead of reverse_lazy breaks compilation with circular import error
success url overrides get_absolute_url defined in Models
class CreateGroup(LoginRequiredMixin,generic.CreateView):
fields = ('name','description')
model = Group
template_name = "groups/group_form.html"
#Using reverse instead of reverse_lazy breaks compilation with circular import error
#success url overrides get_absolute_url defined in Models
success_url = reverse_lazy("index")
You dont specify a model in this class. You just redefine get and redirect methods
class JoinGroup(LoginRequiredMixin,generic.RedirectView):
#We have to get a specific Group object and create a new GroupMember
def get(self,request,*args,**kwargs):
group = get_object_or_404(Group,slug=self.kwargs.get('slug'))
try:
GroupMember.objects.create(user=self.request.user,group=group)
except IntegrityError:
messages.warning(self.request,'Warning! Already a member')
else:
messages.success(self.request,'You are now a member!')
return super().get(request,*args,**kwargs)
def get_redirect_url(self,*args,**kwargs):
return reverse("groups:single",kwargs={'slug':self.kwargs.get('slug')})
class LeaveGroup(LoginRequiredMixin,generic.RedirectView):
def get(self,request,*args,**kwargs):
try:
membership = GroupMember.objects.filter(user=self.request.user,group__slug=self.kwargs.get('slug')).get()
except GroupMember.DoesNotExist:
messages.warning(self.request,'Sorry You are not in this group')
else:
membership.delete()
messages.success(self.request,'You are not a member anymore!')
return super().get(request,*args,**kwargs)
def get_redirect_url(self,*args,**kwargs):
return reverse("groups:single",kwargs={'slug':self.kwargs.get('slug')})
Often times, when html becomes too long, we may want to break it up in separate files and inject them. This is done with include tag
{% include "posts/_post.html" %}
_posts is just a convention for developers to understand that _post.html is a part of another html file