View.py
class Register(TemplateView):
template_name = 'registration.html'
def get(self, request, *args, **kwargs):
form = CreateForm()
return render(request, self.template_name, {'form': form})
#staticmethod
def post(request):
try:
data = request.POST.get
user = User(
first_name=data('first_name'),
last_name=data('last_name'),
username=data('username').strip(),
email=data('email'),
)
user.set_password(data('password').strip())
user.save()
request.session["user_id"] = user.id
return HttpResponse(' Save successfully ')
except Exception as c:
return HttpResponse("Failed : {}".format(c), 500)
Form.py
role_choice= (("Customer", "Customer"), ("Employee", "Employee"))
class CreateForm(forms.Form):
first_name = forms.CharField(label="Enter Your First Name", max_length=30, required=True)
last_name = forms.CharField(label="Enter Your Last Name", max_length=30, required=True)
username = forms.CharField(required=True, widget=forms.TextInput())
email = forms.CharField(required=True, widget=forms.TextInput())
password = forms.CharField(required=True, widget=forms.PasswordInput())
role = forms.ChoiceField(choices=role_choice, widget=forms.RadioSelect())
class Customer(forms.Form):
contact = forms.IntegerField(label="Enter your contact number", required=True, )
amount = forms.IntegerField(required=True, min_value=500)
type = forms.ChoiceField(choices=choice)
Model.py
class Customers(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
contact = models.BigIntegerField()
amount = models.BigIntegerField()
type = models.CharField(max_length=1)
Template
{% extends "home.html" %}
{% load crispy_forms_tags %}
{% block title %}Create Account{% endblock %}
{% block content %}
<div>
{% csrf_token %}
{{ form|crispy }}
<button type="submit">Submit</button><br>
</div>
{% endblock %}
After the registration when user select customer option after sumbit the form i go to customer page if user select employee option he/she go to employee page but i don't know how to do this
First of all, I strongly advice not to write all the views, etc. yourself. Django already has a lot of tooling inplace. It has a UserCreationForm [Django-doc] that can be slighly modified. For example:
# app/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
class RoleUserCreationForm(UserCreationForm):
ROLES = (
('Customer', 'Customer'),
('Employee', 'Employee')
)
role = forms.ChoiceField(choices=ROLES, widget=forms.RadioSelect())
class Meta(UserCreationForm.Meta):
fields = (*UserCreationForm.Meta.fields, 'first_name', 'last_name')
We can here thus add the extra fields for first_name and last_name as well.
Now we can make use of this in a CreateView [Django-doc], and override the form_valid(..) method [Django-doc]:
# app/views.py
from app.forms import RoleUserCreationForm
from django.contrib.auth import get_user_model
from django.shortcuts import redirect
from django.views.generic.edit import CreateView
class RegisterView(CreateView):
model = get_user_model()
form_class = RoleUserCreationForm
def form_valid(self, form):
request.session['user_id'] = self.object.id
if form.cleaned_data['role'] == 'Customer':
return redirect('name-of-customer-view')
else:
return redirect('name-of-employee-view')
Where you replace the 'name-of-customer-view' and 'name-of-employee-view' with the name of these views respectively.
Related
I am trying to display all the categories to appear as a list that I can click and select from, just an exact replica of what I have in my admin panel, but it still display's as a list that isn't clickable.
forms.py
class ProfileEditForm(forms.ModelForm):
"""
Form for updating Profile data
"""
class Meta:
model = Profile
fields = [
"first_name",
"last_name",
"about_me",
"profile_image",
"username",
"email",
"categories",
]
first_name = forms.CharField(label="First Name", max_length=63, required=False)
last_name = forms.CharField(label="Last Name", max_length=63, required=False)
about_me = forms.CharField(label="About Me", max_length=511, required=False)
email = forms.EmailField(label="Email", disabled=True)
username = forms.CharField(label="Username", disabled=True)
profile_image = forms.ImageField(required=False)
categories = forms.ModelMultipleChoiceField(
queryset=Category.objects.all(),
required=False,
widget=forms.CheckboxSelectMultiple(),
)
profile.models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile")
first_name = models.CharField(max_length=63, blank=False)
last_name = models.CharField(max_length=63, blank=False)
about_me = models.CharField(max_length=511, blank=True)
categories = models.ManyToManyField(
Category, related_name="user_categories", symmetrical=False
)
categories.models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=63)
created = models.DateTimeField(auto_now_add=True, blank=True, null=True)
last_modified = models.DateTimeField(auto_now=True, blank=True, null=True)
def __str__(self):
return self.name
def __unicode__(self):
return self.name
class Meta:
verbose_name_plural = "Categories"
settings.html
<div class='row'>
<div class="col s12 m6">
{{form.categories.errors}}
{{form.categories.label_tag}}
{{form.categories}}
</div>
</div>
What I hope to achieve
What I get
You need to create the form itself:
<form method='post'>
</form>
And print each field on a new line:
{{ form.as_p }}
is a security check.
{% csrf_token %}
In the view, I left get_context_data. In it, you can add values to the context, for example, like this:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['rubrics'] = Car.objects.all()
Replace bboard with the name of the folder where your templates are placed.
I have this: templates/bboard which are in the application folder.
In the view for the form, the CreateView class is used, in which: template_name - the name of the template for displaying the page, form_class - the form class is indicated, success_url - where to return in case of successful saving of the form (in this case, this is the same page with the form), get_context_data - the template context (you can print it out and see what's inside).
And if your model has fields: first_name, last_name, about_me, email, username, profile_image, then it is enough that you have specified the fields variable in the class Meta class. You don't need to re-create them in the form.
template_name = 'bboard/tam_form.html'#bboard replace with your prefix
Templates
<form method='post'>
{{form.categories.errors}}
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value='adding'>
</form>
views.py
from .forms import *
from django.views.generic.edit import CreateView
from django.urls import reverse_lazy
class Profile(CreateView):
template_name = 'bboard/settings.html'#bboard replace with your prefix
form_class = ProfileEditForm
success_url = reverse_lazy('test')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return context
urls.py
from django.urls import path
from .views import *
urlpatterns = [
path('test/', Profile.as_view(), name='test'),
]
Update 13.11.2022
This is how my form looks like when I go to the address:
http://localhost:8000/test/
But the form is not submitted. I don't have much experience with this. I can assume that forms.ModelForm expects that the model has such fields, because if you delete the lines with email, username, profile_image and also remove them from the fields and add 'user' to the field, then the data will be saved in the database (checked).
As I said earlier, if the fields are declared in fields, then you do not need to define them again (if you leave them, the form will also be saved). This is what the form class looks like:
class ProfileEditForm(forms.ModelForm):
class Meta:
model = Profile
fields = [
'user',
'first_name',
'last_name',
'about_me',
'categories',
]
categories = forms.ModelMultipleChoiceField(
queryset=Category.objects.all(),
required=False,
widget=forms.CheckboxSelectMultiple(),
)
I am creating a "UsercreationForm" in django.
When I saved the form, it didn't create any entry in database then I debug it and found an error message that Password fields does not match
I don't know what I did wrong. Please help me figure it out.
Here is my forms.py
from django import forms
from accounts.models import Customer, User
from django.contrib.auth.forms import UserCreationForm
from django.core.exceptions import ValidationError
from datetime import datetime
class UserSignup(UserCreationForm):
class Meta:
model = User
fields = ("username","first_name", "last_name", "email")
username = forms.CharField(label="Username", required=True)
first_name= forms.CharField(label="First Name", required=True)
last_name=forms.CharField(label="Last Name", required=False)
email =forms.EmailField(label="Email", required=False)
password1 = forms.CharField(label="Password", required=True)
password2 = forms.CharField(label="Confirm Password", required=True)
def username_clean(self):
username = self.cleaned_data['username'].lower()
new = User.objects.filter(username = username)
if new.count():
raise ValidationError("User Already Exist")
return username
def email_clean(self):
email = self.cleaned_data['email'].lower()
new = User.objects.filter(email=email)
if new.count():
raise ValidationError(" Email Already Exist")
return email
def clean_password2(self):
password1 = self.cleaned_data['password1']
password2 = self.cleaned_data['password2']
if password1 != password2:
raise ValidationError("Password don't match")
return password2
def save(self, commit = True):
user = User.objects.create_user(
self.cleaned_data['username'],
self.cleaned_data['email'],
self.cleaned_data['password1'],
last_login= datetime.now()
)
return user
class AddDetails(forms.ModelForm):
class Meta:
model = Customer
fields = ("age", "phone")
age = forms.IntegerField(label="Age", required=True)
phone = forms.CharField(label="Mobile Number", required=True)
Here is my views.py
from django.shortcuts import render, redirect
from accounts.forms import *
from datetime import datetime
from django.contrib import messages
def usersignup(request):
if request.method=="POST":
# User Sign-up form (username, email, first_name, last_name, password1, password2)
user_form= UserSignup()
# Customer detail form (age and phone number)
details_form = AddDetails(request.POST)
# If both forms are valid
if all((user_form.is_valid(), details_form.is_valid())):
# Saving with commit=False gets you a model object, then you can add your extra data and save it.
user = user_form.save()
customer= details_form.save(commit=False)
# As user is in OnetoOne Relationship with customer
customer.user= user
customer.save()
messages.success(request, 'Account created successfully')
# return redirect('details')
# if a GET (or any other method) we'll create a blank form
user_form =UserSignup()
details_form= AddDetails()
return render(request, 'registration_form.html', {'user_form': user_form, 'details_form': details_form})
Here is registration_form.html
{% extends 'base.html' %}
{% block content %}
<div class = "login">
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<h1>Sign up for new account</h1>
<form method="post" >
{% csrf_token %}
<table>
{{user_form.as_table}}
{{details_form.as_table}}
<tr>
<td></td>
<td><input type="submit" name="submit" value="Register" /></td>
</tr>
</table>
</form>
</div>
{% endblock content %}
Here are my models
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
pass
class Customer(models.Model):
user= models.OneToOneField(User, on_delete=models.CASCADE)
age= models.IntegerField(blank=True)
phone= models.CharField(max_length=15, blank=False, null=False)
def __str__(self):
return self.user.first_name
Both passwords are matched. but still getting errors.
I think, this is because of your if condition in the usersignup view, try some modifications in it, for checking both form validation try changing it to if user_form.is_valid() and details_form.is_valid():, in the following way:
views.py
def usersignup(request):
if request.method == "POST":
# User Sign-up form (username, email, first_name, last_name, password1, password2)
user_form = UserSignup(request.POST)
# Customer detail form (age and phone number)
details_form = AddDetails(request.POST)
# If both forms are valid
if user_form.is_valid() and details_form.is_valid():
# Saving with commit=False gets you a model object, then you can add your extra data and save it.
user = user_form.save()
customer = details_form.save(commit=False)
# As user is in OnetoOne Relationship with customer
customer.user = user
customer.save()
messages.success(request, 'Account created successfully')
# return redirect('details')
# if a GET (or any other method) we'll create a blank form
user_form = UserSignup()
details_form = AddDetails()
return render(request, 'home/registration_form.html', {'user_form': user_form, 'details_form': details_form})
Note: Function based views are generally written in snake_case not in smallcase, it will be better if you changed it to user_sign_up from usersignup.
I have a UserPost List View which is a view for a specific user's posts. I am looping the posts of this specific user but I want to add this user's profile details like profile image and other details like email.
So, I am not sure on how to add the user details of the user's post names as designer not the logged-in user.
I can add the user/designer details in every looped post but I don't want it to be repeated with every post I just want it to appear once just like {{ view.kwargs.username }} as this page is realted only to this user/designer
Here is the models.py
class Post(models.Model):
designer = models.ForeignKey(User, on_delete=models.CASCADE, related_name="post")
title = models.CharField(max_length=100, unique=True)
here is the profile model related to every user
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
first_name = forms.CharField()
last_name = forms.CharField()
class Meta:
model = User
fields = ['username', 'first_name', 'last_name',
'email']
here is the views for the userpostlist which is filtered by a specific user/designer not the logged in user
class UserPostListView(ListView):
model = Post
template_name = "user_posts.html"
context_object_name = 'posts'
queryset = Post.objects.filter(admin_approved=True)
paginate_by = 6
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Post.objects.filter(designer=user, admin_approved=True).order_by('-date_posted')
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
has_items = Item.objects.filter(designer__username=self.kwargs['username']).exists()
context['has_items'] = has_items
return context
here is the template
{% if has_items %}
<h1 class="display-4">Hello, this is {{ view.kwargs.username }} </h1>
<img class="profile_image" src={{ designer.profile.image.url }}> <----------- I want it to appear
{{ designer.email }}<----------- I want it to appear
{% else %}
Show nothing
{% endif %}
{% for post in posts %}
Post details
{% endfor %}
You can add this to the context:
from django.contrib.auth import get_user_model
class UserPostListView(ListView):
model = Post
template_name = 'user_posts.html'
context_object_name = 'posts'
queryset = Post.objects.filter(admin_approved=True)
paginate_by = 6
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).filter(
designer__username=self.kwargs['username']
).order_by('-date_posted')
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['designer'] = designer = get_object_or_404(
get_user_model(),
username=self.kwargs['username']
)
context['has_items'] = Item.objects.filter(designer=designer).exists()
return context
I Need to Restrict the Options in a Select Field of a Django Form for not staff users.
So these are my models.py:
#!/usr/bin/python3
from django.db import models
from django.urls import reverse
class Extension(models.Model):
username = models.CharField(primary_key=True, max_length=200, help_text='')
callerid = models.CharField(max_length=200, help_text='')
extension = models.CharField(max_length=3, help_text='')
firstname = models.CharField(max_length=200, help_text='')
lastname = models.CharField(max_length=200, help_text='')
password = models.CharField(max_length=200, help_text='')
context = models.ForeignKey('Context', on_delete=models.SET_NULL, null=True)
def get_absolute_url(self):
return reverse('extension-detail', args=[str(self.username)])
def my_get_absolute_url(self):
return reverse('my-extension-detail', args=[str(self.username)])
def __str__(self):
return self.username
class Context(models.Model):
name = models.CharField(primary_key=True, max_length=200, help_text='')
countryprefix = models.CharField(max_length=200, help_text='')
cityprefix = models.CharField(max_length=200, help_text='')
number = models.CharField(max_length=200, help_text='')
extensionsfrom = models.CharField(max_length=200, help_text='')
extensionstill = models.CharField(max_length=200, help_text='')
portscount = models.CharField(max_length=200, help_text='')
def get_absolute_url(self):
return reverse('context-detail', args=[str(self.name)])
def my_get_absolute_url(self):
return reverse('my-context-detail', args=[str(self.name)])
def __str__(self):
return self.name
views.py:
#!/usr/bin/python3
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.contrib.auth.models import Permission
from catalog.models import Extension, Context
from django.shortcuts import render
from django.urls import reverse_lazy
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
class ExtensionCreate(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
model = Extension
fields = '__all__'
permission_required = 'catalog.add_extension'
class ExtensionUpdate(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
model = Extension
fields = '__all__'
permission_required = 'catalog.change_extension'
class ExtensionDelete(LoginRequiredMixin, PermissionRequiredMixin, DeleteView):
model = Extension
success_url = reverse_lazy('extensions')
permission_required = 'catalog.delete_extension'
urls.py:
#!/usr/bin/python3
from . import views
from django.urls import path
urlpatterns = [
path('', views.index, name='index'),
path('extensions/', views.ExtensionListView.as_view(), name='extensions'),
path('extension/<str:pk>', views.ExtensionDetailView.as_view(), name='extension-detail'),
path('extension/create/', views.ExtensionCreate.as_view(), name='extension-create'),
path('extension/<str:pk>/update/', views.ExtensionUpdate.as_view(), name='extension-update'),
path('extension/<str:pk>/delete/', views.ExtensionDelete.as_view(), name='extension-delete'),
path('myextensions/', views.ExtensionsByUserListView.as_view(), name='my-extensions'),
path('myextension/<str:pk>', views.ExtensionsByUserDetailView.as_view(), name='my-extension-detail'),
path('contexts/', views.ContextListView.as_view(), name='contexts'),
path('context/<str:pk>', views.ContextDetailView.as_view(), name='context-detail'),
path('context/create/', views.ContextCreate.as_view(), name='context-create'),
path('context/<str:pk>/update/', views.ContextUpdate.as_view(), name='context-update'),
path('context/<str:pk>/delete/', views.ContextDelete.as_view(), name='context-delete'),
path('mycontexts/', views.ContextByUserListView.as_view(), name='my-contexts'),
path('mycontext/<str:pk>', views.ContextByUserDetailView.as_view(), name='my-context-detail'),
]
template:
{% extends "base_generic.html" %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit">
</form>
{% endblock %}
In this is how it looks like:
The Username is always the same as one of the contexts.
Only Staff User can create a new Context and new Users.
The users then should add their extensions.
While employees should be able to select the context when creating a new extension, customers should only be able to see or select their context in the list.
Therefore it is needed to filter the Select-attribute for non-staff members so that only the user's context is visible, which is equal to his Username.
Alternatively, I want to prepopulate and hide the context form field with the Username (=own context)
How can I do either of this in the easiest way possible?
Here is what I tried myself so far:
Like described in this how-to: https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Forms#Renew-book_form_using_a_Form_and_function_view I Defined a Form in forms.py:
#!/usr/bin/python3
from django import forms
class MyExtensionCreateForm(forms.Form):
# username = forms.CharField(help_text="")
# callerid = forms.CharField(help_text="")
# context = forms.CharField(help_text="")
firstname = forms.CharField(help_text="")
lastname = forms.CharField(help_text="")
extension = forms.CharField(help_text="")
password = forms.CharField(help_text="")
def clean_data(self):
data = self.cleaned_data
# Remember to always return the cleaned data.
return data
I then added the folowing to the views.py:
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.urls import reverse
from catalog.forms import MyExtensionCreateForm
def MyExtensionCreate(request):
# extension = get_object_or_404(Extension)
# If this is a POST request then process the Form data
if request.method == 'POST':
# Create a form instance and populate it with data from the request (binding):
form = MyExtensionCreateForm(request.POST)
# Check if the form is valid:
if form.is_valid():
# process the data in form.cleaned_data as required
form.firstname = form.cleaned_data['firstname']
form.lastname = form.cleaned_data['lastname']
form.extension = form.cleaned_data['extension']
form.password = form.cleaned_data['password']
# Prepopulated Fields
form.context = request.user
form.callerid = str(form.cleaned_data['firstname'])+" "+str(form.cleaned_data['lastname'])+" "+str(form.cleaned_data['extension'])
form.username = str(request.user)+"_"+str(form.cleaned_data['extension'])
form.save()
# redirect to a new URL:
return HttpResponseRedirect(reverse('my-extensions'))
# If this is a GET (or any other method) create the default form.
else:
form = MyExtensionCreateForm({'context': request.user})
context = {
'form': form,
}
return render(request, 'catalog/extension_form-by-user.html', context)
# class MyExtensionCreate(LoginRequiredMixin, CreateView):
# model = Extension
# fields = '__all__'
# form_class = MyExtensionCreateForm
Then I added a new URL to URL patterns in urls.py and added the new Link to the base_generic.html
path('myextensions/create/', views.MyExtensionCreate, name='my-extension-create'),
<li>Add Extension</li>
I can view the form, and if I add the context field to the visible form fields, I can see that the context will initially fill with the logged-in username (See First Picture Below). But as soon as I submit the form I'll get Error's no matter what I try, So basically the GET is working, but the POST isn't really.
See Folowing Pictures:
I was able to Filter the Choices by the Username in the ModelForm but since then I'm not able to save the form to the database anymore.
Here is the new Stack Post with the Resolution of this Post here and the new Question/Problem.
Django: saving the Form does not work (The ModelForm Filters the ForeignKey choices by request.user)
everyone!
I want to display to forms in a template
My forms are:
class ContactForm(forms.Form):
contact_name = forms.CharField(
required=True)
contact_email = forms.EmailField(
required=True)
contact_phone = forms.CharField(
required=True)
subject = forms.CharField(
required=True)
message = forms.CharField(
required=True,
widget=forms.Textarea)
class CVCreateForm(forms.ModelForm):
class Meta:
model = CV
fields = '__all__'
And I have two FormViews:
class ContactView(FormView):
form_class = ContactForm
succes_url = reverse_lazy('webpage:home')
def form_valid(self, form):
context = super(ContactView, self).form_valid(form)
contact_email = form.cleaned_data['contact_email']
subject = form.cleaned_data['subject']
message = 'Name: {}\nPhone:{}\n{}'.format(form.cleaned_data['contact_name'], form.cleaned_data['contact_phone'], form.cleaned_data['message'],)
send_mail(subject,
message,
contact_email,
['maumg1196#gmail.com'])
return context
class CVCreateView(FormView):
form_class = CVCreateForm
succes_url = reverse_lazy('webpage:home')
def form_valid(self):
context = super(CVCreateView, self).form_valid(form)
form_owner = form.cleaned_data['owner']
form_cv = form.cleaned_data['cv']
form_email = form.cleaned_data['email']
send_mail('Curriculum Vitae',
form_cv,
form_email,
['maumg1196#gmail.com'])
cv = CV(owner=form_owner, email=form_email, cv=form_cv)
cv.save()
return context
(Note: In the second form the 'form_cv' is gonna be a PDF file I think that isn't a problem to send the email but I don't know very well.)
I want to display this two FormViews in a TemplateView
Thanks :)
In your TemplateView you need to just need to pass the two forms in the context as follows:
from django.views.generic import TemplateView
from .forms import ContactView, CVCreateView
class MyTemplateView(TemplateView):
template_name = 'path/to/my_template.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['contact_form'] = ContactView()
context['cv_form'] = CVCreateView()
return context
In the template you set the form action attribute to point to the URL of the appropriate view, ContactView or CVCreateView, so something like this:
<form action="{% url 'contact_form' %}" method="POST">
{{ contact_form }}
</form>
<form action="{% url 'cv_form' %}" method="POST">
{{ cv_form }}
</form>
Hope this helps?