How to update dynamic form fields in Django - django

The users can dynamically add more fields and edit fields to the forms.
The problem is I don't know how exactly I should pass the dynamic multiple dynamic 'city' ids and edit-update them.
Models.py
class Cities(models.Model):
cityname = models.CharField(max_length=5000, null = True, blank = True)
owner = models.ForeignKey(User, null = True, on_delete=models.CASCADE)
relcountry = models.ForeignKey(Country, null = True, on_delete=models.CASCADE)
Index.html
<form method = "post" action='cityupdate/{{city.id}}' enctype="multipart/form-data">
{% csrf_token %}
{% for city in cities %}
<input type="text" name = "{{city.id}}" value= "{{city.name}}" </input>
{% endfor %}
<input type="submit" name = "cityupdate" value= "Update" </input></a>
</form>
Urls.py
path('cityupdate/<str:id>',views.cityupdate,name='pk')
Views.py
def cityupdate(request,pk):
if request.method == 'POST' and 'cityupdate' in request.POST:
-----------------
I need help to complete the views.py code

Related

Django's Generic UpdateView: How to pass value to the hidden form field?

I am trying to combine Django's generic UpdateView and hidden input field. My purpose is to track whether a post was edited after it was created or not. Hidden field name is "updated".
views.py:
class PostUpdateView(UpdateView):
model = Post
template_name = 'journal/post_update_form.html'
form_class = PostUpdateForm
success_url = reverse_lazy('my_posts')
models.py:
class Post(models.Model):
title = models.CharField(max_length=500)
text = models.TextField(max_length=2000, null=True, blank=True)
owner = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
#storing the link to media files in CharField
image = models.CharField(max_length=500, null=True, blank=True)
audio = models.CharField(max_length=500, null=True, blank=True)
video = models.CharField(max_length=500, null=True, blank=True)
rubric = models.CharField(max_length=100, default="No rubric", choices=RUBRIC_CHOICES)
private = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
updated = models.CharField(max_length=10, default="False")
forms.py:
from django import forms
from .models import Post
class PostUpdateForm(forms.ModelForm):
class Meta:
model = Post
fields = ["title", "text", "image", "audio", "video", "rubric", "private", "updated"]
widgets = {'updated': forms.HiddenInput(attrs={'value':"updated"})}
relevant part of update form template:
<form action="" method="POST">
{% csrf_token %}
{% for field in form %}
{% if field != form.rubric and field != form.private %}
<div class="mb-3 form-group">
<label for="{{field.name}}" class="form-label">{{field.label}}</label>
{{field.errors}}
{% if field == form.text %}
<textarea type="text" class="form-control" id="{{field.name}}" name="{{field.name}}">{{field.value|default_if_none:"" }}</textarea>
{% elif field == form.updated %}
<input type="hidden" id="{{field.name}}" name="{{field.name}}" value="updated">
{% else %}
<input type="text" class="form-control" id="{{field.name}}" name="{{field.name}}" value="{{field.value|default_if_none:"" }}">
{% endif %}
</div>
<...some other fields...>
{% endif %}
{% endfor %}
<input type="submit" class="btn btn-primary" value="Update"/>
</form>
Value of "updated" field is passed successfully, but the field value is visible (non-editable).
In forms.py I tried to:
exclude 'updated' from fields list. Result: the value of "updated" is not saved.
use "widgets = {'updated': forms.HiddenInput}". Result: value is also passed successfully, but the field is still visible.
use only widgets in forms.py and comment out input field [1] in the template. Result: field is visible, editable, value is not saved.
[1] input field:
{% elif field == form.updated %}
<input type="hidden" id="{{field.name}}" name="{{field.name}}" value="updated">
I would appreciate any insights about what might be wrong here. Thank you in advance.
In PostUpdateForm you can do so:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['updated'].initial = 'updated'
self.fields['updated'].disabled = True
https://docs.djangoproject.com/en/4.1/ref/forms/fields/#disabled

Django forms how to display related data in an inner form

I am struggling with Django forms.
I have the following model.py:
class Property(models.Model):
portfolio = models.ForeignKey("portfolios.Portfolio", on_delete=models.CASCADE)
class PropertyImage(models.Model):
property = models.ForeignKey("Property", on_delete=models.CASCADE)
image = models.ImageField(upload_to = property_image_upload_to)
def __str__(self):
return self.image.url
class PropertyDocument(models.Model):
property = models.ForeignKey("Property", on_delete=models.CASCADE)
document = models.FileField()
class Address(models.Model):
property = models.OneToOneField("Property", on_delete=models.CASCADE)
line1 = models.CharField(max_length=100)
line2 = models.CharField(max_length=100, null=True, blank=True)
line3 = models.CharField(max_length=100, null=True, blank=True)
post_code = models.CharField(max_length=7)
town = models.CharField(max_length=100, null=True, blank=True)
city = models.CharField(max_length=100)
When adding/updating a property, I want the form to show the form for related objects like the address, documents/images instead of the select list's that appear in forms - I want to be able to add/edit the related data.
My view.py file
class PropertyCreate(CreateView):
model = Property
form_class=PropertyAddressFormSet
success_url = reverse_lazy('Property_list')
def get_context_data(self, **kwargs):
data = super(PropertyCreate, self).get_context_data(**kwargs)
return data
Property_form.html
{% extends 'base/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" class="btn btn-primary" />
<button class="btn btn-link" onclick="javascript:history.back();">Cancel</button>
</form>
{% endblock %}
urls.py
from . import views
app_name = 'properties'
urlpatterns = [
path('<int:portfolio_id>/<int:pk>/edit', views.PropertyUpdate.as_view(), name='property_edit'),
path('<int:portfolio_id>/create', views.PropertyCreate.as_view(), name='property_new'),
]
I've read about inlineformset_factories and inlineformset's etc, but is this the best choice for my scenario? If so, I can't figure out how to show the portfolio, address form
I;m currently using a inlineformset like so, which creates the Address form on the PropertyCreate view, but I want to also add in the PropertyImages and PropertyDocs to the ProertyCreate view.:
PropertyAddressFormSet = inlineformset_factory(
parent_model=Property,
model=Address,
form=AddressForm,
extra=0,
min_num=1
)
For anyone in the same boat as me, I managed to get this working with the following code:
Forms.py:
class PropertyForm(ModelForm):
""" Edit a property """
class Meta:
model = Property
exclude = ()
PropertyAddressFormSet = inlineformset_factory(
parent_model=Property,
model=Address,
form=AddressForm,
extra=0,
min_num=1
)
Views.py
class PropertyCreate(CreateView):
model = Property
form_class=PropertyForm
success_url = reverse_lazy('Property_list')
def get_context_data(self, **kwargs):
data = super(PropertyCreate, self).get_context_data(**kwargs)
if self.request.POST:
data['address'] = PropertyAddressFormSet (self.request.POST, instance=self.object)
else:
data['address'] = PropertyAddressFormSet ()
return data
template:
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form |crispy }}
<fieldset class="border p-2">
<legend class="w-auto">Address</legend>
{{ address.management_form }}
{% for form in address.forms %}
<div >
{{ form.as_p }}
</div>
{% endfor %}
</fieldset>
</form>
Hope this helps someone.

'PersonForm' object has no attribute 'as_widget'

I am trying to pass string to a hidden field scenario of a form whose data is stored in a database. The goal is to be able to retrieve extra information on client side without having it as another field of the form.
I am getting 'PersonForm' object has no attribute 'as_widget' error.
This is my Model:
class Person(models.Model):
region = models.CharField(max_length=30)
industry = models.CharField(max_length=30)
uuid = models.CharField(max_length=50, blank=True, unique=True, default=uuid.uuid4)
scenario = models.ForeignKey(Scenario, on_delete=models.CASCADE,)
def __str__(self):
return "{}".format(self.uuid)
My Form
class PersonForm(forms.ModelForm):
class Meta:
model=Person
scenario = forms.CharField(widget=forms.HiddenInput())
fields = ['industry', 'region','scenario']
My View
def personforms(request):
persons = Person.objects.all()
if request.method == 'POST':
filled_form = PersonForm(request.POST)
if filled_form.is_valid():
created_person = filled_form.save()
#DEBUG
print(filled_form.cleaned_data['scenario'])
created_person_pk = created_person.id
filled_form = PersonForm()
return redirect('/scenariopage', {'persons':persons})
else:
created_person_pk = None
return render(request, 'core/scenario-landing-page.html', {'personform':filled_form, 'created_person_pk':created_person_pk})
else:
form = PersonForm()
return render(request, 'core/scenario-landing-page.html', {'personform':form})
And my template
<form action="{% url 'personform' %}" method="post" class="custom-form">
{% csrf_token %}
{% render_field personform class="form-control" %}
{% render_field personform.scenario class="form-control form-control-sm" value='{{ scenario.name }}' %}
<input type="submit" class="btn color-btn" value="Go to Scenario page" data-dismiss="gallery-item"/>
</form>
Questions I have:
I have no Error message. But debug print is indicating that filled_form.is_valid(): seems to be invalid.
And this line in the View never print result:
#DEBUG
print(filled_form.cleaned_data['scenario'])
What I am doing wrong?
How could I possibly pass the data to the field scenario.

Django foreign key drop down

New to Django and Python and I need a little help with a foreign key drop down. Basically, I have a category model and a image model and I want users to be able to choose which category to put the image in. How do I create a drop down for the category in the image form? Are my views and html correct too? I have had a look online but I can't seem to do it myself. I keep getting errors.
Here are my models:
class Images(models.Model):
image = models.ImageField(upload_to='images', blank=False)
img_name = models.CharField(max_length=120, blank=True)
img_date = models.DateTimeField(default=now())
img_user = models.ForeignKey(User)
img_cat_id = models.ForeignKey(Categories)
def __unicode__(self):
return self.img_name
class Categories(models.Model):
cat_descr = models.CharField(max_length =120, blank=False)
def __unicode__(self):
return self.cat_descr
VIEWS:
#login_required
def upload_images(request):
context = RequestContext(request)
context_dict={}
if request.method == 'POST': # render the form, and throw it back.
# take the form data and process it!
form = UploadImagesForm(request.POST, request.FILES)
if form.is_valid():
print 'form is_valid'
upload_image = form.save(commit=False)
upload_image.img_user = request.user
if 'image' in request.FILES:
upload_image.image =request.FILES['image']
upload_image.save()
return render(request, 'rmb/upload.html', {'upload_image': form})
else:
print form.errors
# Not a HTTP POST, so we render our form using two ModelForm instances.
# These forms will be blank, ready for user input.
else:
form = UploadImagesForm()
context_dict = {'upload_image': form}
all_categories = Categories.objects.order_by('-id')
context_dict['all_categories'] = all_categories
print context_dict
return render_to_response('rmb/upload.html', context_dict, context)
FORMS:
class UploadImagesForm(forms.ModelForm):
#cat_list = ModelChoiceField(queryset=Categories.objects.all())
class Meta:
model = Images
fields=('image','img_name')
HTML:
{% block body_block %}
<form id="upload_form" method="post" action="/rmb/upload/"
enctype="multipart/form-data">
{% csrf_token %}
{{ upload_image.as_table }}
<input type="submit" name="submit" value="Upload" />
{% for categories in all_categories %}
<div> {{ categories.id }} </div>
{{ categories.cat_descr }}
<input type="submit" name="submit" value="Upload" />
{% endfor %}
</form>
{% endblock %}
You don't need to insert the HTML for the form manually, just use {{form}} in the template.
{% block body_block %}
<form id="upload_form" method="post" action="/rmb/upload/"
enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
</form>
{% endblock %}
By default a ForeignKey will be a select field so you shouldn't need to do much else.
As an aside, give your models and fields more appropriate names. We know these are all image fields, because they are on the image and make sure, unless your model is a collection of things, you give it a singular name. Lastly, when using a Foreign Key and item gets an extra field of fieldname_id that is just the ID, whereas fieldname is the property that gives the related item as well.
So instead of:
class Images(models.Model):
image = models.ImageField(upload_to='images', blank=False)
img_name = models.CharField(max_length=120, blank=True)
img_date = models.DateTimeField(default=now())
img_user = models.ForeignKey(User)
img_cat_id = models.ForeignKey(Categories)
Use:
class Image(models.Model):
image = models.ImageField(upload_to='images', blank=False)
name = models.CharField(max_length=120, blank=True)
date = models.DateTimeField(default=now())
user = models.ForeignKey(User)
category = models.ForeignKey(Categories)

No data displayed when using django ModelForm with Foreign key

I'm trying to display a django ModelForm in my template, but I could not get it to work.
Here is my code:
the template is this:
{% extends 'base.html' %}
{% load i18n %}
{% load url from future %}
{% block content %}
{{ block.super }}
<section>
<article>
<form action="{% url 'SaisirEnfant' %}" method="post">{% csrf_token %}
<fieldset>
<div id="newad"> {{ newenfant.as_p }} </div>
<div id="sub"> <input type="submit" value="Submit" /> </div>
</fieldset>
</form>
</article>
</section>
{% endblock %}
and the models are like this:
class PersonneAdulte(models.Model):
profile = models.ForeignKey(Profile, verbose_name='Personne Adulte')
prenom = models.CharField(max_length=50)
responsable = models.BooleanField(default=False, verbose_name=_('responsable'))
class Famille(models.Model):
responsable = models.ForeignKey(PersonneAdulte, verbose_name='responsable')
sous_responsable = models.IntegerField(null=True, blank=True)
coef_fam = models.IntegerField(null=True, blank=True)
id_fam = models.IntegerField(null=True, blank=True)
class Enfant(models.Model):
responsable = models.ForeignKey(Famille, verbose_name='responsable')
nom = models.CharField(max_length=50 )
finaly the wiews is like this:
class PersonneAdulteForm(ModelForm):
class Meta:
model = PersonneAdulte
exclude = ('profile')
def PersonneAdulte(request):
if request.method == 'POST':
adulte = PersonneAdulteForm(request.POST)
if adulte.is_valid():
#creates a new `User`.
new_user = UserenaSignup.objects.create_user(username=adulte.data['nom'],
email='nom.prenom#site.fr',
password='0000',
active=False,
send_email=False)
# Send the signup complete signal
userena_signals.signup_complete.send(sender=None,
user=new_user)
#Activate a user with an activation key.
activation_key = UserenaSignup.objects.get(user_id=new_user.id).activation_key
user = UserenaSignup.objects.activate_user(activation_key)
t = adulte.save(commit=False)
if t.responsable == False :
new_user.is_active = False
new_user.save()
else :
f = Famille.objects.create(pk=new_user.id, responsable_id=new_user.id, id_fam=new_user.id)
p = adulte.save(commit=False)
p.id = p.profile_id = new_user.id
p.save()
return HttpResponse( 'id: ' + str(p.id) )
else:
adulte = PersonneAdulteForm()
return render_to_response('familles/PersonneAdulte.html', dictionary={ 'adulte' : adulte}, context_instance=RequestContext(request))
Profile is the model defined by the userena package
My view is for creating a new Enfant instance but no data at all is displayed and there is no error message. The problem is related to the foreign key in my model (responsable) because if I exclude the field in my form it works fine. Anybody knows where this problem comes from or how I can debug it?