data from views.py to Django forms - python

I am a newbie in Django and I have learn some basic things about it. My problem is, I get data from django models but I am not able to pass/display it to a form. I would like to have a forms.py with 1 phone_id Selector and 3 textInputs in order to insert data to the desired phone.
My models.py:
class Phone(models.Model):
user = models.ForeignKey(User)
num_calls = models.CharField(max_length=20, null=True, blank=True)
time_btwn_calls = models.CharField(max_length=20, null=True, blank=True)
psap = models.CharField(max_length=30, null=True, blank=True)
My forms.py:
from django import forms
class phoneForm(forms.Form):
NumberOfCalls = forms.CharField(
min_length = 1,
widget=forms.TextInput({'class': 'form-control'})
)
TimeBetweenCalls = forms.CharField(
widget=forms.TextInput({'class': 'form-control'})
)
PSAP = forms.CharField(
min_length = 1,
widget=forms.TextInput({'class': 'form-control'})
)
def __init__(self, *args, **kwargs):
phone_choices = kwargs.pop('phone_choices')
super(Send2tcu, self).__init__(*args, **kwargs)
self.fields['phone'] = forms.MultipleChoiceField(
required = True,
widget = forms.Select({'class': 'form-control'}),
choices = phone_choices
)
I just create a form with the 3 textInputs and the MultipleChoiceField where I need to display the data from the differents phone_id.
My view.py:
def phone_config(request):
phones = Phone.objects.filter(user_id = request.user.id).values_list('id', flat=True)
if request.method == 'POST':
form = phoneForm(request.POST, phone_choices=phones)
if form.is_valid():
cleaned_data = form.cleaned_data
phone_id = cleaned_data.get('phone')
NumberOfCalls = cleaned_data.get('NumberOfCalls')
TimeBetweenCalls = cleaned_data.get('TimeBetweenCalls')
PSAP = cleaned_data.get('PSAP')
Tcu.objects.filter(id=phone_id).update(
num_calls = NumberOfCalls,
time_btwn_calls = TimeBetweenCalls,
psap = PSAP,
)
return redirect(reverse('gracias'))
else:
form = phoneForm(phone_choices=phones)
return render(request, 'configurer/configurer.html', {'form': form})
def gracias_view(request):
return render(request, 'configurer/gracias.html')
In my view first of all, I get the all the phone_id for the current user. Then I check if the method is post and I get the data from the form and also I pass to the form the different phone_ids.Then I check if the form is valid and I create the object Phone. After that assign the different parameters to the selected phone_id and save them.
There is something wrong in my code. I am getting this error:
TypeError at /configurer/
'int' object is not iterable
return render(request, 'heroconfigurer/heroconfigurer.html', {'form':
form})

models.py:
class Phone(models.Model):
user = models.ForeignKey(User)
num_calls = models.CharField(max_length=20, null=True, blank=True)
time_btwn_calls = models.CharField(max_length=20, null=True, blank=True)
psap = models.CharField(max_length=30, null=True, blank=True)
forms.py:
from django.forms.widgets import TextInput, Select
class PhoneViewForm(ModelForm):
class Meta:
model = Phone
widgets = {'user': Select(attrs={'class': 'form-control'}),
'num_calls': TextInput(attrs={'class': 'form-control'}),
'time_btwn_calls': TextInput(attrs={'class': 'form-control'}),
'psap': TextInput(attrs={'class': 'form-control'})
}
fields = ['user',
'num_calls',
'time_btwn_calls',
'psap'
]
If you manipulate model objects in your form Django recommends you to use ModelForm. You also may fill this form with initial model instance. Hope that helps.

Related

How to get a specific queryset in Django

I am building a hospital management app and I am currently building the Nurse's webpage. In that webpage, I would like the following to display: a list of all employed nurses, a list of their workshifts, and what departments they work for.
I am trying to get the department section to display but I keep getting an error "too many values to unpack (expected 2)".
What can I do so that the nurses' department shows?
Models.py
from django.db import models
# Create your models here.
#Work Related aka Department and Work Shift
class Department(models.Model):
name = models.CharField(max_length=200, null=True, blank=True)
def __str__(self):
return self.name
class WorkShift(models.Model):
name = models.CharField(max_length=200, null=True, blank=True)
start_datetime = models.DateTimeField(null=True, blank=True)
end_datetime = models.DateTimeField(null=True, blank=True)
def __str__(self):
return self.name
#Personel Related aka Employees and Patients
class Doctor(models.Model):
name = models.CharField(max_length=200, null=True, blank=True)
email = models.CharField(max_length=200, null=True)
phone = models.CharField(max_length=200, null=True)
department = models.ForeignKey(Department, null=True, blank=True, on_delete=models.CASCADE)
work_shift = models.OneToOneField(WorkShift, blank=True, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Nurse(models.Model):
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, null=True)
phone = models.CharField(max_length=200, null=True)
sector = models.ForeignKey(Department, null=True, blank=True, on_delete=models.CASCADE)
reports_to = models.ForeignKey(Doctor, blank=True, null=True, on_delete=models.CASCADE)
work_shift = models.OneToOneField(WorkShift, default="", blank=True, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Patient(models.Model):
STATUS = (
('Sick', 'Sick'),
('Healing', 'Healing'),
('Cured', 'Cured'),
('Deceased', 'Deceased'),
)
name = models.CharField(max_length=200, null=True, blank=True)
description = models.TextField(blank=True, null=True)
status = models.CharField(max_length=200, null=True, blank=True, choices=STATUS)
department = models.ForeignKey(Department, default="", null=True, blank=True, on_delete=models.CASCADE)
care = models.ForeignKey(Nurse, default="", blank=True, null=True, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True, blank=True, null=True)
def __str__(self):
return self.name
from django.shortcuts import render, redirect
Views.py
# Create your views here.
from django.shortcuts import render
from .models import Doctor, Nurse, Patient, Department, WorkShift
from django.http import HttpResponse
from .forms import DoctorForm, NurseForm, PatientForm
# Create your views here.
def index(request):
patient = Patient.objects.all()
nurse = Nurse.objects.all()
doctor = Doctor.objects.all()
department = Department.objects.all()
total_patient = patient.count()
sick = patient.filter(status='Sick').count()
healing = patient.filter(status='Healing').count()
cured = patient.filter(status='Cured').count()
total_nurse = nurse.count()
# if request.method == 'POST':
# form =
context = {
'patient':patient, 'nurse':nurse,
'doctor':doctor, 'total_patient':total_patient,
'sick':sick, 'healing':healing, 'cured':cured,
'total_nurse':total_nurse,
'department':department
}
return render(request, 'lifesaver/index.html', context)
#All Patient Related
def patient(request):
patient = Patient.objects.all()
context = {'patient':patient}
return render(request, 'lifesaver/patient.html', context)
def patient_add(request):
patient = Patient.objects.all()
form = PatientForm()
if request.method == 'POST':
form = PatientForm(request.POST)
if form.is_valid():
print("Patient Form is Valid")
form.save()
else:
print("Patient Form is Invalid")
print(form.errors)
return redirect('patient')
context = {'form':form,}
return render(request, 'lifesaver/patient_add.html', context)
def patient_update(request, pk):
patient = Patient.objects.get(id=pk)
form = PatientForm(instance=patient)
if request.method == 'POST':
form = PatientForm(request.POST, instance=patient)
if form.is_valid():
print('Update completed')
form.save()
return redirect('patient')
else:
print('Update not completed')
print(form.errors)
context = {'form':form}
return render(request, 'lifesaver/patient_update.html', context)
#All Doctor Related
def doctor(request):
doctor = Doctor.object.all()
context = {}
return render(request, 'lifesaver/doctor.html', context)
def doctor_add(request):
doctor = Doctor.object.all()
form = DoctorForm()
context = {'doctor':doctor, 'form':form}
return render(request, 'lifesaver/doctor')
def doctor_update(request):
doctor = Doctor.object.all()
form = DoctorForm()
context = {'doctor':doctor, 'form':form}
# Nurse Related
def nurse(request):
nurse = Nurse.objects.all()
workshift = WorkShift.objects.all()
department = Nurse.objects.get('sector')
context = {'nurse':nurse, 'workshift':workshift, 'department':department}
return render(request, 'lifesaver/nurse.html', context)
def nurse_add(request):
nurse = Nurse.objects.all()
form = NurseForm()
if request.method == 'POST':
form = NurseForm(request.POST)
if form.is_valid():
print("Nurse Form is Valid")
form.save()
else:
print("Nurse Form is Invalid")
print(form.errors)
return redirect('nurse')
context = {'form':form,}
return render(request, 'lifesaver/nurse_add.html', context)
def nurse_update(request):
nurse = Nurse.objects.all()
form = NurseForm()
context = {}
return render(request, 'lifesaver/nurse_update.html', context)
#Work Related
def department(request):
department = Department.objects.all()
context = {'department':department}
return render(request, 'lifesaver/department.html', context)
Forms.py
from django import forms
from django.forms import ModelForm
from .models import Doctor, Nurse, Patient, Department, WorkShift
from django.contrib.auth.forms import UserCreationForm
class DoctorForm(forms.ModelForm):
name = forms.CharField(widget = forms.TextInput(attrs =
{
'placeholder': 'Add a New Doctor',
'class': 'form-control'
}
))
department = forms.ModelChoiceField(queryset=Department.objects.all(), widget=forms.Select(attrs=
{
'class': 'selectpicker',
'placeholder': 'Department',
}
))
class Meta:
model = Doctor
fields = ['name', 'department']
class NurseForm(forms.ModelForm):
name = forms.CharField(widget = forms.TextInput(attrs =
{
'placeholder': 'Add a New Nurse',
'class': 'form-control'
}
))
class Meta:
model = Nurse
fields = ['name']
class PatientForm(ModelForm):
name = forms.CharField(widget = forms.TextInput(attrs =
{
'placeholder': 'Add a New Nurse',
'class': 'form-control'
}
))
description = forms.CharField(widget = forms.TextInput(attrs =
{
'placeholder': "Describe the patient's symptoms",
'class': 'form-control'
}
))
department = forms.ModelChoiceField(queryset=Department.objects.all(), widget=forms.Select(attrs=
{
'class': 'selectpicker',
'placeholder': 'Select Department',
}
))
class Meta:
model = Patient
fields = ['name', 'description', 'department', 'care', 'status']
#Work Related
class WorkShiftForm(ModelForm):
class Meta:
model = WorkShift
fields = '__all__'
Nurse.html
{% extends 'lifesaver/main.html' %}
{% block content %}
{% for nurse in nurse %}
{{nurse.name}}
{{nurse.report_to}}
{{nurse.care}}
{{nurse.work_shift}}
{{department}}
{% endfor %}
{% endblock %}
In models.py, Nurse object has field 'sector' which is a Foreign Key to a Department record. So part of the problem is you're trying to output the wrong field name in your template as there is no actual department field defined on Nurse model.
Try these edits to views.py:
nurses = Nurse.objects.all()
then in your context: context = {..., 'nurses': nurses, ...}
Then in nurse.html:
{% for nurse in nurses: %}
...
{{ nurse.sector.name }}
{% endfor %}
That should at least get your nurse objects rendered in the template. But you have a potential issue in calling nurse.sector when that FK is defined in the Nurse model with null=True. So a better practice would be to define an accessor method in the Nurse model to check if sector is present before calling it's name, i.e.:
# in Nurse model
def department_name(self):
if self.sector_id:
return self.sector.name
else:
return '' # or some other default
Then you could edit nurse.html again replacing my code above with:
{% for nurse in nurses: %}
...
{{ nurse.department_name }}
{% endfor %}
This is just scratching the surface of how you could handle this but it hopefully answers your question and prevents a common error once you make these edits.
You'll also probably want to look into Django QuerySet API's select_related() and prefetch_related() methods to avoid N+1 query issues that are possible in your current code. See here and here for more background.
So for example, to avoid N+1, instead of calling nurses = Nurse.objects.all() instead do nurses = Nurse.objects.select_related('sector').all(). That will do a join to the Department model on the FK. This answer to one of the above N+1 questions has more details.
you need to pass a field and a value, e.g.
Nurse.objects.get('sector' = 'dentistry')
or if you want to display a specific nurses department you would use this in your template:
{{nurse.department.name}}

Update field in db in django from views with existing form, won't update because of "Integrity Error"

My first post, really newbie at programming. I am having issues to update a field in a form. I'll try to explain my best.
I have a Catalog class (products or services) with a couple fields, 2 of them must be unique.
models.py
class Catalogo(models.Model):
item = models.CharField(
max_length=100, help_text="Product or service name", unique=True
)
sku = models.CharField(max_length=50, help_text="Part Number", unique=True)
category = models.CharField(
max_length=15, choices=categoria, verbose_name="Category"
)
description = models.CharField(
max_length=200,
help_text="Item description",
verbose_name="DescripciĆ³n",
)
created = models.DateTimeField(auto_now_add=True, help_text="Created")
updated = models.DateTimeField(auto_now_add=True, help_text="Updated")
active = models.BooleanField(default=True)
class Meta:
verbose_name = "product and service"
verbose_name_plural = "products and services"
def __str__(self):
return self.item
Then i have a form to gather the information
forms.py
categories = [("Product", "Product"), ("Service", "Service")]
class NewProductForm(forms.Form):
item = forms.CharField(
widget=forms.TextInput(attrs={"class": "form-control"}),
label="Item",
max_length=100,
)
sku = forms.CharField(
widget=forms.TextInput(attrs={"class": "form-control"}),
label="Part number",
max_length=50,
)
category = forms.ChoiceField(
choices=categories,
label="Category",
)
description = forms.CharField(
widget=forms.Textarea(attrs={"class": "form-control"}),
label="Item description",
)
Now for the views...i created 2 functions, one for adding new product/service and one for updating
views.py
def new_prod_serv(request):
new_form = NewProductForm()
if request.method == "POST":
new_form = NewProductForm(request.POST)
if new_form.is_valid():
new_product = Catalogo(
item=new_form["item"].value(),
sku=new_form["sku"].value(),
category=new_form["category"].value(),
description=new_form["description"].value(),
)
new_product.save()
return redirect("products-services")
else:
print(new_form.errors)
context = {"formulario": new_form}
return render(request, "SkytechnosaApp/comercial/nuevoproducto.html", context)
def update_prod_serv(request, primarykey):
product_service = Catalogo.objects.get(id=primarykey)
item = product_service.item
sku = product_service.sku
category = product_service.category
description = product_service.description
form_data = {
"item": item,
"sku": sku,
"category": category,
"description": description,
}
form = NewProductForm(initial=form_data)
if request.method == "POST":
form = NewProductForm(request.POST, initial=form_data)
if form.is_valid():
form.save()
return redirect("products-services")
else:
print(form.errors)
context = {"form": form}
return render(request, "SkytechnosaApp/comercial/nuevoproducto.html", context)
The html works okay, the problem i'm facing is when i click on edit...it will populate the form with the information of the product or service i want to edit (that's fine), but then i make the changes on the comment field for example (just want to update comment) and then I get the error IntegrityError at /comercial/productos/nuevo
UNIQUE constraint failed: Comercial_catalogo.sku
It's like it's trying to create another product, because when i go back and i edit all the fields, and click on save, i see another product created, but I just wanted to update, rather than create a new product....what i am missing?
Thank you!
Your form code you pasted in your question is not complete (it's just a form.Form not a form.ModelForm, and yet you called form.save())
forms.py
class NewProductForm(forms.ModelForm):
item = forms.CharField(
widget=forms.TextInput(attrs={"class": "form-control"}),
label="Item",
max_length=100,
)
sku = forms.CharField(
widget=forms.TextInput(attrs={"class": "form-control"}),
label="Part number",
max_length=50,
)
category = forms.ChoiceField(
choices=categories,
label="Category",
)
description = forms.CharField(
widget=forms.Textarea(attrs={"class": "form-control"}),
label="Item description",
)
class Meta:
model = Catalogo
After that, if you want to update an instance (instead of creating one), you have to tell the ModelForm which instance it has to update:
view.py
def update_prod_serv(request, primarykey):
...
instance = Catalogo.objects.get(id=primarykey)
if request.method == 'POST':
form = NewProductForm(request.POST, instance=instance) # you don't need to use `initial` since
if form.is_valid():
form.save()
...
That said, it's generally best to have just ONE view for creating and updating. If you want to see how that works let me know.

How can I connect a model instance to a user in django?

Im looking to make it so the logged in user that creates a profile is linked to their guestprofile model when they create their profile.
When I create the guest profile while logged in, it successfully creates the guest profile, but in the guest profile admin screen there is no user connected to the guest profile model created. Instead there is a dropdown menu listing all users, which makes the connection process manual. Thanks.
Forms.py
class AddProfileForm(forms.ModelForm):
name = forms.CharField(max_length=50, widget=forms.TextInput(attrs={'class': 'form-control'}))
location = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'class': 'form-control'}))
summary = forms.CharField(max_length=500, widget=forms.Textarea(attrs={'class': 'form-control'}))
profile_pic = forms.ImageField()
class Meta:
model = GuestProfile
fields = ('name', 'location', 'summary', 'profile_pic')
Models.py
class GuestProfile(models.Model):
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
location = models.CharField(max_length=100)
summary = models.TextField(max_length=350)
profile_pic = models.ImageField(null=True, blank=True, upload_to="images/")
def __str__(self):
return str(self.user)
views.py
class AddProfileView(CreateView):
model = GuestProfile
form_class = AddProfileForm
template_name = 'profilemanip/addprofile.html'
success_url = reverse_lazy('home')
def get_object(self):
return self.request.user
Edit: I ended up solving my issue by changing my AddProfileView to the following:
def AddProfileView(request,*args,**kwargs):
form = AddProfileForm(request.POST or None)
if form.is_valid():
obj = form.save(commit=False)
obj.user = request.user
obj.save()
form = AddProfileForm()
return render(request, "profilemanip/addprofile.html", {"form": form})

Django model stoped working when adding more models

I have a view in which the user can edit their profile everything worked fine and everything was being updated (biography, first_name, username, email and profile-picture) but now that I added a new app that contains three views in which the user can upload, delete and like posts, the user update sistem stoped working for some reason just the (update, email, first_name)still worked. The update view calls 2 models, User that lets you edit(name, username and email) and Profile that lets you edit(bio and change the profile pictures) it looks like when I added the upload, delete and like functions mentioned before, the whole Profile model "disapeared" even tho is there. The error I am getting is RelatedObjectDoesNotExist User has no profile.
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profile_pic = models.ImageField(upload_to='profile_pics', null=True, blank=True, default='default.png')
bio = models.CharField(max_length=400, default=1, null=True)
connection = models.CharField(max_length = 100, blank=True)
follower = models.IntegerField(default=0)
following = models.IntegerField(default=0)
def __str__(self):
return f'{self.user.username} Profile'
class Post(models.Model):
text = models.CharField(max_length=200)
video = models.FileField(upload_to='clips', null=True, blank=True)
user = models.ForeignKey(User, related_name='imageuser', on_delete=models.CASCADE, default='username')
liked = models.ManyToManyField(User, default=None, blank=True, related_name='liked')
updated = models.DateTimeField(auto_now=True)
created =models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.text)
LIKE_CHOICES = (
('Like', 'Like'),
('Unlike', 'Unlike'),
)
class Like(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
value = models.CharField(choices=LIKE_CHOICES, default='Like', max_length=10)
def __str__(self):
return str(self.post)
views.py
def edit_profile(request):
if request.method == 'POST':
form = EditProfileForm(request.POST, instance=request.user)
form1 = UpdateProfileForm(request.POST, request.FILES, instance=request.user.profile)
if form.is_valid and form1.is_valid:
form.save()
form1.save()
return redirect('profile')
else:
form = EditProfileForm(instance=request.user)
form1 = UpdateProfileForm(instance=request.user)
args = {
'form': form,
'form1': form1,
}
return render(request, 'profile-edit.html', args)
urls.py
urlpatterns = [
path('<username>/', views.profile, name='profile'),
path('edit-profile', views.edit_profile, name='edit-profile'),
]
forms.py
class EditProfileForm(UserChangeForm):
class Meta:
model = User
fields = (
'first_name',
'username',
'email',
)
exclude = ('password',)
class UpdateProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = (
'bio',
'profile_pic',
)
If you need to see more code please let me know in the comments.
Add the following in your views before the if statement:
profile, created = Profile.objects.get_or_create(user=request.user)
You need the ", created" since the result of get_or_create will be a tuple not an object - the profile either already exists or must be created.
For your new problem, change the following line:
form1 = UpdateProfileForm(request.POST, request.FILES, instance=request.user.profile)
to:
form1 = UpdateProfileForm(request.POST or None, request.FILES, instance=request.user.profile)

Django ModelFormset name instead of ID in foreign key field

I'm having a problem with modelformset custom field so to speak. This is the code so far and it works fine:
models.py:
class Workplace(models.Model):
user = models.ForeignKey(User)
description = models.TextField(blank=True, null=True)
organization = models.ForeignKey(Organization)
position = models.CharField(max_length=250, null=True)
start = models.DateTimeField(null=True, blank=True)
end = models.DateTimeField(null=True, blank=True)
place = models.ForeignKey(Place, null=True, blank=True)
deleted = models.BooleanField(default=False)
forms.py:
class UserWorkplaceForm(forms.ModelForm):
class Meta:
model = Workplace
labels = {
'deleted': 'Delete this position'
}
def __init__(self, *args, **kwargs):
super(UserWorkplaceForm, self).__init__(*args, **kwargs)
self.fields['position'].required = True
self.fields['organization'].required = True
self.fields['start'].required = True
views.py:
def settings_workplace(request):
workplace_formset = modelformset_factory(Workplace,
form=UserWorkplaceForm,
fields=('user', 'position', 'organization', 'start', 'end', 'deleted'),
widgets={'user': forms.HiddenInput(),
'start': forms.DateInput(attrs={'class': 'workplace-date'}),
'end': forms.DateInput(attrs={'class': 'workplace-date'}),
'deleted': forms.CheckboxInput(),
'organization': forms.TextInput()
},
extra=0)
if request.method == "POST":
formset = workplace_formset(request.POST)
if formset.is_valid():
formset.save()
formset = workplace_formset(queryset=request.user.get_profile().workplace.filter(deleted=False))
else:
formset = workplace_formset(queryset=request.user.get_profile().workplace.filter(deleted=False))
context = {
'formset': formset
}
return render_to_response('accounts/settings_workplaces.html', context, RequestContext(request))
The 'organization' field is rendered as a Select HTML element. I can't have that because there are thousands of organizations in the database. What I'd like to do is display the Organization as a text field. That's what I did in the widgets part. However, that gives me the ID of the field, normally, not the name.
Is there a way for me to get both? I need the name for a nicer display and I need the ID in case editing happens (on a different field) because that field is required.
Any ideas?
Can you make it a ChoiceField where the 1st value is the ID of Organization, and the 2nd value is the Human Readable name of the Organization? That is my recommendation to handle this situation. Here is the documentation on setting 'choices' in Django:
https://docs.djangoproject.com/en/1.7/ref/forms/fields/#choicefield
https://docs.djangoproject.com/en/1.7/ref/models/fields/#choices

Categories

Resources