Skip to main content

django-crud-demo

This article outlines the features and functionalities of the django-crud-demo project, assuming you have it installed and properly configured on your machine

Project structure

django-crud-demo/ │ ├───.github │ └───workflows ├───requirements ├───screenshots ├───src │ ├───apps │ │ └───users │ │ ├───management │ │ │ └───commands │ │ ├───migrations │ │ ├───templatetags │ │ └───... │ ├───core │ │ ├───settings │ │ │ ├───base │ │ │ ├───development │ │ │ └───production │ │ └───... │ ├───media │ ├───staticfiles │ └───templates │ └───auth │ └───layouts │ └───main │ └───users └───static

Auth and Validate

Age Restriction

The user must be at least 18 years old to sign up, which is verified by checking their date of birth. The age is calculated based on the date of birth provided in the form.

forms.py
    def clean(self):
cleaned_data = super(CustomUserCreationForm, self).clean()
dob = self.cleaned_data["date_of_birth"]
age = abs(date.today() - dob)
if (age.days / 365.0) < 18:
raise forms.ValidationError(
"You must be at least 18 to signup.",
code="too_young",
)
return cleaned_data

If the user is younger than 18, an error is raised with a message stating they can't sign up. If the age is acceptable, the cleaned data is returned.

Profile Verification

The UpdateProfileView class allows logged-in users to update their profiles. It requires authentication, displays the current profile data in forms, and processes updates when submitted

views.py
@method_decorator(login_required(login_url="/login/"), name="dispatch")
class UpdateProfileView(LoginRequiredMixin, TemplateView):
template_name = 'users/user_update_profile.html'
http_method_names = ["get", "post"]

def get(self, request, *args, **kwargs):
user = self.request.user

if "u_form" not in kwargs:
kwargs["u_form"] = forms.UpdateUserForm(instance=user)

if "p_form" not in kwargs:
kwargs["p_form"] = forms.UpdateProfileForm(instance=user.user_profile)

return super().get(request, *args, **kwargs)


def post(self, request, *args, **kwargs):
user = self.request.user
u_form = forms.UpdateUserForm(request.POST, instance=user)
p_form = forms.UpdateProfileForm(request.POST, request.FILES, instance=user.user_profile)

if u_form.is_valid() and p_form.is_valid():
u_form.save()
p_form.save()
messages.success(request, f"Awesome {user.first_name}! Your profile has been updated.")
return redirect("/")

return super().get(request, u_form=u_form, p_form=p_form)

If the update is successful, the user will get a verification badge.

Session Timeout

By default, users will be automatically logged out if idle for 5 minutes, unless the "Remember Me" option is selected upon login, extending the session to 30 days.

settings.py
SESSION_EXPIRE_AT_BROWSER_CLOSE = True

SESSION_COOKIE_AGE = 10 * 30 # 5 Minutes

Overall, CustomLoginView enhances the standard login functionality with additional features like session management and security measures.

views.py
class CustomLoginView(LoginView):
form_class = LoginForm
template_name = "auth/login.html"
success_url = '/'
redirect_field_name = REDIRECT_FIELD_NAME

@method_decorator(csrf_protect)
@method_decorator(never_cache)
def dispatch(self, request, *args, **kwargs):
return super(CustomLoginView, self).dispatch(request, *args, **kwargs)

def get_context_data(self, **kwargs):
redirect_to = self.request.GET.get(self.redirect_field_name)
if redirect_to is None:
redirect_to = '/'
return super(CustomLoginView, self).get_context_data(**kwargs)

def form_valid(self, form):
redirect = super().form_valid(form)
remember_me = form.cleaned_data.get("remember_me")

if remember_me is True:
SESSION_DURATION = 30 * 24 * 60 * 60 # 1 Month
expiry = getattr(settings, "KEEP_LOGGED_DURATION", SESSION_DURATION)
self.request.session.set_expiry(expiry)

return redirect

def get_success_url(self):
redirect_to = self.request.POST.get(self.redirect_field_name)
if not url_has_allowed_host_and_scheme(
url=redirect_to, allowed_hosts=[
self.request.get_host()]):
redirect_to = self.success_url

return redirect_to

Custom commands

Check migration

Check what changes would be made to the database for the apps_users app without applying them.

py manage.py makemigrations apps_users --dry-run --verbosity 3

Create and delete dummy users.

To create (5) dummy users, run:

py manage.py create_users 5

Dummy users has prefix @dummy_ so that we can delete them all at once. To delete dummy users, run

py manage.py delete_dummy

Create a new SECRET_KEY.

py manage.py new_secret