Django Model formset is partially working - python

I have normally just a simple question but I can't get it working.
I have a view where customers can add, delete or edit their addresses.
so the forms are generating, and I can open the edit_customer_form, the values are filled in because query set. But if I click on save, the form is posting, its hopping in the right loop: if 'edit_address' in request.POST: but I got the output from: print('ERROR', edit_address_form.errors)
that all fields are required and there are no inputs given. That is strange.
The HTML forms looks like:
<input type="text" name="form-0-Address_Firstname" value="Christopher" class="form-control" autofocus="" id="id_form-0-Address_Firstname">
The error says:
ERROR [{'CustomerID': ['Dette felt er påkrævet.'], 'ID': ['Dette felt er påkrævet.']}, {'Address_Firstname': ['Dette felt er påkrævet.'],
In my eyes the field name is different to the value given by the prefix, which is necessary. But how can I save the form and give the values to the form.
view.py:
customer_addresses = CustomerAddresses.objects.filter(CustomerID=customer)
AddressFormSet = modelformset_factory(CustomerAddresses, form=CustomerAddressesForm, extra=0)
formset = AddressFormSet(queryset=customer_addresses, form_kwargs={'user': User.ID})
if request.method == 'POST':
if 'add_address' in request.POST:
add_address_form = CustomerAddressesForm(User.ID, request.POST)
if add_address_form.is_valid():
add_address_form.save()
if 'edit_address' in request.POST:
address_id = request.POST.get('id_Address')
address_data = CustomerAddresses.objects.get(pk=address_id)
edit_address_form = AddressFormSet(request.POST, queryset=customer_addresses, form_kwargs={'user': User.ID})
print('ERROR', edit_address_form.errors)
messages.error(request, 'ERROR')
if edit_address_form.is_valid():
instances = edit_address_form.save(commit=False)
for instance in instances:
instance.save()
return redirect('addresses')
if 'delete_customer_address_id' in request.POST:
delete_customer_address_id = request.POST.get('delete_customer_address_id')
request.session['delete_customer_address_id'] = delete_customer_address_id
return redirect('delete-customer-address')
if 'register_customer' in request.POST:
register_form = CustomerAddressesForm(user=user_id)
if register_form.is_valid():
customer = register_form.save(commit=False)
customer.UserID = user_id
customer.save()
# You can redirect to a success page or login the user directly
redirect(request.META.get('HTTP_REFERER'))
else:
add_address_form = CustomerAddressesForm(user=User.ID)
and my form:
class CustomerAddressesForm(forms.ModelForm):
Title = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control mb-3', 'autofocus': True}),
required=False)
Address_Firstname = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control', 'autofocus': True}))
Address_Lastname = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control', 'autofocus': True}))
Zip = forms.IntegerField(
widget=forms.TextInput(attrs={'class': 'form-control', 'maxlength': '5', 'data-toggle': 'maxlength'}),
label='Postnummer')
City = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control', 'autofocus': True}))
Address_Company = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control', 'autofocus': True}),
required=False)
Street = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control', 'autofocus': True}), required=False)
Country = forms.ModelChoiceField(widget=forms.Select(attrs={'class': 'form-select'}),
queryset=CountryList.objects.values_list('countryname', flat=True).order_by(
'code'), initial='Denmark', to_field_name='countryname')
Is_Default_Shipping_address = forms.BooleanField(
widget=forms.CheckboxInput(attrs={'class': 'form-check-input', 'id': 'customSwitch4'}), initial=False,
required=False)
Is_Default_Billing_address = forms.BooleanField(
widget=forms.CheckboxInput(attrs={'class': 'form-check-input', 'id': 'customSwitch3'}), initial=False,
required=False)
class Meta:
model = CustomerAddresses
fields = ['Title', 'Address_Firstname', 'Address_Lastname', 'Zip', 'City', 'Address_Company', 'Country',
'Is_Default_Shipping_address', 'Is_Default_Billing_address', 'Address_CustomerSalutation',
'CustomerID', 'Street']
def __init__(self, user, *args, **kwargs):
super(CustomerAddressesForm, self).__init__(*args, **kwargs)
self.fields['Address_CustomerSalutation'] = forms.ModelChoiceField(
widget=forms.Select(attrs={'class': 'form-select mb-3'}),
queryset=Salutation.objects.filter(UserID_id=user), empty_label=None)

I found the the problem, it was a misunderstand, I created for every instance a own <form> tag, this was not working because
{{ formset.management_form }}
have to be in the form for all formsets.
I tried also
{{ form.instance.management_form }}
and
{{ form.management_form }}
in the {% for form in formset %} loop, but it was not working. I also excluded the CustomerID field because it will not be changed by the customer or the admin.

Related

Choices in django form

in my form i want to select department from 2 options: some object(every time only one) and None.
my form.py
class TeamGoalForm(ModelForm):
def __init__(self, *args, **kwargs):
employees = kwargs.pop('employees')
department = kwargs.pop('department')
super().__init__(*args, **kwargs)
self.fields['employees'].queryset = employees
self.fields['department'].choices = [(1, department), (2, None)]
self.fields['department'].initial = [1]
class Meta:
model = TeamGoal
fields = ('team_goal_title','department','employees', 'team_goal_description', 'gpd_year','team_factor_0','team_factor_1','team_factor_2','team_factor_3','team_factor_weight')
widgets = {
'team_goal_title': forms.TextInput (attrs={'class':'form-control', 'placeholder':'Enter the title of goal'}),
'department': forms.Select (attrs={'class': 'form-control', 'placeholder':'Select department'}), }
in my view.py I have had:
if request.method == 'POST':
form = TeamGoalForm(request.POST, employees=employees, department=department)
if form.is_valid():
form.save()
Here my department is an object.
How to implement something like this, 'cos my solution does't work?
You are not showing much of the code, but here is more or less how the different files should look like, hope this helps:
**#models.py**
from django.db import models
class department(models.Model):
# department fields
pass
class TeamGoal(models.Models):
...
deparment = models.ForeignKey(department, on_delete=models.CASCADE)
...
**#forms.py**
from django.forms import ModelForm
from django import forms
class TeamGoalForm(ModelForm):
class Meta:
model = TeamGoal
fields = (
'team_goal_title',
'department',
'employees',
'team_goal_description',
'gpd_year',
'team_factor_0',
'team_factor_1',
'team_factor_2',
'team_factor_3',
'team_factor_weight'
)
deparments = deparment.objects.all()
widgets = {
'deparments': forms.Select(choices=deparments,
attrs={
'class': 'form-control',
'placeholder':'Select department'
})
**#views.py**
from .forms import TeamGoalForm
def AddTeamGoalForm(request):
context = {
'TeamGoalForm': TeamGoalForm,
}
if request.method == 'POST':
addTeamGoalForm = TeamGoalForm(request.POST)
if addTeamGoalForm.is_valid():
newTeamGoalForm = addTeamGoalForm.save()
return redirect('/')
else:
return render(request, '/TeamGoalForm.html', context)
**# TeamGoalForm.html**
<form method="POST">
{% csrf_token %}
{{ TeamGoalForm}}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
NOTE: you may need to adjust it based on the code you've already writen, but hopefully this leads close to a solution.

Error while try to make widget to the form in django

I get an error when I try to add a widget to the form.
The error:
File "C:\Users\lib\site-packages\django\forms\fields.py", line 558, in __init__
super().__init__(**kwargs)
TypeError: __init__() got an unexpected keyword argument 'attrs'
The model
class Video(models.Model):
author = models.ForeignKey(Account, on_delete=models.CASCADE)
video = models.FileField(upload_to='post-videos')
title = models.CharField(max_length=100)
description = models.TextField(null=True, blank=True)
video_poster = models.ImageField(max_length=255, upload_to='post-videos')
The views
def VideosUploadView(request, *args, **kwargs):
all_videos = Video.objects.all()
V_form = Video_form()
video_added = False
if not request.user.is_active:
# any error you want
return redirect('login')
try:
account = Account.objects.get(username=request.user.username)
except:
# any error you want
return HttpResponse('User does not exits.')
if 'submit_v_form' in request.POST:
print(request.POST)
V_form = Video_form(request.POST, request.FILES)
if V_form.is_valid():
instance = V_form.save(commit=False)
instance.author = account
instance.save()
V_form = Video_form()
video_added = True
contex = {
'all_videos': all_videos,
'account': account,
'V_form': V_form,
'video_added': video_added,
}
return render(request, "video/upload_videos.html", contex)
The form
class Video_form(forms.ModelForm):
class Meta:
model = Video
fields = ('title', 'description', 'video', 'video_poster')
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'description': forms.TextInput(attrs={'class': 'form-control'}),
'video': forms.FileField(widget=forms.FileInput(attrs={'class': 'form-control'})),
'video_poster': forms.ImageField(attrs={'class': 'form-control'}),
}
You must assign valid widget in the Video_form:
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'description': forms.TextInput(attrs={'class': 'form-control'}),
'video': forms.FileInput(attrs={'class': 'form-control'}),
'video_poster': forms.ClearableFileInput(attrs={'class': 'form-control'}),
}
forms.FileField and forms.ImageField are fields not widgets.
My problem was style the form fields and I explored a good way to styling the fields by add the field name after the form name
Like this way
<span class="control-fileupload">
<!--here what I mean--> {{ V_form.video }}
<label for="file1" class="text-left">click to choose a Video on your computer.</label>
</span>
and here also
<label>{{ V_form.title }}</label>

Why i get this value

I want to when i click on the user discharge button it will go to the page and the all user information take automatically. But i cannot get this value. Here is the image in the discharge button i click but its shows like this.
Here is my code : views.py
def discharge_view(request, pk):
form = DischargForm()
if request.method == 'POST':
form = DischargForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Successfull')
return redirect('discharge-patient')
context = {
'form': form,
}
return render(request, 'hospital/discharge.html', context)
forms.py :
class DischargForm(forms.ModelForm):
class Meta:
model = PatientDischarge
fields = ('assign_doctor', 'admitted', 'release_date', 'medicine_cost', 'other_charge')
widgets = {
'assign_doctor': forms.Select(attrs={'class': 'form-control'}),
'admitted': forms.Select(attrs={'class': 'form-control'}),
'release_date': forms.TextInput(attrs={'class': 'form-control'}),
'medicine_cost': forms.TextInput(attrs={'class': 'form-control'}),
'other_charge': forms.TextInput(attrs={'class': 'form-control'}),
}
models.py
class PatientDischarge(models.Model):
assign_doctor = models.ForeignKey(Doctor, on_delete=models.CASCADE)
admitted = models.ForeignKey(Admitted, on_delete=models.CASCADE)
release_date = models.DateField(auto_now_add=False)
medicine_cost = models.IntegerField(null=True)
other_charge = models.IntegerField()
def __str__(self):
return self.admitted.patient_name if all([self.admitted, self.admitted.patient_name]) else 0
def days_count(self):
return self.release_date - self.admitted.admited_date if all([self.admitted, self.admitted.admited_date]) else 0
def room_bill(self):
return self.days_count() * self.admitted.room_service if all([self.admitted, self.admitted.room_service]) else 0
def total_bill(self):
return self.room_bill().days + self.medicine_cost + self.other_charge
discharge.html
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{% for fields in form %}
<div class="form-group"></div>
{{ fields.label_tag }}
{{ fields }}
{% endfor %}
<br>
<input type="submit" value="Submit">
To pass an instance to the form you can do this form = DischargForm(instance=<DischargeInstance>) and the template will have pre-filled values in the form as per the instance.
Can you provide your models.py.

Django: How can i validate the combination existance of two fields?

I'm using Django Model Form. Can anyone help me validate those fields to get field error using clean()?
The Name field cannot be repeated in the same office, only in a different one.
form.py
class CreateSalesRepForm(forms.ModelForm):
class Meta:
model = CreateSalesRep
fields = ['name', 'office']
widgets = {
'office': forms.Select(attrs={'class': 'form-control', 'placeholder': 'Enter Office'}),
'name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter Name'})
}
UPDATED (form.py) --- Here is the solution, you can use this codes to validate both insert and update form.
def clean(self):
cleaned_data = super().clean()
office = cleaned_data.get("office")
name = cleaned_data.get("name")
duplicates = CreateSalesRep.objects.filter(office=office, name=name)
if (self.instance.pk and None):
duplicates = duplicates.filter(pk=self.instance.pk)
if duplicates.exists():
msg = "Name already exist in office selected"
self.add_error('name', msg)
self.add_error('office', msg)
view.py
def create_salesrep(request):
if request.method == "POST":
form = CreateSalesRepForm(request.POST or None)
if form.is_valid():
form.save()
messages.success(request, 'Successfully Saved!', 'alert-success')
return redirect('sales_rep')
else:
return render(request, 'salesrep/create_salesrep.html', {'form':form})
else:
form = CreateSalesRepForm()
context = {'form':form}
return render(request, 'salesrep/create_salesrep.html', context)
def update_salesrep(request, pk):
srep = CreateSalesRep.objects.get(id=pk)
form = CreateSalesRepForm(instance=srep)
if request.method == "POST":
form = CreateSalesRepForm(request.POST or None, instance=srep)
if form.is_valid():
form.save()
messages.success(request, 'Successfully Updated!', 'alert-success')
return redirect('sales_rep')
else:
return render(request, 'salesrep/update_salesrep.html', {'form':form})
else:
form = CreateSalesRepForm(instance=srep)
return render(request, 'salesrep/update_salesrep.html', {'form':form})
You can validate in the forms:
class CreateSalesRepForm(forms.ModelForm):
class Meta:
model = CreateSalesRep
fields = ['name', 'office']
def clean(self):
cleaned_data = super().clean()
office= cleaned_data.get("office")
name = cleaned_data.get("name")
duplicates = CreateSalesRep.objects.filter(office=office, name=name)
if self.instance.pk:
duplicates = duplicates.filter(pk=self.instance.pk)
if duplicates.exists():
raise forms.ValidationError('Name already in office')
That being said, you could enforce this in the model/db level as well by adding the following to your CreateSalesRep model:
class CreateSalesRep(models.Model):
...
class Meta:
unique_together = ['office', 'name']
You can try following inside your model class
class Meta:
unique_together = [('office', 'name')]

Django permissions in checkbox form

I have a template in which I edit all the basic fields of a model User.
Now I want to have a form in which there will be displayed all available permissions in a checkbox-like style. The ones already assigned to the User should already be checked.
I have a form.py, with a form for editing User, but have not completed the permissions form.
class UserSettingsForm(forms.ModelForm):
class Meta:
model = User
fields = (
'username',
'first_name',
'last_name',
'email',
'urnik',
'ure_na_teden',
'rfid',
'oddelek',
'status_zaposleni',
)
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(UserSettingsForm, self).__init__(*args, **kwargs)
instance = getattr(self, 'instance', None)
self.fields['username'].disabled = True
def save(self):
user = super(UserSettingsForm, self).save()
return user
class UserPermissonsForm(forms.ModelForm):
class Meta:
model = Permission
fields = (
'name',
'content_type',
'codename',
)
And a views.py:
#login_required
def uporabnik_uredi(request, username=None):
user = get_object_or_404(User, username=username)
uporabnik_form = UserSettingsForm(request.POST or None,request=request, instance=user)
permissions = [(p.id, p.name) for p in Permission.objects.filter(user=user)]
data = {
'uporabnik' : user,
'form' : uporabnik_form,
'from': request.GET.get('from', None),
'permissions' : permissions,
}
if request.POST:
if uporabnik_form.is_valid():
user = uporabnik_form.save()
next = request.GET.get('next', None)
return redirect(next)
return render(request, "sifranti/uporabniki/uredi.html", data)
And also a template, just to see which current permissions are assigned to the user:
<div class="">
{% for id, name in permissions %}
{{ id }} - {{ name }} <br>
{% endfor %}
</div>
This is how I do but i use a MultipleSelect, I guess you can apply some of this to checkboxes.
class EditUserForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(EditUserForm, self).__init__(*args, **kwargs)
def get_label(obj):
permission_name = str(obj).split('|')[2].strip()
model_name = permission_name.split(' ')[2].strip()
return '%s | %s' % (model_name.title(), permission_name)
User = get_user_model()
content_type = ContentType.objects.get_for_model(User)
self.fields['user_permissions'].queryset = Permission.objects.filter(content_type=content_type)
self.fields['user_permissions'].widget.attrs.update({'class': 'permission-select'})
self.fields['user_permissions'].help_text = None
self.fields['user_permissions'].label = "Label"
self.fields['user_permissions'].label_from_instance = get_label
def save(self, commit=True):
user_instance = super(EditUserForm, self).save(commit)
user_instance.save()
user_instance.user_permissions.set(self.cleaned_data.get('user_permissions'))
return user_instance
class Meta:
model = get_user_model()
fields = ['email', 'first_name', 'last_name', 'user_permissions']
widgets = {
'email': forms.EmailInput(attrs={'class': 'form-control', 'style': 'width: 300px;'}),
'first_name': forms.TextInput(attrs={'class': 'form-control', 'style': 'width: 300px;'}),
'last_name': forms.TextInput(attrs={'class': 'form-control', 'style': 'width: 300px;'}),
'user_permissions': forms.SelectMultiple(attrs={'style': 'width: 350px; height: 200px;'})
}
Hope this helps, good luck!

Categories