I wish to know how to display 'auto_now_add' fields (and as disabled fields) in django frontend forms.
I attach some of relevant code:
# models.py
class ModelA(models.Model):
name = models.CharField('Name', max_length=100)
inserted = models.DateTimeField('Inserted ', auto_now_add=True)
# forms.py
class ProcessModelAForm(forms.ModelForm):
class Meta:
model = ModelA
fields = '__all__'
widgets = {
"name": forms.TextInput({
"class": "form-control",
"disabled": True,
}),
"inserted": forms.DateTimeInput({
"class": "form-control",
"disabled": True,
}),
}
# views.py
def process_model_a(request, pk):
instance_model_a = get_object_or_404(ModelA, id=pk)
process_form = ProcessModelAForm(instance=instance_model_a)
if request.method == 'POST':
# ...
return render(request, 'myapp/process_model_a.html', {'process_form ': process_form , 'instance':instance_model_a , } )
# process_model_a.html
<form method="post" class="form-horizontal">
{% csrf_token %}
{% for field in process_form %}
<div class="form-group form-group-lg">
<label for="{{ field.id_for_label }}" class="col-sm-2 control-label">{{field.label}}</label>
<div class="col-sm-6">
{{ field }}
</div>
<div class="col-sm-4">
{{ field.errors }}
</div>
</div>
{% endfor %}
<div class="form-group">
<div class="col-sm-10">
<button type="submit" class="btn btn-primary btn-lg center-block">Process</button>
</div>
</div>
</form>
The page "process_model_a.html" shows only "name" fields.
How can I display also "inserted" field?
Thanks.
Related
I'm trying to update a user profile using two forms the problem is that when I click to update I get the following error:
“<ul class="errorlist">
<li>username<ul class="errorlist"><li>This field is required.</li>
</ul>
”
My model module is the following:
# user.models
from django.contrib.auth.models import AbstractUser
from django.db import models
from model_utils.models import TimeStampedModel
from localflavor.br.models import BRPostalCodeField, BRStateField, BRCNPJField, BRCPFField
class User(AbstractUser):
class Roles(models.IntegerChoices):
SUPER = 0
COMPANY = 1
UNITY = 2
STAFF = 3
picture = models.ImageField(blank=True, null=True)
role = models.IntegerField(choices=Roles.choices, default=Roles.STAFF)
class Staff(TimeStampedModel):
user: User = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
unity = models.ForeignKey(Unity, related_name="staff", on_delete=models.CASCADE)
cpf = BRCPFField("CPF")
class Meta:
verbose_name: str = 'Staff'
verbose_name_plural: str = 'Staff'
ordering = ("-created",)
def __str__(self):
if f"{self.user.first_name} {self.user.last_name}".strip():
return f"{self.user.first_name} {self.user.last_name}"
return str(self.user.username)
And my user forms looks like:
#user.forms
class UserModelForm(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email', 'is_active']
class StaffModelForm(forms.ModelForm):
class Meta:
model = Staff
fields = ['cpf', 'unity']
widget = {
'cpf': forms.TextInput(attrs={'class': "form-control", 'placeholder': 'Primeiro Nome', }),
'unity': forms.EmailInput(attrs={'class': "form-control", 'placeholder': 'meu#email.com', }),
}
with the following view:
#views
…
def update_staff(request: HttpRequest, pk: int) -> HttpResponse:
instance: Staff = get_object_or_404(Staff, pk=pk) # get staff instance
template_name = 'pages/staff_update_form.html' # use this template
if request.method == "POST":
profile_form = user_forms.StaffModelForm(request.POST, instance=instance)
user_form = user_forms.UserModelForm(request.POST, request.FILES, instance=instance.user)
print(user_form.is_valid())
print(user_form.errors)
print(profile_form.is_valid())
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request, 'Your profile is updated successfully')
return redirect(to='pages:dashboard')
context = dict(profile_form=user_forms.StaffModelForm(instance=instance),
user_form=user_forms.UserModelForm(instance=instance.user))
return render(request, template_name=template_name, context=context)
Print output:
False
<ul class="errorlist"><li>username<ul class="errorlist"><li>This field is required.</li></ul
></li></ul>
True
and HTML:
{% load crispy_forms_tags %}
{% if user_form.errors %}
<div class="alert alert-danger alert-dismissible" role="alert">
<div id="form_errors">
{% for key, value in user_form.errors.items %}
<strong>{{ value }}</strong>
{% endfor %}
</div>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
<div class="py-5 text-center">
<span class="material-icons" style="height: 48px; width: auto; font-size: 48px;">people_alt</span>
<h1 class="h3 mb-3 fw-normal">Atualize aqui os dados do usuário!</h1>
</div>
<form class="form-signin" method="POST" enctype="multipart/form-data">
<div class="form-group">
<div class="row g-8 my-auto mx-auto" style="padding-left: 12%; padding-right: 12%;">
<div class="col-md-8 col-lg-12">
{% crispy profile_form %}
</div>
</div>
<div class="row g-8 my-auto mx-auto" style="padding-left: 12%; padding-right: 12%;">
<div class="col-md-8 col-lg-12">
{% crispy user_form %}
</div>
</div>
<div class="col-md-12 col-lg-12">
<br>
<div class="modal-footer">
Cancel
<button class="btn btn-primary mb-2" type="submit">Update</button>
</div>
</div>
</div>
</form>
<div class="py-5 text-center">
<p class="mt-5 mb-3 text-muted">© 2022-2023</p>
</div>
So I have no idea what the source of this problem is. Everything seems fine to me, can anyone help me?
I am still new to django. Playing around with a leadmanager app and I don't know why my form is not validating.
views
def index(request):
lead=LeadForm()
if request.method == 'POST':
lead=LeadForm(request.POST)
if lead.is_valid():
messages.success(request, f'Thank you for registering. Someone will be contacting you soon.')
return redirect('index')
else:
lead=LeadForm()
messages.error(request, f'Something went wrong. Please try again later.')
return render(request, "frontend/index.html", {'lead':lead})
in index.html
<form action="" method="POST" class="lead-form">
{% csrf_token %}
<fieldset class="lead-info">
<div class="form-control">
<label for="">Full Name</label>
{{ lead.fullname }}
</div>
<div class="form-control">
<label for="">Email</label>
{{ lead.email }}
</div>
<div class="form-control">
<label for="">Phone</label>
{{ lead.phone }}
</div>
<div class="form-control">
<label for="">City</label>
{{ lead.city }}
</div>
</fieldset>
<button type="submit" class="btn-pill">Submit</button>
</form>
in forms.py
class LeadForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
model = Lead
fields = ['fullname', 'email', 'phone', 'city', 'contact_preference']
widgets = {'contact_preference': forms.RadioSelect }
Any help is appreciated. contact_preference is rendering FYI, I just cut the code to keep this question not that long.
So i have a button on my detailView page for my model 'patient', and that takes you to a createView for my other model 'appointment'. What i want is the foreign key field of the appointment to be pre-filled depending on what detailView i come from. Here is my code so far:
urls.py:
# /patients/appointment/add
url(r'appointment/add/$', views.appointmentCreate.as_view(), name='appointment-create'),
models.py:
class patient(models.Model):
TITLE_CHOICES = (
('Mr', 'Mr'),
('Mrs', 'Mrs'),
('Ms', 'Ms'),
('Miss', 'Miss'),
)
Title = models.CharField(max_length=100, blank=True, choices=TITLE_CHOICES)
First_Name = models.CharField(max_length=250, default='')
Surname = models.CharField(max_length=250, default='')
DOB = models.DateField()
class appointment(models.Model):
Patient = models.ForeignKey(patient, on_delete=models.CASCADE)
views.py:
class appointmentCreate(LoginRequiredMixin, CreateView):
model = appointment
fields = ['Patient', 'Date', 'Time', 'Duration', 'Location', 'Clinician', 'AppointmentType']
form-template.html:
<body>
{% for field in form %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<span class="text-danger small">{{ field.errors }}</span>
</div>
<label class="control-label col-sm-2">{{ field.label_tag }}</label>
<div class="col-sm-10">{{ field }}</div>
</div>
{% endfor %}
</body>
appointment_form.html:
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-body">
<h3>Add new appointment</h3>
<form class="form-horizontal" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% include 'patients/form-template.html' %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
The button from the detailView of patient to create appointment:
<ul class="nav nav-pills" style="margin-bottom: 10px;">
<li role="presentation" class="active">View All</li>
<li role="presentation">Add New Appointment</li>
</ul>
For example, the url might be /appname/appointment/add/?Patient=pk , where the end part determines what the value of Patient will be. I have looked into the get_initial function but do not understand how it can help me achieve this. Any help is appreciated. I am relatively new to django so please nothing too complex.
Edit: I have added this code to my model, thanks to Dimitris Kougioumtzis:
def get_context_data(self, **kwargs):
context = super(appointmentCreate, self).get_context_data(**kwargs)
context['patient_id'] = self.request.GET.get('patient')
return context
How do i implement this code?
first you create a modelForm:
from django import forms
from your_app.models import appointment
class AppointmentForm(forms.ModelForm):
class Meta:
model = appointment
fields = ['Patient', 'Date', 'Time', 'Duration', 'Location', 'Clinician', 'AppointmentType']
Then you pass the model form in your CreateView:
class appointmentCreate(LoginRequiredMixin, CreateView):
model = appointment
form_class = AppointmentForm
def get_initial(self):
patient = self.request.GET.get('patient')
return {
'patient': patient,
}
and Your patient choicefield will be populated based on the request get parameter
Hello I have got question I have made modelformset_factory and in options I have choosen can_delete = True and now I don't know how to delete marked objects as 'DELETE' : True to delete them from database. I was trying to do this in some ways and it didnt work. I was looking for it also in django formsetmodels documentation but this didnt help me. With this option can_delete = True I get additional checkbox in my html page Delete and marking him only prints me in console on print:
{'username': 'sw', 'email': 'a#gmail.com', 'city': 'ss', 'code': 12345, 'id': , 'DELETE': False}
Saving forms to database is working but I dont know how to delete marked forms from database.
I would be very thankful for every help.
I have made modelformset_factory from model in models.py
class TestModel(models.Model):
username = models.CharField(max_length=120)
email = models.EmailField()
city = models.CharField(max_length=120)
code = models.IntegerField()
#W admin panelu za miast TestModel object bedzie username
def __str__(self):
return self.username
Then I have added in my views.py function:
def django_modelformset(request):
TestModelFormset = modelformset_factory(TestModel, fields=['username', 'email', "city",
"code"], extra=1, can_delete=True)
formset = TestModelFormset(request.POST or None)
if formset.is_valid():
for form in formset:
print(form)
print(form.cleaned_data)
form.save()
context = {"formset": formset}
return render(request, "modelformset.html", context)
My modelformset.html looks like this:
<form method="POST" action="">
{% csrf_token %}
{{ formset.management_form}}
{% for form in formset %}
<div>
{{ form.as_p }}
<hr/>
</div>
{% endfor %}
<input type="submit" value="Save">
I haven't personally had to do this, but from the docs it seems you have a few options.
Call save on the formset instead of each form.
if formset.is_valid():
formset.save()
If you must loop through each form you could something like this.
if formset.is_valid():
for form in formset:
print(form.cleaned_data)
if form.cleaned_data["DELETE"]:
# Do what you want with the form data
# i.e. get the object from the database and delete it.
else:
form.save()
Loop through the deleted forms separately.
if formset.is_valid():
forms = formset.save(commit=False)
for object in formset.deleted_objects:
object.delete()
It's work for me
view.py
Blog_MetaFormSet = modelformset_factory(Metas, form=MetaForm, extra=0, can_delete=True)
Blog_MetaQuerySet = Metas.objects.filter(blog=blog_obj).order_by('created_at')
contex={
"blog_meta_formset": Blog_MetaFormSet(request.POST,queryset=Blog_MetaQuerySet),
}
if blog_meta_formset.is_valid():
for metaform in blog_meta_formset:
meta_obj = metaform.save(commit=False)
meta_obj.blog = blog_obj
if metaform.cleaned_data["DELETE"]==True:
meta_obj.delete()
else:
meta_obj.save()
In Templates
<div class="row">
<div id="cfield-form-list"> {{ blog_meta_formset.management_form }} {% for meta_form in blog_meta_formset %}
<div id="form-{{forloop.counter0}}" class="cfield-form xrow">
<div class="col-md-12 mb-3">
<div class="row d-flex align-items-center">
<div class="col-md-4">
<label class="form-label">Name</label> {{ meta_form.title|attr:"class:form-control"|attr:"type:text" }} </div>
<div class="col-md-4">
<label class="form-label">Value</label> {{ meta_form.value|attr:"class:form-control"|attr:"rows:2" }} </div>
<div class="col-md-4">
<div class="form-check custom-checkbox mb-3 checkbox-primary"> {{ meta_form.DELETE|attr:"class:form-check-input"|attr:"type:checkbox" }}
<label class="form-check-label" for="customCheckBox2">Delete</label>
</div>
</div>
</div>
</div> {{meta_form.id}} </div> {% endfor %} </div>
<div id="empty_form" class="hidden">
<div class="col-md-12 mb-3">
<div class="row d-flex align-items-center">
<div class="col-md-4">
<label class="form-label">Name</label> {{ blog_meta_formset.empty_form.title|attr:"type:text"|attr:"class:form-control" }} </div>
<div class="col-md-4">
<label class="form-label">Value</label> {{ blog_meta_formset.empty_form.value|attr:"class:form-control"|attr:"rows:2" }} </div>
<div class="col-md-4">
<div class="form-check custom-checkbox mb-3 checkbox-primary"> {{ blog_meta_formset.empty_form.DELETE|attr:"class:form-check-input"|attr:"type:checkbox" }}
<label class="form-check-label" for="customCheckBox2">Delete</label>
</div>
</div>
<div class="col-md-4">
<button type="button" class="btn btn-danger remove_cfield" rel="">Delete</button>
</div>
</div>
</div>
</div>
<div class="col-md-12">
<button type="button" id="add-cfield" class="btn btn-primary mb-3 mt-3 ">Add Custom Field</button>
</div>
</div>
In js
const totalNewForms = document.getElementById('id_form-TOTAL_FORMS')
const addMoreBtn = document.getElementById('add-cfield')
addMoreBtn.addEventListener('click',add_new_form)
function add_new_form(event){
if (event){
event.preventDefault()
}
const currentCF_Forms = document.getElementsByClassName('cfield-form')
console.log(currentCF_Forms)
const currentCF_FormCount = currentCF_Forms.length //+ 1
const formCopyTarget = document.getElementById('cfield-form-list')
const copyEmptyFormEl = document.getElementById('empty_form').cloneNode(true)
//remove class hidden
copyEmptyFormEl.setAttribute('class','cfield-form xrow')
copyEmptyFormEl.setAttribute('id',`form-${currentCF_FormCount}`)
const regex = new RegExp('__prefix__','g')
copyEmptyFormEl.innerHTML = copyEmptyFormEl.innerHTML.replace(regex,currentCF_FormCount)
totalNewForms.setAttribute('value', currentCF_FormCount +1)
//now add new empty form element to our html form
formCopyTarget.append(copyEmptyFormEl)
Basically I want to change value of company id and company name if your company field is changed.
Here I have used django-autocomplete-light for your company field. Code for this form:
class PartnerAddForm(forms.ModelForm):
company_id = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control', 'disabled': ''}), required=False)
company_name = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control', 'disabled': ''}), required=False)
class Meta:
model = CompanyCompanyMap
fields = ('your_company',)
widgets = {
'your_company': autocomplete.ModelSelect2(url='url_company_autocomplete',
attrs={'class': 'form-control',
'data-placeholder': 'Type for getting available companies'})
}
Code for autocomplete view of your company field:
class CompanyAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
qs = CompanyAccess(self.request).get_non_partners()
if self.q:
qs = qs.filter(company_name__istartswith=self.q)
return qs
And code for template of this form
<form class="form-horizontal" role="form" action="." method="POST">
{% csrf_token %}
{% for f in form %}
<div class="form-group">
<label for="id_{{ f.name }}" class="col-sm-2 control-label">{{ f.label|capfirst }}</label>
<div class="col-sm-7">
{{ f }}
</div>
</div>
{% endfor %}
<div class="form-group">
<label class="col-sm-2 control-label"></label>
<div class="col-sm-7">
<button type="submit" class="btn btn-default btn-primary">
Add Company as Friend
</button>
</div>
</div>
<!-- /.table-responsive -->
</form>
Is there any way to change it using js or other mechanism?