Passing initial value in formset - python

Models
attendance_choices = (
('absent', 'Absent'),
('present', 'Present')
)
class Head_of_department(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
email = models.CharField(max_length=30)
def __str__(self):
return self.first_name
class Employee(models.Model):
first_name = models.CharField(max_length=200, unique=True)
last_name = models.CharField(max_length=200, unique=True)
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
email = models.EmailField(max_length=100)
def __str__(self):
return self.first_name + ' ' + self.last_name
class Attendance(models.Model):
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
employee = models.ForeignKey('Employee', on_delete=models.CASCADE, )
attendance = models.CharField(max_length=8, choices=attendance_choices, blank=True)
Views
class Attendancecreate(CreateView):
model = Attendance
fields = ['employee']
success_url = '/dashboard/'
def get_context_data(self,** kwargs):
context = super(Attendancecreate, self).get_context_data(**kwargs)
context['formset'] = AttendanceFormset(queryset=Attendance.objects.none(), instance=Head_of_department.objects.get(email=email), initial=[{'employee': employee} for employee inself.get_initial()['employee']])
context['attendance_form'] = Attendanceform()
email = self.request.user.email
hod = Head_of_department.objects.get(email=email)
context["employees"] = Employee.objects.filter(head_of_department =hod)
return context
def get_initial(self):
email = self.request.user.email
hod = Head_of_department.objects.get(email=email)
initial = super(Attendancecreate , self).get_initial()
initial['employee'] = Employee.objects.filter(head_of_department=hod)
return initial
def post(self, request, *args, **kwargs):
formset = AttendanceFormset(queryset=Attendance.objects.none(), instance=Head_of_department.objects.get(email=email), initial=[{'employee': employee} for employee inself.get_initial()['employee']))
if formset.is_valid():
return self.form_valid(formset)
def form_valid(self, formset):
instances = formset.save(commit=False)
for instance in instances:
instance.head_of_department = get_object_or_404(Head_of_department, email=self.request.user.email)
instance.save()
return HttpResponseRedirect('/dashboard/')
def form_invalid(self, formset):
print ('errors')
print (formset.errors)
Forms
class Attendanceform(ModelForm):
class Meta:
model = Attendance
fields = ('employee','attendance','hod')
AttendanceFormset = inlineformset_factory(Head_of_department,Attendance,fields=('attendance',))
Template
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{ form }}
<br><br>
{% endfor %}
Error
Below shown square brackets was printed in the console when I used print(formset.errors)
[]
How to pass employees as initial values for attendance model as shown below in the images, employees will be rendered and rendered values have to be passed as employee in attendance model.
Is there any workaround with modelformset or inlineformset ? I can't get it right with the views I have included in the question .

I was missing request.post ,
class Attendancecreate(CreateView):
...
def post(self, request, *args, **kwargs,):
formset = AttendanceFormset(request.POST,queryset=Attendance.objects.none(), instance=Head_of_department.objects.get(email=self.request.user.email), initial=[{'employee': employee} for employee in self.get_initial()['employee']])
if formset.is_valid():
return self.form_valid(formset)
Template
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{ form.employee.initial }} {{ form.employee}} {{ form.attendance }}
<br><br>
{% endfor %}

Related

Unable to get user.id from into django form

I'm unable to get user.school.id into the form shown below.
I have not been able to know the reason as to why this is happening.
Below is my forms.py
class StudentsForm(forms.ModelForm):
class Meta:
model = StudentsModel
fields = ("school","adm","name","kcpe","form","stream","gender","notes")
widgets = {
'school':forms.TextInput(attrs={"class":'form-control','value':'','id':'identifier','type':'hidden'}),
"adm":forms.TextInput(attrs={"class":'form-control'}),
"name":forms.TextInput(attrs={"class":'form-control'}),
"form":forms.Select(choices=class_forms,attrs={"class":'form-control'}),
"stream":forms.Select(choices=streams,attrs={"class":'form-control'}),
"gender":forms.Select(choices=gender, attrs={"class":'form-control'}),
}
Below is the script from the template where the id is to reflect.
<script>
document.getElementById('identifier').value = '{{ user.school.id }}';
</script>
And this is the Students model
class StudentsModel(models.Model):
school = models.ForeignKey(School,on_delete=models.CASCADE)
adm = models.CharField(max_length=200)
name = models.CharField(max_length=200)
form = models.ForeignKey(FormModel, on_delete=models.CASCADE)
stream = models.ForeignKey(StreamModel,on_delete=models.CASCADE)
gender = models.ForeignKey(GenderModel,on_delete=models.CASCADE)
def __str__(self):
return "%s | %s" % (self.name,self.adm)
Please help me out. If there's anything else I need to add let me know.
class School(models.Model):
name = models.CharField(max_length=100,default='default')
def __str__(self):
return str(self.name)
class User(AbstractUser):
school = models.ForeignKey(School, on_delete=models.DO_NOTHING, null=True, blank=True,default=1)
#role = models.CharField(max_length=10, choices=ROLES, blank=False, null=False)
is_student = models.BooleanField(default=False)
is_teacher = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
def __str__(self):
return (str(self.school) + ' | ' + self.username)
The view
class AddStudentView(LoginRequiredMixin,CreateView):
model = StudentsModel
form_class = StudentsForm
template_name = 'students.html'
success_url = reverse_lazy('students')
def get_context_data(self, *args, **kwargs):
streams = StreamModel.objects.filter(school=self.request.user.school)
students = StudentsModel.objects.filter(school=self.request.user.school)
forms = FormModel.objects.filter(school=self.request.user.school)
context = super(AddStudentView,self).get_context_data(*args, **kwargs)
context["streams"] = streams
context["students"] = students
context["forms"] = forms
return context
The form is here
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.media }}
{{ form.as_p }}
<button class="btn btn-primary">Add</button>
<span class="nav-item dropdown one " style="float:right">
Upload
</span>
</form>
I was able t solve this by creating two different views, one for createview and the other for listview. This worked.

Creating model instance in django

The general task: there is a list of the events which are displayed in a table view, the user clicks on the event and gets redirected to a single event page, which displays extra information about an event.
There is a button on this template that should give functionality to record some data of the event in the user-selected events list.
And I really don't get how to pass the event data into the form to create the user_event, maybe I chose the wrong way to create the instance of the model?
Models.py
class Event(models.Model):
LANGUAGE_CHOICES = [
('EN', 'English'), ('IT', 'Italian'), ('FR', 'French'), ('DE', 'German'), ('RU', 'Russian'), ]
STATUS_CHOICES = [('draft', 'Draft'), ('confirmed', 'Confirmed'), ]
FORMAT_CHOICES = [('live', 'Live'), ('online', 'Online'), ]
TOPIC_CHOICES = [('cataract', 'Cataract'),
('vitreo', 'Vitreoretinal'),
('optometry', 'Optometry'),
('multi', 'Multidisciplinary'),
('plastic', 'Plastic and Reconstructive surgery'),
('onco', 'Ocular oncology'),
('glaucoma', 'Glaucoma'),
('pediatrics', 'Pediatrics'), ]
title = models.CharField(
max_length=250, verbose_name='Event', db_index=True, default="Event")
slug = models.SlugField(max_length=250, unique_for_date='publish')
kol = models.ManyToManyField(
Kol, verbose_name='Presenter', db_index=True, blank=True)
body = models.TextField(verbose_name='Description', blank=True)
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
sponsor = models.CharField(
max_length=150, verbose_name='Sponsored by', default='')
organizer = models.CharField(
max_length=150, verbose_name='Organized by', default='')
topic = models.CharField(
max_length=100, choices=TOPIC_CHOICES, default='multi', verbose_name='Discipline')
status = models.CharField(
max_length=100, choices=STATUS_CHOICES, default='draft')
event_format = models.CharField(
max_length=50, choices=FORMAT_CHOICES, default='online', verbose_name='Format', db_index=True)
main_language = models.CharField(
max_length=50, choices=LANGUAGE_CHOICES, default='EN', verbose_name='Main language', db_index=True)
event_url = models.URLField(blank=True)
event_date_start = models.DateField(
verbose_name='Start date', db_index=True)
event_time_start = models.TimeField(default='09:00')
event_date_finish = models.DateField(
verbose_name='End date', auto_now=True)
event_time_finish = models.TimeField(default='18:00')
is_cme = models.BooleanField(
default=False, verbose_name='CME credits', db_index=True)
objects = models.Manager() # the default manager
published = PublishedManager() # published manager
futured = FutureManager() # future dates only
# follow check
users_follow = models.ManyToManyField(
settings.AUTH_USER_MODEL, related_name='events_liked', blank=True)
class Meta:
ordering = ('event_date_start',)
def __str__(self):
return self.title
def get_kols(self):
return "\n".join([str(p) for p in self.kol.all()])
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Event, self).save(*args, **kwargs)
#property
def _month(self):
return datetime.date(self.event_date_start).month
event_month = property(_month)
def get_absolute_url(self):
return reverse('events:event_detail', args=[self.publish.year,
self.publish.strftime(
'%m'),
self.publish.strftime(
'%d'),
self.slug])
class UserEvent(models.Model):
follower = models.ForeignKey(
User, related_name='user_events', on_delete=models.CASCADE)
my_event = models.ForeignKey(
Event, related_name='selected_event', on_delete=models.CASCADE)
title = models.CharField(
max_length=250, verbose_name='Event', db_index=True, default="Event")
event_url = models.URLField(blank=True)
event_date_start = models.DateField(
verbose_name='Start date')
event_date_finish = models.DateField(
verbose_name='End date')
class Meta:
ordering = ['-event_date_start']
def save(self, *args, **kwargs):
created = not self.pk
super().save(*args, **kwargs)
if created:
UserEvent.objects.create(user=self)
def __str__(self):
return self.title
forms.py
class UserEventForm(forms.ModelForm):
class Meta:
model = UserEvent
fields = ("title", "event_url",
"event_date_start", "event_date_finish")
detail.html with the button
{% extends 'bbase11.html' %} {% block title %} {{ event.title}} {% endblock %} {% block content %}
<div class="container">
<h1> {{ event.title }}</h1>
<p class='event_descr'> {{event.body}}</p>
<p> Presenting professionals {{event.get_kols}}</p>
<div>Organized by {{event.organizer}}</div>
<div>Sponsored by {{event.sponsor}}</div>
<div>
<form action= "{% url "events:add_event" %}" method = "POST" >
{{form.as_p}}
{% csrf_token %}
<input id='event' type='hidden' value = {{event.id}}>
<button type="submit" class="btn btn-outline-primary btn-sm m-0 waves-effect">Add to calendar</button></div>
</form>
</div>
{% endblock %}
views.py
def event_detail(request, year, month, day, event):
event = get_object_or_404(Event, slug=event,
status='confirmed',
publish__year=year,
publish__month=month,
publish__day=day)
return render(request, 'events/event/detail.html', {'event': event, 'add_event': add_event})
#login_required
def add_event(request):
if request.method == 'POST':
form = UserEventForm(request.POST or None)
if form.is_valid():
form.save()
messages.success(request, ("Event has been added"))
return redirect('event_list')
else:
messages.error(request, ("Event has not been added"))
return redirect('events:event_list')
else:
events = Event.futured.all()
return render(request, 'list.html', {'events': events})
Using a class based view instead of your function based one, you can override the get_initial method as follows:
class AddEventCreateView(CreateView):
model = Event
form_class = UserEventForm
template_name = 'your/template.html'
def get_initial(self):
initial = super().get_initial()
# Add your initial values here - for example
initial['title'] = 'Some value'
return initial
def form_valid(self, form):
self.object = form.save(commit=False)
# Do something here
return super().form_valid(form)
def get_success_url(self):
return reverse_lazy('your:url-name')
You can now pass as many initial values to your form as needed. See http://ccbv.co.uk/projects/Django/3.0/django.views.generic.edit/CreateView/#get_initial for details.
It looks like it may be a typo in the URL in the detail.html with the quotes.
Change this:
<form action= "{% url "events:add_event" %}" method = "POST" >
To this:
<form action="{% url 'events:add_event' %}" method="POST">

Render a list of foreign key in template

Models
class Head_of_department(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
email = models.CharField(max_length=30)
def __str__(self):
return self.first_name
class Employee(models.Model):
first_name = models.CharField(max_length=200, unique=True)
last_name = models.CharField(max_length=200, unique=True)
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
email = models.EmailField(max_length=100)
def __str__(self):
return self.first_name + ' ' + self.last_name
class Attendance(models.Model):
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
employee = models.ForeignKey('Employee', on_delete=models.CASCADE, )
attendance = models.CharField(max_length=8, choices=attendance_choices, blank=True)
Views
class Attendancecreate(CreateView):
model = Attendance
fields = ['employee']
success_url = '/dashboard/'
def get_context_data(self,** kwargs):
context = super(Attendancecreate, self).get_context_data(**kwargs)
email = self.request.user.email
hod = Head_of_department.objects.get(email=email)
context["objects"] = self.model.objects.filter(employee__head_of_department =hod)
print (context["objects"])
return context
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.head_of_department = get_object_or_404(Head_of_department, email=self.request.user.email)
self.object.save()
return super().form_valid(form)
Template
<div class="form-group">
{% for item in objects %}
{{ item.employee }}
{% endfor %}
</div>
The webapp has a login feature. The headofdepartment can mark the attendance . I want to render a list of employees under the respective logged in HOD and mark attendance . I want to do this in the same view .
I am unable to render the employees for logged in HOD.
I found the solution , I wrote views incorrectly.
model = Attendance
fields = ['employee']
success_url = '/dashboard/'
def get_context_data(self,** kwargs):
context = super(Attendancecreate, self).get_context_data(**kwargs)
email = self.request.user.email
hod = Head_of_department.objects.get(email=email)
context["objects"] = Employee.objects.filter(head_of_department =hod)
print (context["objects"])
return context
Template
{% for emp in objects %}
{{ emp.first_name }} {{ emp.last_name }}
{% endfor %}

how to get all records of related models and display dynamic data in django

I'm new in django.I want to retrieve all the records from related models and display the dynamic data in templates. I tried by using raw sql also but i could not display dynamic data templates.
models.py:
class NewRegistration(models.Model):
houseowner_name_en = models.CharField(max_length=30)
ward_no = models.ForeignKey(system_settings.models.Wardno)
contactno = models.CharField(max_length=30)
construction_type = models.ForeignKey(system_settings.models.ConstructionType)
taxpayer_id = models.CharField(max_length=30, blank=True, null=True)
cen = models.IntegerField()
is_forwarded = models.BooleanField(default=False)
class Application(models.Model):
registration_date = models.CharField(max_length=15)
building_use = models.ForeignKey(to=system_settings.models.BuildingUse)
building_category = models.CharField(max_length=30)
building_structure_category = models.ForeignKey(to=system_settings.models.BuildingStructureCategory)
building_storey = models.IntegerField(blank=True, null=True, default=0)
reg = models.ForeignKey(NewRegistration)
class Landowner(models.Model):
landowner_type = models.CharField(max_length=30)
lo_salutation = models.CharField(max_length=30)
lo_name_np = models.CharField(max_length=30)
lo_citizenship_issue_date = models.CharField(max_length=30)
reg = models.ForeignKey(NewRegistration)
views.py:
def export(request):
all_objects = NewRegistrationModel.objects.all()
# houseowner= all_objects.houseownerinfo_set.all()
app_all=Application.objects.all()
landinfo=Landinfo.objects.all()
return render(request, 'exports.html', {'all_objects': all_objects})
I did it like this.
views.py
def export(request):
all_objects = NewRegistration.objects.all()
return render(request, 'exports.html', {'all_objects': all_objects})
exports.html
# in template when displaying
{% for registration in all_objects %}
{{ registration.fiscalyear }}
{% for owner in registration.landowner_set.all %}
{{owner.landowner_type}}
{{owner.lo_wardno}}
{% endfor %}
{% endfor %}
you can use generic.ListView in your views.py file like that:
class Export(generic.ListView):
model = NewRegistration
template_name = "your_template_name.html"
def get_queryset(self):
return NewRegistration.objects.all()
def get_context_data(self, **kwargs):
context = super(Export, self).get_context_data(**kwargs)
context['app_all'] = Application.objects.all()
context['landinfo'] = Landingo.objects.all()
return context
you can accees the datas in your template like that {{ app_all }} or {{ landinfo }}.

Unable to automatically pick foreign key from modelform

I am working on a product app on Python 2.7 / Django 1.7.
I have a model for product namely 'product_profile' and I want to allow my customer (end user) to ask any thing regarding specific products using a form.
However I am unable to allow user to automatically select the product (foreign key) and the customer has to select from a drop-down which quite irrational. I have also assigned the foreign key in url-variable.
here is my code:
MODEL.PY
class ProductProfile(models.Model):
category = models.ForeignKey(Category)
brand = models.ForeignKey(Brand)
product_name = models.CharField(max_length=128)
model_name = models.CharField(max_length=128)
generation = models.CharField(max_length=128)
processor = models.CharField(max_length=128)
ram = models.DecimalField(max_digits=2, decimal_places=0)
hdd = models.DecimalField(max_digits=6, decimal_places=2)
optical_drive = models.CharField(max_length=128)
display = models.CharField(max_length=128)
card_reader = models.CharField(max_length=128)
blue_tooth = models.CharField(max_length=128)
web_cam = models.CharField(max_length=128)
warranty = models.CharField(max_length=128)
price = models.DecimalField(max_digits=9, decimal_places=2)
condition = models.TextField()
product_image = models.ImageField(upload_to=update_Product_image_filename)
post_date = models.DateTimeField(db_index=True, auto_now_add=True)
# Override th __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.product_name
class Customer_ps_contact(models.Model):
name = models.CharField(max_length=128)
email = models.EmailField(max_length=75)
subject = models.CharField(max_length=128 )
product = models.ForeignKey(ProductProfile)
message = models.TextField()
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format:
'+999999999'. Up to 15 digits allowed.")
phone_number = models.CharField(validators=[phone_regex], blank=True, max_length=15) # validators should be a
list
def __unicode__(self):
return self.name
FORM.PY
class Customer_ps_contactForm(forms.ModelForm):
class Meta:
model = Customer_ps_contact
product = forms.ModelChoiceField(queryset=ProductProfile.objects.all(),
widget=forms.HiddenInput())
fields = ('name','email', 'product','subject','message', 'phone_number')
VIEWS.PY
def product_inquiry(request, product_id):
product = ProductProfile.objects.get(pk=product_id)
if request.method == 'POST':
#form = Customer_ps_contactForm(request.POST, initial = {'product': product})
#form = Customer_ps_contactForm(initial = {'product': product.id})
form = Customer_ps_contactForm(request.POST)
if form.is_valid():
form_data_dict = form.cleaned_data
print form_data_dict['product']
mail_customer_enquriy(form_data_dict) # Function to send email to admin
thank_u_customer(form_data_dict) # Function to send email to customers
form = form.save(commit=False)
form.product = product
form.save()
return home(request)
else:
print ("form is not valid")
print (form.errors)
else:
form = Customer_ps_contactForm()
context_dict = {'form':form, 'product': product}
return render(request, 'product/product_inquiry2.html',context_dict)
URL Patterns
urlpatterns = patterns('',
url(r'^inquiry/(?P<product_id>\d+)/$', views.product_inquiry, name='price'), # Only relevent url given
)
Template : product_inquiry2.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block body_block %}
{% block title %}Product Inquiry{% endblock %}
<div class="row">
<div class="col-md-10 col-md-offset-1">
<h2 style="font-weight:bold">Enquiry regarding '{{product.product_name}}'</h2>
<hr>
<form id="contact_form" method="post" action=""/>
{% csrf_token %}
{{ form | crispy }}
<input class="btn btn-primary pull-right " type="submit" name="submit" value="Submit the Message" />
</form>
</div>
</div>
{% endblock %}
What should I do?
You know what the product is from the id in the url, so there's no need to include it in your form.
To check that the product exists in the database, you can use the get_object_or_404 shortcut.
def product_inquiry(request, product_id):
product = get_object_or_404(ProductProfile, pk=product_id)
Then leave out 'product' from your list of fields, and remove the ModelChoiceField with hidden input widget.
class Customer_ps_contactForm(forms.ModelForm):
class Meta:
model = Customer_ps_contact
fields = ('name','email','subject','message','phone_number')
You are already setting the product when you save it, but it would be clearer to use the variable name instance to make it clearer what's going on. If you change your mail_customer_enquriy and thank_u_customer methods to use the instance instead of cleaned_data, then you won't have to do anything with form.cleaned_data.
if form.is_valid():
instance = form.save(commit=False)
instance.product = product
instance.save()
mail_customer_enquriy(instance) # Function to send email to admin
thank_u_customer(instance) # Function to send email to customers
return home(request)

Categories

Resources