Django formset for models without foreign key - django

I'm trying to use formset to create connections between my Neo4j nodes. These models have been constructed using the django-neomodel package. They aren't related using foreign keys, but since this isn't an inline formset that shouldn't matter, right?
models.py
class Person(DjangoNode):
uid = UniqueIdProperty()
name = StringProperty(max_length=50)
created_at = DateTimeProperty(default=datetime.now)
friends = RelationshipTo('Friend', 'FRIENDED', model=FriendRel)
# DjangoNode class must have a Meta class and documentation specifies 'django_node'
class Meta:
app_label = 'django_node'
class FriendRel(DjangoRel):
created_at = DateTimeProperty(default=datetime.now)
class Meta:
app_label = 'django_rel'
forms.py
class PersonForm(forms.ModelForm):
class Meta:
model = Person
# don't need fields for automatically assigned keys like `uid` and `created_at`
fields = ['name']
class FriendRelForm(forms.ModelForm):
class Meta:
model = FriendRel
exclude = () #"creating ModelForm without either 'fields' || 'exclude' attribute is prohibited"
FriendRelFormSet = formset_factory(FriendRelForm, extra=1)
form.html
<div>
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<table class="table">
{{ friends.management_form }}
{% for form in friends.forms %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tr class="{% cycle "row1" "row2" %} formset_row">
{% for field in form.visible_fields %}
<td>
<!-- Include the hidden fields in the form -->
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<input type="submit" value="Save"/>
</form>
</div>
I'm expecting a "friend" formset to appear in the rendered form, but am not quite sure how to get it there. If I add the following I get an error:
class FriendRelForm(forms.ModelForm):
class Meta:
model = FriendRel
exclude = ()
fields = ['friends']
***ERROR*** django.core.exceptions.FieldError: Unknown field(s) (friends) specified for FriendRel

Related

Django template does not output multiple forms and save to modelform

the issue is that template does not output multiple forms and save to Assumptions modelform. I am trying to save input from multiple forms by adding different names from template to Assumptions.Name field in Assumptions model. However, this approach does not work for some reason. Advise how to solve it would be highly appreciated. Thank you in advance.
views.py
from django.shortcuts import render
from .forms import modelformset_factory, AssumptionsForm
from .models import Assumptions
def get_assumptions(request):
if request.method == 'POST':
if 'name' in request.POST:
formset = modelformset_factory(Assumptions, form = AssumptionsForm, extra = 5)
if formset.is_valid():
print('valid form')
for form in formset:
print('Looping forms')
assumptions = form.save(commit='False')
assumptions.Name = 'name'
assumptions.save()
formset = modelformset_factory(Assumptions, form = AssumptionsForm, extra = 5)
return render(request, 'assumptions.html', {'formset': formset})
assumptions.html
{% for name in "AB" %}
<div class="form">
<form action="" method="post">
{% csrf_token %}
{{ formset.management_form }}
{{ formset.non_form_errors.as_ul }}
<table id="formset" class="form">
{% for form in formset.forms %}
{% if forloop.first %}
<thead><tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr></thead>
{% endif %}
<tr class="{% cycle 'row1' 'row2' %}">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<input type="submit" name="{{name}}" value="save" />
</form>
</div>
{% endfor %}
models.py
from django.db import models
from django.forms import ModelForm
class Assumptions(models.Model):
Worst = models.FloatField(null=True, blank=True, default=None)
Base = models.FloatField(null=True, blank=True, default=None)
Best = models.FloatField(null=True, blank=True, default=None)
Name = models.TextField(null=True, blank=True, default=None)
forms.py
from django import forms
from django.forms import modelformset_factory, ModelForm
from .models import Assumptions
class AssumptionsForm(ModelForm):
class Meta:
model = Assumptions
fields = ['Worst', 'Base', 'Best']
exclude = ['Name']

Django looping formsets cause ValidationError in management form

I am trying to output two same forms and save them to database with different prefix. I used this post https://collingrady.wordpress.com/2008/02/18/editing-multiple-objects-in-django-with-newforms/ as an example. However I get validation error that management form is being tampered with. Could you please kindly advise how to solve it? Thank you.
Also is it possible to filter database by the prefix in this case if i want to retrieve the data later for analysis.
VIEWS.PY
from django.shortcuts import render
from .forms import modelformset_factory, AssumptionsForm
from .models import Assumptions
model_names = ['Form1', 'Form2']
def get_assumptions(request):
AssumptionsFormset = modelformset_factory(
Assumptions, form=AssumptionsForm, extra=5)
if request.method == 'POST':
formsets = [AssumptionsFormset(request.POST, prefix=thing) for thing in model_names]
if all([formset.is_valid() for formset in formsets]):
for formset in formsets:
for form in formset:
form.save()
else:
formsets = [AssumptionsFormset(request.POST, prefix=thing) for thing in model_names]
return render(request, 'assumptions.html', {'formsets': formsets})
ASSUMPTIONS.HTML
<div class="form">
<form action="" method="post">
{% csrf_token %}
{% for formset in formsets %}
{{ formset.management_form }}
{{ formset.non_form_errors.as_ul }}
<h1>{{formset.prefix}}</h1>
<table id="formset" class="form">
{% for form in formset.forms %}
{% if forloop.first %}
<thead><tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr></thead>
{% endif %}
<tr class="{% cycle 'row1' 'row2' %}">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<input type="submit" value="Submit">
{% endfor %}
</form>
</div>
MODELS.PY
from django.db import models
from django.forms import ModelForm
class Assumptions(models.Model):
Worst = models.FloatField(null=True, blank=True, default=None)
Base = models.FloatField(null=True, blank=True, default=None)
Best = models.FloatField(null=True, blank=True, default=None)
FORMS.PY
from django import forms
from django.forms import modelformset_factory, ModelForm
from .models import Assumptions
class AssumptionsForm(ModelForm):
class Meta:
model = Assumptions
fields = '__all__'
You are trying to initialize the formsets with request.POST on GET requests, which of course can't work.
Replace the second
formsets = [AssumptionsFormset(request.POST, prefix=thing) for thing in model_names]
with
formsets = [AssumptionsFormset(prefix=thing) for thing in model_names]

Django dynamically filter list in template

I have a page which lists all of the athletes that a certain coach has. Coaches, however, can have multiple teams and I am trying to allow them to select a team from a dropdown at the top of the page and dynamically filter the list of athletes to only show those on the selected team.
My template:
<table class='table'>
<tr>
<td><h3>Team</h3></td>
<td><h3>First Name</h3></td>
<td><h3>Last Name</h3></td>
<td><h3>Email</h3></td>
</tr>
{% for athlete in athletes %}
{% if not athlete.coach_ind %}
<tr><td>
{% for team in athlete.team.all %}
{{ team.school }} {{ team.mascot }} {{ team.sport }}
{% endfor %}
</td>
<td>{{ athlete.user.first_name }}</td>
<td>{{ athlete.user.last_name }}</td>
<td>{{ athlete.user.email }}</td>
</tr>
{% endif %}
{% endfor %}
</table>
My view:
teams_list = request.user.profile.team.all()
athletes = UserProfile.objects.filter(team__in=teams_list).order_by('team','user__last_name')
I am able to successfully get the correct list of all athletes and their information, I'm just not sure how to create a dynamic filter to show only by team.
You can use django-filter for it https://github.com/alex/django-filter.
Example from documentation:
Model
class Product(models.Model):
name = models.CharField(max_length=255)
manufacturer = models.ForeignKey(Manufacturer)
Filter
class ProductFilter(django_filters.FilterSet):
class Meta:
model = Product
fields = ['manufacturer']
View
def product_list(request):
f = ProductFilter(request.GET, queryset=Product.objects.all())
return render_to_response('my_app/template.html', {'filter': f})
Template
{% block content %}
<form action="" method="get">
{{ filter.form.as_p }}
<input type="submit" />
</form>
{% for obj in filter %}
{{ obj.name }}<br />
{% endfor %}
{% endblock %}
Another app to those for this type of "chained" selection is selectable (http://django-selectable.readthedocs.io/en/latest/advanced.html#chained-selection). You have to put some additional javascript to the template, though.

Saving from a django-leaflet widget

I am having trouble saving the point coordinates from a django-leaflet form. I can display the leaflet widget and add point markers but when I submit the form no geometry is sent. I know this from looking at what is posted back to the server in FireBug.
e.g.
csrfmiddlewaretoken 3fOhKMkrlMqIvQfqsq6Myx9agpsif2aQ
geom
name test
submit Save
Here is the code:
forms.py
from leaflet.forms.fields import MultiPointField
class LocationForm(forms.ModelForm):
geom = MultiPointField()
class Meta:
model = Location
fields = ['name', 'geom']
models.py
from leaflet.forms.fields import MultiPointField
class Location(models.Model):
locationid = models.IntegerField(primary_key=True)
name = models.CharField(max_length=256)
geom = MultiPointField()
def __unicode__(self):
return self.name
template file
{% load leaflet_tags %}
{% leaflet_js plugins="forms" %}
{% leaflet_css plugins="forms" %}
<form id="location_form" method="post" action="/addlocation/">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text}}
{{ field }}
{% endfor %}
<div class="login-actions">
<button type="submit" name="submit" value="Save">Save</button>
</div> <!-- .actions -->
</form>
May be you missed, in settings:
'ENGINE': 'django.contrib.gis.db.backends.mysql', # if use mysql
in models:
from django.contrib.gis.db import models as gismodels
class Location(gismodels.Model):

How to split form to two columns?

I have model:
class Post(models.Model):
path = 'images' + str(datetime.now().year) + '/' + str(datetime.now().month)
image = models.ImageField(upload_to=path, null=True)
recommended = models.BooleanField(default = False)
promoted = models.BooleanField(default = False)
title = models.TextField(blank = True)
intro = RichTextField(config_name='full_ck', blank = True)
text = RichTextField(config_name='full_ck', blank = True)
, form:
class Form(forms.ModelForm):
id = forms.ModelChoiceField(queryset=Post.objects.all(), widget=forms.HiddenInput())
class Meta:
model = Post
and template:
<table cellpadding="0" cellspacing="0">
<formset>
{% for field in form %}
{% if field.is_hidden %}
{{ field }}
{% else %}
<div class="fieldWrapper">
{% if field.errors %}<div class="errorbox">{% endif %}
<p>{{ field.label_tag }}</p>
<p>{{ field }}{% block formextrafields %}{% endblock %}</p>
<p></p>
{% if field.errors %}<p>{{ field.errors }}</p></div>{% endif %}
</div>
{% endif %}
{% endfor %}
</formset>
</table>
But I want to divide form to two columns. In first may be intro, text and title fields and in second others. How to do it?
I use this in view:
form = list(form)
, in model I set order with:
class Meta:
model = Post
fields = (my fields in order)
and in template:
<!-- first -->
<table cellpadding="0" cellspacing="0">
<formset>
{% for field in form|slice:":3" %}
[...]
{% endfor %}
</formset>
</table>
<!-- second -->
<table cellpadding="0" cellspacing="0">
<formset>
{% for field in form|slice:"3:" %}
[...]
{% endfor %}
</formset>
</table>
And it works.
You could use crispy forms for the layout and to add css classes: https://github.com/maraujop/django-crispy-forms