Django Inline formsets with Form wizard¶ - python

I have two models, the second one have a ForeignKeyto the first one.
I'm using Django form wizzard to complet many regrouped fields in separated steps. The problem is when I arrive in the "TeamMember" step, where I'm supposed to let the user enter many members.
I was thinking to use Django Inline formset, but I can not implement it inside my formwizard, I get a
[u'ManagementForm data is missing or has been tampered with']
error when I try to display this step.
Here is my implementation, if some one have any idea, it would be really appreciated :).
Don't hesitate to contact me if you need more informations.
Thanks in advance for your help.
Yann
models.py
class Team(models.Model):
name = name = models.CharField(_(u'Team'), max_length=50))
class TeamMember(models.Model):
team = models.ForeignKey(Team)
first_name = models.CharField(_('First name'), max_length=50, blank=True, null=True)
first_name = models.CharField(_(u'Last name'), max_length=50, blank=True, null=True)
forms.py
class FundingRequestFormTeam(ModelForm):
class Meta:
model = TeamMember
exclude = ('team',)
fields = ('first_name', 'last_name')
TeamMemberFormSet = inlineformset_factory(Team, TeamMember)
urls.py
team_wizard = TeamWizard.as_view(FORMS_DATA, url_name='team_data_step')
urlpatterns = patterns('lending.views',
url(r'^file/(?P<step>.+)/(?P<project_id>[0-9\-]+)$', login_required(team_wizard), name='team_step_edit'),
)
views.py
FORMS_DATA = [("info", TeamFormInfo),
("team_members", TeamFormSet),
("social", FundingRequestFormSocial),
("documents", FundingRequestFormDocuments), ]
The rest of the view is something simple like in the documentation of the django form wizard
team_step_teammembers.html
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{% bootstrap_form form %}
{% endfor %}
{% else %}
{% bootstrap_form wizard.form %}
{% endif %}
</form>
Django version 1.7.3
Python version 2.7.5

Related

I Use for loop inside django template, but Django Generic editing views don't send data to template

I'm very new to django. I'm creating student attendance system. I can add classes and students in each class. But when it comes to check attendance I get stuck. My model, form, view and template for checking attendance are here:
models.py
choice_list = [(1, 'Present'), (2, "Absent")]
class AttendanceChecking(models.Model):
pupil = models.ForeignKey(ClassPupils, on_delete=models.CASCADE, related_name='pupil_attendance')
pupil_class = models.ForeignKey(SchoolClassess, on_delete=models.CASCADE, related_name='class_attendance')
teacher = models.ForeignKey(User, on_delete=models.CASCADE, related_name='responsible_attendance')
date = models.DateField()
mark_attendance = models.CharField(max_length=100, choices=choice_list, default='Present')
forms.py
choice_list = [(1, 'Present'), (2, "Absent")]
class AttendanceForm(forms.ModelForm):
mark_attendance = forms.ChoiceField(choices=choice_list)
class Meta:
model = AttendanceChecking
fields = ('mark_attendance',)
views.py
class AttendanceListView(LoginRequiredMixin, FormView):
form_class = AttendanceForm
context_object_name = 'classes'
model = SchoolClassess
template_name = 'app_school/attendance_list_view.html'
attendance_list_view.html
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% if user.is_authenticated %}
{% for pupil in classes.pupils.all %}
{{ pupil.pupil_lname }} {{pupil.pupil_fname}}
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="submit" name="">
{% endfor %}
{% endif %}
</form>
{% endblock %}
My purpose is creating a table which is the list of all students in a class and additional column for attendance as shown in image students list for checking attendance. when confirm button is clicked the data must be saved db table.
I tried, but when I use CreateView or FormView the data isn't showed in template with for loop.
If you can help me using generic editing views, I would be appreciated.

How to create a form field for every foreignkey in manytomany relationship in Django

I don't understand how to build a specific form in Django.
First of all here are my models:
class Category(models.Model):
name = models.CharField(max_length=200, unique=True)
class Assessment(models.Model):
name = models.CharField(max_length=200)
pub_date = models.DateTimeField(verbose_name=_('date published'), default=timezone.now)
classgroup = models.ForeignKey(ClassGroup, verbose_name=_('class'), on_delete=models.CASCADE, related_name='+')
category = models.ManyToManyField(Category, through='AssessmentScale', through_fields=('assessment', 'category'),)
total = models.IntegerField()
class AssessmentScale(models.Model):
assessment = models.ForeignKey(Assessment, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
value = models.IntegerField()
I would like to have a form like this html form. Actually, an assessment scale is sub-divided into different categories. So when I create an assessment, I'd like have a form field for each category allowing to add a value via my custom intermediary model AssessmentScale. But I really don't know the Django way to build this form. I read this post, which is similar I think, and someone advised the use of Inline model formsets. But I don't understand how to solve my problem with the latter. Could you help me?
I had no answer from Stackoverflow but a friend of mine solved my problem like this with inline formset:
# forms.py
class AssessmentForm(ModelForm):
class Meta:
model = Assessment
exclude = ('category',)
CategoryAssessmentFormSet = inlineformset_factory(
Assessment,
Assessment.category.through,
fields=['category', 'value'],
can_delete=False,
extra=Category.objects.count(),
max_num=Category.objects.count(),
widgets={'category': Select(attrs={'hidden': 'true'})}
)
in my view, to render the formset:
# views.py
initial = [{'category': category} for category in Category.objects.all()]
formset = CategoryAssessmentFormSet(initial=initial)
Select is hidden but I still want the name of the selected field, in my template:
# template
{{ formset.management_form }}
{% for form in formset %}
<div class="p-2">
{% for value,selected in form.fields.category.choices %}
{% if value == form.category.value %}{{ selected }}{% endif %}
{% endfor %}
{{ form.category }}
</div>
<div>
{{ form.value}}
</div>
{% endfor %}

To determine the user's role in the project

In my django website I have pages like 'project_list' and 'project_detail'. Every project has members with different roles (developer, manager, e.t.c.). I want to show different buttons depending on the current user's role in the project in template. I need ideas how to realise it. Lets say something like that in template:
{% if request.user.role_in_the_current_project = 'manager' %}
SOW SOMETHING
{% endif %}
models.py
class Project(models.Model):
name = models.CharField(max_length=250,)
slug = models.SlugField(max_length=250, unique_for_date='publication_date',)
*Other fields*
def get_absolute_url(self):
return reverse('project:project_detail', args=[self.slug])
class Membership (models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
ROLE_CHOICES = (
('manager', 'Manager'),
('developer', 'Developer'),
('business_analyst', 'Business analyst'),
('system_analysts', 'System analysts'),
)
role = models.CharField(max_length=20, choices=ROLE_CHOICES,)
view.py
def project_detail(request, slug):
project = get_object_or_404(Project, slug=slug, status='public')
return render(request, 'project/project_detail.html', {'project': project,})
project_detail.html
{% block content %}
<h1>{{ project.name }}</h1>
<p>{{ project.description|linebreaks }}</p>
{%endblock %}
urls.py
urlpatterns = [
url(r'^project/(?P<slug>[-\w]+)/$', project_detail, name='project_detail'),
]
You can use the concept of choices inside a model field and then by using these you can make decisions inside your templates (or to your views) to show appropriate content.
Let me know if you need more info on this.
[EDIT]: So, what you want is to check each time the value of role. Right?
In your views.py write:
project = get_object_or_404(Project, slug=slug, status='public')
memberships = project.membership_set.all()
Then because one project can have many Membership records you should iterate over the memberships to get each time the role.
So, in your template:
{% for membership in memberships %}
{% if membership.role == 'Manager' %} Do stuff here {% endif %}
{% endfor %}
Note that .role will give you back the second value of the ROLE_CHOICES sub-tuple which is capitalized, while the first one is that will be shown in the user if you use the function get_role_display()
Well, after all I found solusion. In view I add:
is_manager = project.membership_set.filter(user=request.user, role='Manager').exists()
Then in template I add:
{% if is_manager %}
<button>Create</button>
{% endif %}

How do I retrieve the values of selected checkboxes and show it in the template?

What am I doing ?
I'm training on a simple application where one can order a pizza and select his toppings, once the form submitted it shows the submitted queries in the template file.
What is the problem?
I'm having a really hard time showing the checked checkboxes from the form on the template file.
Here are my files :
models.py
class PickedDatas(models.Model):
name = models.CharField(max_length=255, blank=True, null=True)
class Picked(models.Model):
name = models.CharField(max_length=255)
picked = models.ManyToManyField(PickedDatas, blank=True)
forms.py
class CustomChoiceField(forms.ModelMultipleChoiceField):
def label_from_instance(self, obj):
return mark_safe('%s' % (obj.name))
class SomeForm(forms.ModelForm):
class Meta:
model = Picked
fields = ['name', 'picked']
picked = CustomChoiceField(queryset=PickedDatas.objects.all(), widget=forms.CheckboxSelectMultiple())
views.py
def some_view(request):
if request.method == 'POST':
form = SomeForm(request.POST)
if form.is_valid():
...
else:
form = SomeForm
return render(request, 'features.html', {'form':form, 'picked':Picked.objects.all()})
As for the template file, I'm using the for loop to show Picked models datas.
How can I achieve what I am trying to do ?
EDIT
here is the template file features.html
<h2>Enter your name and choose your pizza toppings</h2>
<form method='post'>
{% csrf_token %}
{{ form.as_p }}
<input type='submit' value='submit'>
</form>
{% for p in picked %}
<h2>Pizza For : <strong>{{ p.name }}</strong></h2>
<p>{{ p.picked }}</p>
{% endfor %}
it gives me this for {{ p.picked }} : pizza.PickedDatas.None
Picked.picked is a many to many field, so you need to loop through the options:
{% for picked in picked %}<!-- Note renamed variable to prevent clash with inner loop -->
<h2>Pizza For : <strong>{{ picked.name }}</strong></h2>
<p>{% for p in picked.picked.all %}{{ p }}{% endfor %}</p>
{% endfor %}

Filter on many-to-one model

I want to be able assign users vehicle registrations, and when the user logs into the website their home page should have a list of vehicle regs they own.
However I cannot get the model class to filter on the foreign key.
views.py
#login_required
def home(request):
# This is the basic user landing Page
veh_list = Vehicle.objects.filter(UserProfile.user)
return render(request, 'portal/home.html', {"veh_list": veh_list})
model.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class UserProfile(models.Model):
# This line is required. Links UserProfile to a User model instance.
user = models.OneToOneField(User)
# The additional attributes we wish to include.
compName = models.CharField(max_length = 20)
milkco = models.IntegerField()
# Override the __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.user.username
class Vehicle(models.Model):
vehid = models.CharField(max_length = 10)
company = models.ForeignKey(UserProfile, default = 1)
class Meta:
db_table = "vehicle"
def __unicode__(self):
return self.vehid
home.html
<!DOCTYPE html>
{% extends 'portal/base.html' %}
{% block title %}{{user.first_name }} {{ user.last_name }} Portal{% endblock %}
{% block content %}
<p>This is the home Page</p>
{% if user.is_authenticated %}
<h4>Optiload says... hello {{ user.first_name }} {{ user.last_name }}!</h4>
{% endif %}
{% for veh in veh_list %}
{{ veh}}
{% endfor %}
{% if user.is_authenticated %}
Logout<br/>
{% endif %}
{% endblock %}
Could someone help me with where I'm going wrong?
Thanks
Django offers a powerful and intuitive way to “follow” relationships in lookups, taking care of the SQL JOINs for you automatically, behind the scenes. To span a relationship, just use the field name of related fields across models, separated by double underscores, until you get to the field you want.
So your query should look like
veh_list = Vehicle.objects.filter(company__user=request.user)
Reference
You cannot make queries with unnamed arguments:
Vehicle.objects.filter(UserProfile.user)
In this case you want:
Vehicle.objects.filter(company=[your user])

Categories

Resources