I looking for a resolving of my issue.
I have custom User model:
class User(AbstractUser):
username = models.CharField(max_length=150, unique=True, blank=False, null=False)
first_name = models.CharField(max_length=150, blank=True)
last_name = models.CharField(max_length=150, blank=True)
password = models.CharField(max_length=150, blank=False)
email = models.EmailField(unique=True, blank=False)
date_create = models.DateTimeField(auto_now_add=True)
address = models.CharField(blank=True, max_length=128)
phone = PhoneNumberField(unique=True)
photo = models.ImageField(upload_to='images/', blank=True)
is_active = models.BooleanField(default=True)
In my app I have e-mail-confirmation. When I create user I hit the "is_active=False". When user activate account then flag "is_active=True". Everything works good.
But when INactive user tries to log in I wanna get message from Django in Login form.
Django has it(source code):
def confirm_login_allowed(self, user):
if not user.is_active:
raise ValidationError(
self.error_messages['inactive'],
code='inactive',
)
But doesn't work for me.
Update: When inactive user tried to log in I get same message as user with incorrect username or password.
I tried to override AuthenticationForm:
User = get_user_model()
class CustomAuthenticationForm(AuthenticationForm):
class Meta: # tried with Meta and without
model = User
def confirm_login_allowed(self, user):
if not user.is_active:
raise forms.ValidationError('There was a problem with your login.')
View:
class CustomLoginView(SuccessMessageMixin, LoginView):
form_class = CustomAuthenticationForm
success_url = reverse_lazy('home')
success_message = "You was logged in successfully"
url:
path('login/', CustomLoginView.as_view(), name='login'),
Update, templates base and login:
<!doctype html>
{% load static %}
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css"
integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx"
crossorigin="anonymous"></script>
{% block mystyle %}
{% endblock %}
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark justify-content-center">
<a class="navbar-brand" href="#">Site</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-link" href="{% url 'home' %}">Home</a>
{% if user.is_authenticated %}
<a class="nav-link" href="{% url 'cabinet' %}">Cabinet</a>
<a class="nav-link" href="{% url 'logout' %}">LogOut</a>
{% else%}
<a class="nav-link" href="{% url 'signup' %}">SignUp</a>
<a class="nav-link text-right" href="{% url 'login' %}">LogIn</a>
{% endif %}
</div>
</div>
</nav>
{% if messages %}
{% for message in messages %}
<div class="alert alert-success">{{ message }}</div>
{% endfor %}
{% endif %}
{% block content %}
{% endblock %}
</body>
</html>
{% extends "base.html" %}
{% load crispy_forms_tags %}
<!DOCTYPE html>
{% block title %}Log In{% endblock %}
{% block content %}
<h1 class="row justify-content-center p-4">Log In</h1>
<div class="row justify-content-center">
<div class="col-4">
<form autocomplete="off" method="post">
{% csrf_token %}
{{ form|crispy }}
<div class="container p-2">
Forgot your password?
</div>
<div class="container p-2">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
{% endblock %}
Could someone help me? Thanks.
I understood it from point of security. I resolved it just override ModelBackend
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
UserModel = get_user_model()
class CustomModelBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
if username is None or password is None:
return
try:
user = UserModel._default_manager.get_by_natural_key(username)
except UserModel.DoesNotExist:
# Run the default password hasher once to reduce the timing
# difference between an existing and a nonexistent user (#20760).
UserModel().set_password(password)
else:
if user.check_password(password): # here (remove 'and self.user_can_authenticate(user):')
return user
Settings
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'accounts.backends.CustomModelBackend',
]
Related
Registration for this Django 4.0.3 project works well except for failure to present error messages and previously completed form field contents. In other words, registration is working with both user_form and profile_form completed and the database is updated as expected.
What is not working
If the user mismatches passwords no error is returned and page returns a blank form (I was under the impression by passing the forms back as a context dictionary that field data would be preserved - not sure what I'm missing in this regard)
The error check in forms.py to ensure a unique email is not working either (I do use forms error-checking extensively throughout the project). However, given the failure to present the password mismatch error I am inclined to believe both these symptoms share the same cause.
When registration is not valid (password mismatch or non-original email address) blank forms are returned.
The fact that forms validation is not working properly suggests that there is something inherently wrong in the register view. However, after looking at this for a couple of days I'm hoping that the bright minds of Stack Overflow will be able to point me in the right direction...
I am including all the relevant code snippets in anticipation of their being requested to support diagnosis. Given that the only element of user registration that is not working is the failure to return error messages and preserve form field contents what I've included may well be over-kill. And, I won't be surprised if I've missed something. If so, please comment with any such requests and I'll update the question.
Code Snippets
settings.py
This snippet is included to show the default password validators.
# Password validation
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
models.py
I have added a one-to-one relationship between the built-in User model and my own Profile model. I am aware that the User model can be extended, but opted for a Profile model (for which the Django Documentation acknowledges as acceptable). I have omitted the COUNTRY_CHOICES constant as, by my estimation, these 200+ lines of code will not support diagnosis.
from django.db import models
from django.contrib.auth.models import User
from phone_field import PhoneField
# ...
# ####################### CHOICE CONSTANTS #######################
PRONOUN_CHOICES = [
('---', '---'),
('She/her', 'She/her'),
('He/him', 'He/him'),
('They/them', 'They/them'),
('Rather not say', 'Rather not say'),
]
NOTIFICATION_PREFERENCE = [
('None', 'None'),
('Email', 'EMail'),
('Text/SMS', 'Text/SMS'),
]
# Omitted COUNTRY_CHOICES to save space
# ...
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
pronoun = models.CharField(max_length=20, choices=PRONOUN_CHOICES, default='---')
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
full_name = models.CharField(max_length=200, blank=True, null=True)
address_1 = models.CharField(max_length=100)
address_2 = models.CharField(max_length=100, blank=True, null=True)
city = models.CharField(max_length=50)
state_province_county = models.CharField(max_length=100, verbose_name='State/Province/County')
postal_zip_code = models.CharField(max_length=10, verbose_name='postal/zip code')
country = models.CharField(max_length=100, choices=COUNTRY_CHOICES, default='---')
phone = PhoneField(blank=True, help_text='Contact phone number')
notification_preference = models.CharField(
max_length=10,
choices=NOTIFICATION_PREFERENCE,
default='Email',
help_text='''If you would like to receive booking confirmation notifications from us please select your preference.'''
)
def __str__(self):
return f'{self.first_name} {self.last_name}'
forms.py
I'm using forms.py to validate for a unique email. I added this because the original approach (inspired by Corey Schafer) didn't appear to prevent duplicate email addresses.
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
# ############ Profile form validation ############
def profile_form_validation(form, form_type):
cleaned_data = super(form_type, form).clean()
if not cleaned_data.get('phone') and cleaned_data.get('notification_preference') == 'Text/SMS':
form.add_error(
'phone',
'A phone number must be entered in order to be able to receive text messages on your phone.'
)
return
# ############ Forms ############
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = [
'username',
'email',
'password1',
'password2',
]
def clean(self):
cleaned_data = super(UserRegisterForm, self).clean()
if User.objects.filter(email=cleaned_data.get('email')).exists():
self.add_error(
'email',
'That email address is already associated with an account. Please use another email address.',
)
return self.cleaned_data
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = [
'pronoun',
'first_name',
'last_name',
'address_1',
'address_2',
'city',
'state_province_county',
'postal_zip_code',
'country',
'phone',
'notification_preference',
]
def clean(self):
profile_form_validation(self, ProfileUpdateForm)
return self.cleaned_data
views.py
My instinct is that the cause of the problem is with the view to process registration.
Please note that:
I am using login() to automatically log the user in once registration is complete.
The auto-login works if the both passwords match and the email address entered is unique.
The redirect to 'events' works.
The only functionality not working is the failure to return error messages or preserve previously completed fields (excepting password1 and password2 obviously).
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth import login
from .models import Profile
from .forms import (
UserRegisterForm,
ProfileUpdateForm,
)
def register(request):
if request.method == 'POST':
user_form = UserRegisterForm(request.POST)
profile_form = ProfileUpdateForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
# Process user form
user = user_form.save(commit=False)
user.save()
# Process profile form
profile_form.instance.user = user
profile_form.instance.full_name = f'{profile_form.instance.first_name} {profile_form.instance.last_name}'
profile_form.save()
# Log in user after registration
login(request, user)
messages.success(request, f'Your account (username:{username}) has been created. '
f'You are now logged in!')
return redirect('events')
else:
user_form = UserRegisterForm()
profile_form = ProfileUpdateForm()
return render(request, 'users/register.html', {'user_form': user_form, 'profile_form': profile_form})
else:
user_form = UserRegisterForm()
profile_form = ProfileUpdateForm()
return render(request, 'users/register.html', {'user_form': user_form, 'profile_form': profile_form})
urls.py
Including urls.py is probably over-kill.
from django.contrib.auth import views as auth_views
from django.urls import path
# ...
urlpatterns = [
# ...
path('register/', user_views.register, name='register'),
# ...
]
register.html
Template inclusion is also likely over-kill. However, this demonstrates the explicit use of form.errors. Again, there is no problem with template rendering (so I'm omitting base.html and the css file).
{% extends 'base.html' %}
{% load crispy_forms_filters %}
{% load crispy_forms_tags %}
{% block title %}Register{% endblock %}
{% block content %}
<section class="content-section">
<h3 class="mb-2"><strong>Registration</strong></h3>
</section>
{% if form.errors %}
<section class="content-section-danger alert-section">
<div>
<p class="alert-danger">Please review the following:</p>
<ul>
{% for key, value in form.errors.items %}
{% for error in value %}
{% if error != '' %}
<li class="alert-danger">{{ error }}</li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
</div>
</section>
{% endif %}
<section class="content-section">
<div class="row">
<div class="col-lg-12 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-BlueGray">
<strong>Your Account Details</strong>
</li>
</ul>
</div>
</div>
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<div class="row">
<div class="col-lg-3 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-white">
{{ user_form.username|as_crispy_field }}
</li>
</ul>
</div>
<div class="col-lg-3 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-white">
{{ user_form.email|as_crispy_field }}
</li>
</ul>
</div>
<div class="col-lg-3 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-white">
{{ user_form.password1|as_crispy_field }}
</li>
</ul>
</div>
<div class="col-lg-3 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-white">
{{ user_form.password2|as_crispy_field }}
</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-lg-12 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-BlueGray">
<strong>Your Profile</strong>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-lg-3 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-white">
{{ profile_form.pronoun|as_crispy_field }}
</li>
</ul>
</div>
<div class="col-lg-3 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-white">
{{ profile_form.first_name|as_crispy_field }}
</li>
</ul>
</div>
<div class="col-lg-3 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-white">
{{ profile_form.last_name|as_crispy_field }}
</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-lg-9 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-white">
{{ profile_form.address_1|as_crispy_field }}
</li>
</ul>
</div>
<div class="col-lg-3 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-white">
{{ profile_form.address_2|as_crispy_field }}
</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-lg-3 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-white">
{{ profile_form.city|as_crispy_field }}
</li>
</ul>
</div>
<div class="col-lg-3 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-white">
{{ profile_form.state_province_county|as_crispy_field }}
</li>
</ul>
</div>
<div class="col-lg-3 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-white">
{{ profile_form.postal_zip_code|as_crispy_field }}
</li>
</ul>
</div>
<div class="col-lg-3 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-white">
{{ profile_form.country|as_crispy_field }}
</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-lg-3 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-white">
{{ profile_form.phone|as_crispy_field }}
</li>
</ul>
</div>
{% if SMS_MESSAGING_ACTIVE == 'Yes' %}
<div class="col-lg-9 pt-2 pb-2">
<ul class="list-group">
<li class="list-group-item list-group-item-white">
{{ profile_form.notification_preference|as_crispy_field }}
</li>
</ul>
</div>
{% else %}
{{ profile_form.notification_preference.as_hidden }}
{% endif %}
</div>
<div class="row">
<div class="col-lg-3">
</div>
</div>
</fieldset>
<div class="row pt-4 pb-2">
<div class="col-lg-3">
<button class="btn btn-success col-12" type="submit">Register</button>
</div>
</div>
</form>
<div class="pt-2">
<small class="text-muted">
Already have an account? Log In
</small>
</div>
</section>
{% endblock content %}
I am not sure how I missed this, but apparently I was re-creating the forms with the else branch. face palm
I'm answering the question in the chance that someone else saves time.
Corrected views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth import login
from .models import Profile
from .forms import (
UserRegisterForm,
ProfileUpdateForm,
)
def register(request):
if request.method == 'POST':
user_form = UserRegisterForm(request.POST)
profile_form = ProfileUpdateForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
# Process user form
user = user_form.save(commit=False)
user.save()
# Process profile form
profile_form.instance.user = user
profile_form.instance.full_name = f'{profile_form.instance.first_name} {profile_form.instance.last_name}'
profile_form.save()
# Log in user after registration
login(request, user)
messages.success(request, f'Your account (username:{username}) has been created. '
f'You are now logged in!')
return redirect('events')
return render(request, 'users/register.html', {'user_form': user_form, 'profile_form': profile_form})
else:
user_form = UserRegisterForm()
profile_form = ProfileUpdateForm()
return render(request, 'users/register.html', {'user_form': user_form, 'profile_form': profile_form})
The moral of this story, if you're validating forms there is no need to return those forms when the forms do not return as valid!
I need some help when I create a user and user profile accordingly and when I try to access to any user by another user the request turns me on the request I work on not the real user, although, I'm using the slug to specify what the user I click on it maybe I can not explain what happens to me exactly for more explanation, please click on that video to show what I mean: https://www.youtube.com/watch?v=MzSo0ay2_Xk&feature=youtu.be
accounts app
models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.template.defaultfilters import slugify
CHOICE = [('male', 'male'), ('female', 'female')]
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
slug = models.SlugField(max_length=100, unique=True, blank=True)
overview = models.TextField(editable=True, blank=True, default='You have no an Overview yet')
city = models.CharField(max_length=20, blank=False)
phone = models.IntegerField(default=0, blank=True)
sex = models.CharField(max_length=10, default='male', choices=CHOICE)
skill = models.CharField(max_length=100, default='You have no skills yet')
logo = models.ImageField(upload_to='images/', default='images/default-logo.jpg', blank=True)
def __str__(self):
return self.user.username
def save(self, *args, **kwargs):
self.slug = slugify(self.user)
super().save(*args, **kwargs)
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(receiver=create_profile, sender=User)
view.py
class ViewProfile(UpdateView):
queryset = UserProfile.objects.all()
template_name = 'accounts/profile.html'
form_class = UpdateInfoForm
slug_field = 'slug'
slug_url_kwarg = 'user_slug'
def get_success_url(self):
return reverse_lazy('accounts:view_profile', kwargs={'user_slug': self.request.user.userprofile.slug})
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
user_prof = UserProfile.objects.get(user=self.request.user)
context['user_prof'] = user_prof
context['get_favourite'] = User.objects.get(username=self.request.user.username).favorite.all()
return context
def form_valid(self, form):
form.instance.user_slug = self.request.user.userprofile.slug
self.object = form.save()
return super().form_valid(form)
profile.html
{% extends 'base.html' %}
{% block title %} {{ user.first_name }} {{ user.last_name }} Profile {% endblock %}
{% block body %}
<!-- User Profile Section -->
{% if user.is_authenticated %}
<div class="profile">
<div class="container-fluid">
<div class="col-md-1">
<div class="thumbnail">
<div class="row">
<div class="col-xs-12">
<!-- Profile View Section -->
<div class="logo-image text-center">
{% if user.userprofile.logo %}
<div class="my-image">
{% if request.user.username == user.userprofile.slug %}
<a href="{% url 'accounts:user_image' user.userprofile.slug %}">
<img class="img-responsive" src="{{ user.userprofile.logo.url }}">
</a>
<span>
<a href="{% url 'accounts:add_avatar' user.userprofile.slug %}" class="fa fa-camera fa-1x text-center">
<p>Upload Image</p>
</a>
</span>
{% endif %}
</div>
{% else %}
{% load static %}
<div class="my-image">
<img class="img-responsive img-thumbnail" src="{% static 'index/images/default-logo.jpg' %}">
<span>
<a href="{% url 'accounts:add_avatar' user.userprofile.slug %}" class="fa fa-camera fa-1x text-center">
<p>Upload Image</p>
</a>
</span>
</div>
{% endif %}
<h4>{{ user.first_name }} {{ user.last_name }}</h4>
</div>
</div>
<div class="col-xs-12">
<div class="caption">
<ul class="nav nav-pills nav-stacked">
<li role="presentation" class="active">Overview</li>
<li role="presentation" class="">Personal Information</li>
<li role="presentation" class="">Skills</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Information Sections -->
<div class="col-md-8 col-md-offset-3 information">
<div class="overview show" id="overview">
<h2 class="line">Overview</h2>
<p class="lead">{{ user.userprofile.overview }}</p>
<a data-placement="bottom" title="update overview" class="fa fa-edit" data-toggle="modal" data-tooltip="tooltip" data-target=".overview_info"></a>
</div>
<div class="personal-info" id="personal-information">
<h2 class="line">Personal Information</h2>
<p class="lead">City: {{ user.userprofile.city }}</p>
<p class="lead">Phone Number: 0{{ user.userprofile.phone }}</p>
<p class="lead">Sex: {{ user.userprofile.sex }}</p>
<a data-placement="bottom" title="update personal information" class="fa fa-edit" data-toggle="modal" data-tooltip="tooltip" data-target=".personal_info"></a>
</div>
<div class="skill" id="my-skills">
<h2 class="line">Skills:</h2>
<p class="lead">{{ user.userprofile.skill }}</p>
<a data-placement="bottom" title="update skills" class="fa fa-edit" data-toggle="modal" data-tooltip="tooltip" data-target=".skills"></a>
</div>
</div>
<!-- get all questions -->
{% if user_prof.userasking_set.all %}
<div class="col-md-8 col-md-offset-3 user_questions">
<h2 class="line">All Questions You Asked</h2>
{% for questions in user_prof.userasking_set.all %}
<p>{{ questions.title }}</p>
{% endfor %}
</div>
{% endif %}
<!-- get favourites -->
{% if get_favourite %}
<div class="col-md-8 col-md-offset-3 user_questions">
<h2 class="line">Favourites</h2>
{% for fav in get_favourite %}
<p>{{ fav.title }}</p>
{% endfor %}
</div>
{% endif %}
</div>
{% include 'accounts/information_form.html' %}
</div>
{% include 'base_footer.html' %}
{% endif %}
{% endblock %}
self.request.user refers to the currently logged in user. That is why you are getting the same result for all users.
To get what you want, you need to make the following change in your views:
user_prof = UserProfile.objects.get(pk=self.kwargs['pk'])
But also, I'm not sure why you are using an UpdateView when you simply want to display objects? You should use TemplateView instead.
I am brand new to Django.
I made a register form.
One time out of two, when i try to register a new user i have an exception "auth_user.username"
it seems there is no rule, it can works many times in a row and with new user registration i have the error!
Here is my form.py
from django.contrib.auth.forms import UserCreationForm,AuthenticationForm
from django.contrib.auth.models import User
from bootstrap_modal_forms.mixins import PopRequestMixin, CreateUpdateAjaxMixin
from django import forms
class CustomUserCreationForm(PopRequestMixin, CreateUpdateAjaxMixin,
UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
def clean_email(self):
if User.objects.filter(email=self.cleaned_data['email']).exists():
raise forms.ValidationError("the given email is already registered")
return self.cleaned_data['email']
'''
views.py
enter code here
from django.urls import reverse_lazy
from bootstrap_modal_forms.generic import BSModalCreateView,BSModalLoginView
from .forms import CustomUserCreationForm,CustomAuthenticationForm
class SignUpView(BSModalCreateView):
form_class = CustomUserCreationForm
template_name = 'signup.html'
success_message = 'Success: Sign up succeeded. You can now Log in.'
success_url = reverse_lazy('index')
signup.html
enter code here
{% load widget_tweaks %}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-
q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
body data-spy="scroll" data-target=".site-navbar-target" data-offset="300">
<form method="post" action="">
{% csrf_token %}
<div class="modal-header">
<h3 class="modal-title">Register</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{% render_field field class="form-control" placeholder=field.label %}
<div class="{% if field.errors %} invalid{% endif %}">
{% for error in field.errors %}
<p class="help-block" style="color:red">{{ error }}</p>
{% endfor %}
</div>
</div>
{% endfor %}
Register
THANK YOU
I remember two ways we can accomplish that:
Override the User model's save method and only try to save if the object does not exist:
def save(self, *args, **kwargs):
if not User.objects.filter(name=self.name).first():
super(User, self).__init__(*args, **kwargs)
Create your custom model and inherit from User, and drop the unique constraint:
class CustomUser(User):
username = models.CharField(_("User name"), max_length=30, blank=False)
This way you have more control of your validations.
I am trying to build an educational website and am trying to put all categories using for loops in a dropdown in the navbar. I have put it in base.html and all other templates extend base.html. But the items are only shown in the root page whose template is home.html.
I have tried using passing multiple contexts to all posts.
base.html:
{% load static %}
<!doctype html>
<html>
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="{% static 'blog/main.css' %}">
<title>{% block title %}ION{% endblock %}</title>
</head>
<body>
<header class="site-header">
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand mr-4" href="{% url 'blog-home' %}">ION</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle" aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarToggle">
<div class="navbar-nav mr-auto">
<a class="nav-item nav-link" href="{% url 'blog-home' %}">Home</a>
<a class="nav-item nav-link" href="{% url 'post-all' %}">Posts</a>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Categories</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
{% for cate in cat %}
<a class="dropdown-item" href="{% url 'category' cate.pk %}">{{ cate.name }}</a>
{% endfor %}
</div>
</li>
<a class="nav-item nav-link" href="{% url 'blog-about' %}">About</a>
</div>
<!-- Navbar Right Side -->
<div class="navbar-nav">
{% if user.is_authenticated %}
<a class="nav-item nav-link" href="{% url 'post-create' %}">New Post</a>
<a class="nav-item nav-link" href="{% url 'profile' %}">Profile</a>
<a class="nav-item nav-link" href="{% url 'logout' %}">Logout</a>
{% else %}
<a class="nav-item nav-link" href="{% url 'login' %}">Login</a>
<a class="nav-item nav-link" href="{% url 'register' %}">Register</a>
{% endif %}
</div>
</div>
</div>
</nav>
</header>
<main role="main" class="container">
<div class="row">
<div class="col-md-12">
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{message.tags}}">
{{message}}
</div>
{% endfor %}
{% endif %}
{% block content %}{% endblock %}
</div>
</div>
</div>
</main>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
<!--From snippets navigation, main, and the starter template: https://getbootstrap.com/docs/4.3/getting-started/introduction/
home.html (Only place where it works):
{% extends "blog/base.html" %}
{% block title %}
ION Home
{% endblock %}
{% block content %}
<div class="text-center">
<h1>Home</h1>
</div>
<div class="card">
<img class="card-img-top" src="https://www.litmos.com/wp-content/uploads/2016/06/blog-eLearning-templates.png" alt="Card image cap">
<div class="card-body">
<h3 class="card-title text-center">Learning Reimagined</h3>
<p class="card-text">
ION is an open network that intends to reimagine learning. Anyone from anywhere can upload courses and help those unable to go to conventional schools or as an aid for education.
We promote education to the fullest. We believe in equal right for everyone. Students can take the help of ION to study or even make ION their primary study source.
</p>
</div>
</div>
{% endblock %}
views.py:
def home(request):
context = {
'posts': Post.objects.all(),
'cat': Category.objects.all()
}
return render(request, 'blog/home.html', context)
def about(request):
return render(request, 'blog/about.html', {'title':'About'})
class PostListView(ListView):
model = Post
template_name = 'blog/posts.html' #<app>/<model>_<viewtype>.html
context_object_name = 'posts' #It needs the specifying to loop over just like it did in the context of home
ordering = ['-date_posted']
paginate_by = 15
class UserPostListView(ListView):
model = Post
template_name = 'blog/user_posts.html' #This is when you click a profile in a post, it takes you to his posts only
context_object_name = 'posts'
paginate_by = 15
def get_queryset(self):#This does so that it takes you to the user posts only if he currently still exists
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Post.objects.filter(author=user).order_by('-date_posted')
class PostDetailView(DetailView):
model = Post
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'content', 'display', 'category']
def form_valid(self, form):#This sets the user to be the author of the blog you're trying to create
form.instance.author = self.request.user
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
fields = ['title', 'content', 'display', 'category']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):#This is where only the author can update the post
post = self.get_object()
if self.request.user == post.author:
return True
return False
class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Post
success_url = '/'
def test_func(self):#This is where only the author can update the post
post = self.get_object()
if self.request.user == post.author:
return True
return False
class CatPostListView(ListView):
model = Post
template_name = 'blog/science.html' #This is when you click a profile in a post, it takes you to his posts only
context_object_name = 'posts'
paginate_by = 15
def get_queryset(self):
return Post.objects.filter(category=2).order_by('-date_posted')
models.py:
class Category(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField()
parent = models.ForeignKey('self', blank=True, null=True, related_name='children', on_delete=models.SET_NULL)
class Meta:
# enforcing that there can not be two categories under a parent with same slug
# __str__ method elaborated later in post. use __unicode__ in place of
# __str__ if you are using python 2
unique_together = ('slug', 'parent',)
verbose_name_plural = "categories"
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
category = models.ForeignKey('Category', null=True, blank=True, on_delete=models.SET_NULL)
display = models.TextField(max_length=250)
date_posted = models.DateTimeField(default=timezone.now)#DON'T USE () HERE Just auto_now_ will show the date of the current day
author = models.ForeignKey(User, on_delete=models.CASCADE)#No () #This deletes the posts when the user is deleted
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
I expect the categories to show up on all pages.
It won't because there is no category data in other pages(apart from home page). So either you can send the Category variable through context variable cat in each view, or you can create a custom context processor, like this:
def cat_on_all_pages(request):
return {'cat': Category.objects.all()}
And add it in the settings:
'OPTIONS': {
'context_processors': [
'path.to.cat_on_all_pages',
# other context processors
],
}
If you add custom context processor, then you can remove cat from context in home view.
When I submit my form, it doesn't post the form data and just reloads the form.
It was working beforehand but I'm not sure what I've changed that doesn't make it work anymore. Posting the data through the admin still works fine.
The only 'error' message I can see is in the terminal:
which can be seen here
It sends a get request instead of a post request as well. I've also tested it with removing the JS and bootstrap CDNs but the issue is still the same.
My code is below:
Here is my views.py
def create(request):
if request.method == 'POST':
form = EventCreateForm(request.POST, request.FILES)
if form.is_valid():.
instance = form.save(commit=False)
instance.author = request.user
instance.save()
instance.save_m2m()
return redirect('event:home')
else:
form = EventCreateForm()
return render(request, 'event/create.html', {'form': form})
create.html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{{ form.media }}
<div class="container-fluid">
<div class="col-md-4">
<div class="page-header">
<p> Create an event!</p>
</div>
<form method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{{ form | crispy}}
<button type="submit">Submit</button>
<br>
<br>
</form>
</div>
</div>
{% endblock %}
Base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://code.jquery.com/jquery-3.2.1.min.js" crossorigin="anonymous" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" crossorigin="anonymous" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" crossorigin="anonymous" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'event/css/custom.css' %}">
<title>Django Project</title>
</br>
<div class="container-fluid" style='font-family:arial'>
<center>
<h2> Welcome to the django website!</h2>
</center>
</div>
{{ form.media }}
</head>
<!-- body of the text -->
<body>
{% if messages %}
{% for messages in messages %}
{{ message }}
{% endfor %}
{% endif %}
{% if user.is_authenticated %}
<nav class="navbar navbar-expand-md navbar-dark bg-dark sticky-top">
<div class="navbar-nav">
<a class="nav item nav-link active" href="{% url 'event:home' %}">Home</a>
<a class="nav item nav-link" href="{% url 'profiles:profile' %}">Profile</a>
<a class="nav item nav-link" href="{% url 'profiles:edit' %}">Edit profile</a>
<a class="nav item nav-link" href="{% url 'event:create' %}">Create</a>
<a class="nav item nav-link" href="{% url 'profiles:logout' %}">Logout</a>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">
<button class="btn btn-success" type="submit">Search</button>
</div>
{% else %}
Login
Register
{% endif %}
</nav>
{% block content %}
{% endblock %}
</body>
</html>
Models.py
class Event(models.Model):
title = models.CharField(max_length=100)
link = models.TextField()
author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
image = models.ImageField(default='default.jpg', upload_to='event_images')
image_thumbnail = ImageSpecField(source='image',
processors=[ResizeToFill(100, 100)],
format='JPEG',
options={'quality': 60})
start = models.DateField(blank=True, null=True)
start_time = models.TimeField(blank=True, null=True)
end = models.DateField(blank=True, null=True)
end_time = models.TimeField(blank=True, null= True)
description = HTMLField('description')
tags = models.ManyToManyField(Tags)
subject = models.ManyToManyField(Subject)
attendees = models.ManyToManyField(User, related_name = 'attendees', blank=True)
def __str__(self):
return f'{self.title}'
def get_absolute_url(self):
return reverse('event:detail', kwargs={'pk': self.pk})
Thanks everyone in advance,
All help will be greatly appreciated!
You may have deleted your action. Try adding the url back?
<form method="post" action="{% url "event:create" %}" enctype="multipart/form-data">
I had a problem like this too. I solved it by getting rid of a div tag containing a bootstrap class (<div class="form-group>" to be more precise) located around my form.
same problem existed for me also , the silly mistake you have done is the button thing in your create.html file , replace that with input tap with type submit and class btn , button doesn't submit request
Try this :
<input type="submit" class="btn btn-primary" value="Submit">
i know its bit late but this may seem helpful