ModelMultipleChoiceField - cleaned_data have no value - python

I want to make simple blog with posts and tags, but i have a problem with adding tags from ModelMultipleChoiceField... after calling .is_valid(), cleaned_data should have selected tags but instead it is None.
print(form.cleaned_data)
returns:
{'description': u'xyz', 'title': u'xyz', 'haslo': u'', 'tags': None}
I have tried to change it to simple ChoiceField with initial choices from table but with same result.
My models:
class Tag(models.Model):
nazwa = models.CharField(max_length=24)
def __str__(self):
return self.nazwa
def __unicode__(self):
return self.nazwa
class Post(models.Model):
tytul = models.CharField(max_length=200)
skrocona_tresc = models.CharField(max_length=350, blank=True)
tresc = models.TextField(blank=True)
haslo = models.CharField(max_length=24, blank=True)
data = models.DateTimeField(auto_now=False, auto_now_add=True)
id_user = models.ForeignKey(User, on_delete=models.CASCADE)
tags = models.ManyToManyField(Tag)
Form:
class PostAddForm(forms.ModelForm):
title = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}),required=False)
password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'form-control'}),required=False)
description = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}),required=False)
tags = forms.ModelMultipleChoiceField(queryset=Tag.objects.all(), required=False)
class Meta:
model = Post
fields = [
'title',
'password',
'description',
'tags'
]
and view:
def add_post(request):
forma_PA = PostAddForm(request.POST or None)
if request.is_ajax():
if forma_PA.is_valid():
post = forma_PA.save(commit=False)
post.tresc = request.POST.get('html')
post = Post(tytul=forma_PA.cleaned_data.get('title'),
id_user_id=request.user.id,
skrocona_tresc=forma_PA.cleaned_data.get('description'),
tresc=request.POST.get('html'),
haslo=forma_PA.cleaned_data.get('password'),
)
post.save()
tagi = forma_PA.cleaned_data['tags']
print(forma_PA.cleaned_data)
if(tagi):
post.tags.add(tagi)
context = {
'form': forma_PA
}
return render(request, 'Blog/add_post.html', context)
i am just starting with Django ;/

Related

How to use accessors in Django?

I've read previous Q and docs, however still not able to make it work..
I have the following models:
class Process(models.Model):
class Meta:
verbose_name_plural = "Processes"
name = models.CharField(max_length=120)
description = models.CharField(max_length=4)
parent_process = models.ForeignKey('self', related_name="parent_process+", on_delete=models.PROTECT, blank=True, null=True, verbose_name="parent process")
process_activities = models.CharField(max_length = 2048, blank=True, verbose_name="process activites")
owner = models.ForeignKey(User, related_name="owner+", on_delete=models.PROTECT, blank=True, null=True, verbose_name="owner")
def __str__(self):
return "{}".format(self.name)
class ControlTest(models.Model):
history = AuditlogHistoryField()
name = models.CharField(max_length=120)
description = models.CharField(max_length=120)
Now I want to use an accessor to access the name of the process and display in a table (tables.py):
class controltestTable(tables.Table):
class Meta:
hoofdproces = tables.Column(accessor='process.name')
model = ControlTest
fields = ['id',"name", "hoofdproces", "sub_process", 'description', 'control', 'delegate', 'owner', 'reviewer1', 'reviewer2', 'reviewer1_r', 'reviewer2_r', 'delegate_r',
'owner_r', 'reviewer_status', 'status', 'history', 'comments', 'review_comments', 'due_date', 'review1_due_date', 'review2_due_date', 'documentation']
template_name = "django_tables2/bootstrap-responsive.html"
Views.py:
class ControlTestView(SingleTableView, FormView, SingleTableMixin, FilterView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
queryset = kwargs.pop('object_list', None)
if queryset is None:
self.object_list = self.model.objects.all()
context['controltests'] = ControlTest.objects.all()
return context
def post(self, request, *args, **kwargs):
form = self.get_form()
print(form)
if form.is_valid():
instance = form.save(commit=True)
instance.save()
print('valid')
return self.form_valid(form)
else:
print(form.errors)
return self.form_invalid(form)
template_name = "control/ControlTest.html"
model = ControlTest
form_class = ControlTestForm
table_class = controltestTable
success_url = reverse_lazy('controltest')
However, nothing gets displayed in the hoofdproces column :(
How is that possible? What am I doing wrong?
Please help!

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}}

ContentType matching query does not exist on django 2.2

I have been using django to build a Blog, and when i tried to make a comment section under each post i get the comment icon(where i can type some comments) but when i post the comment i get the error straight away, which is "ContentType matching query does not exist".
I tried to find the problem on stack and youtube but they said that solving this problem requires experience on dumpdata
class Comment(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1, null=True, on_delete=models.SET_NULL)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
content = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
objects = CommentManager()
def blog_post_detail_view(request, slug):
instance = get_object_or_404(BlogPost, slug=slug)
share_string = quote_plus(instance.content)
initial_data = {
'content_type': instance.get_content_type,
'object_id': instance.id
}
form = CommentForm(request.POST or None, initial=initial_data)
if form.is_valid():
c_type = form.cleaned_data.get('content_type')
content_type = ContentType.objects.get(model=c_type)
obj_id = form.cleaned_data.get('object_id')
content_data = form.cleaned_data.get('content')
new_comment, created = Comment.objects.get_or_create(
user=request.user,
content_type=content_type,
object_id=obj_id,
content=content_data
)
comments = instance.comments
template_name = 'blog/detail.html'
context = {
"object": instance,
'comments': comments,
'share_string': share_string,
'comment_form': form
}
return render(request, template_name, context)
from django import forms
from .models import Comment
class CommentForm(forms.Form):
content_type = forms.CharField(widget=forms.HiddenInput)
object_id = forms.IntegerField(widget=forms.HiddenInput)
content = forms.CharField(widget=forms.Textarea)
So basically i should have gotten my comment posted but instead i get that error:"ContentType matching query does not exist".
Your CommentForm should be a ModelForm, you can set the widgets in the Meta.widgets of the ModelForm
class CommentForm(forms.ModelForm):
class Meta:
model = Meta
fields = ('content_type', 'object_id', 'content')
widgets = {
'content_type': forms.HiddenInput,
'object_id': forms.HiddenInput,
}
This way form.cleaned_data.get('content_type') will contain the actual ContentType object so you don't have to do ContentType.objects.get

Django: How to filter ForeignKey choices by request.user with ModelFormSet

I just want to filter select field in a form, regarding a currently logged user. Every user has own categories and budgets - I want to display only a models related with a currently logged user. I've tried stuff with filtering before is_valid field, but with no result. Please, find my code below:
views.py
#login_required
def day_data_multiadd(request, no_of_lines=0):
no_of_lines = int(no_of_lines)
CostFormSet = modelformset_factory(Cost, form=DataAddForm, extra=no_of_lines)
if request.method == 'POST' and 'form' in request.POST:
formset = CostFormSet(request.POST, request.FILES)
if formset.is_valid():
for form in formset.forms:
f = form.save(commit=False)
f.user = request.user
f.save()
else:
formset = CostFormSet(queryset=Cost.objects.none())
if request.method == 'POST' and 'no_line' in request.POST:
generate_form = MultiaddGenerateForm(request.POST)
if generate_form.is_valid():
cd = generate_form.cleaned_data
return HttpResponseRedirect(reverse('core_sm:day_data_multiadd', args=(cd['formy'], )))
else:
generate_form = MultiaddGenerateForm()
return render(request, 'core_sm/costs/multi_add.html', {'formset': formset,
'no_of_lines': no_of_lines,
'generate_form': generate_form})
forms.py
class DataAddForm(forms.ModelForm):
class Meta:
model = Cost
fields = ['title', 'value', 'publish', 'category', 'budget']
exclude = ['user']
labels = {
'title': _('Tytuł'),
'value': _('Wartość'),
'publish': _('Data'),
'category': _('Kategoria'),
'budget': _('Budżet')
}
models.py
class Category(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
title = models.CharField(max_length=200)
publish = models.DateField(auto_now_add=True)
updated = models.DateField(auto_now=True)
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
def get_absolute_ur(self):
return reverse('core_sm:category_detail', args=[self.id])
class Budget(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
title = models.CharField(max_length=200, db_index=True)
value = models.DecimalField(decimal_places=2, max_digits=10)
publish = models.DateField(auto_now_add=True)
updated = models.DateField(auto_now=True)
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('core_sm:budget_detail', args=[self.id])
class Cost(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
budget = models.ForeignKey(Budget, related_name='cost')
category = models.ForeignKey(Category, related_name='cost')
title = models.CharField(max_length=200, db_index=True)
publish = models.DateField(default=timezone.now)
created = models.DateField(auto_now_add=True)
updated = models.DateField(auto_now=True)
value = models.DecimalField(max_digits=10, decimal_places=2)
class Meta:
ordering = ('-publish',)
def get_absolute_url(self):
return reverse('core_sm:stats_detail', args=[self.publish.year,
self.publish.strftime('%y'),
self.publish.strftime('%m'),
self.publish.strftime('%d')])
def __str__(self):
return self.title
According to the docs you can pass custom parameters to formsets forms.
class DataAddForm(forms.ModelForm):
class Meta:
model = Cost
fields = ['title', 'value', 'publish', 'category', 'budget']
exclude = ['user']
labels = {
'title': _('Tytuł'),
'value': _('Wartość'),
'publish': _('Data'),
'category': _('Kategoria'),
'budget': _('Budżet')
}
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
self.fields['category'].queryset = Category.objects.filter(user=user)
self.fields['budget'].queryset = Budget.objects.filter(user=user)
super(DataAddForm, self).__init__(*args, **kwargs)
views.py
formset = CostFormSet(queryset=Cost.objects.none(), form_kwargs={'user': request.user})

Update Django Model With Form Field

I am trying to update the quantity of my Inventory model using a Integer form field on the front end. I am able to add a new inventory item, but I want to update existing items. Here is my code:
FROM VIEWS.PY
def view_inventory(request, slug):
if request.method == 'POST':
quantity_add = addQuantity(request.POST)
if quantity_add.is_valid():
cd = quantity_add.cleaned_data
addq=Inventory(quantity = cd.get('quantity'))
addq.save()
quantity_add=addQuantity()
return render(request, 'inv/view_inventory.html', {
'item': get_object_or_404(Inventory.objects.all(), slug=slug),
'form' : quantity_add,
})
FROM MODELS.PY
class Inventory(models.Model):
quantity = models.IntegerField()
name = models.CharField(max_length=150, unique = True)
slug = models.SlugField(unique = True)
date = models.DateTimeField(auto_now_add=True)
description = models.CharField(max_length=250)
category = models.ForeignKey(Category, null=True, blank=True)
def __unicode__(self):
return self.name
#permalink
def get_absolute_url(self):
return ('view_inventory', None, { 'slug' : self.slug })
class Meta:
ordering = ['-date']
FROM URLS.PY
url(r'^(?P<slug>[\w\-]+)/$', 'inv.views.view_inventory', name='view_inventory'),
You only have to get the record and then update it:
def view_inventory(request, slug):
if request.method == 'POST':
quantity_add = addQuantity(request.POST)
if quantity_add.is_valid():
cd = quantity_add.cleaned_data
old_inventory = Inventory.objects.get(id=something here) #id or pk or whatever you want
old_inventory.quantity = cd.get('quantity')
old_inventory.save()
quantity_add=addQuantity()
return render(request, 'inv/view_inventory.html', {
'item': get_object_or_404(Inventory.objects.all(), slug=slug),
'form' : quantity_add,
})

Categories

Resources