2 Forms in a django template using cookiecutter-django - django

I'm creating 2 forms on one template in cookiecutter-django. I have both forms working on a normal django project but when I migrated them to cookiecutter-django, the forms did not work on the user_detail template.
This is the forms.py
class NarrateForm(ModelForm):
class Meta:
model = Narrate
fields = [
'title',
'body',
]
exclude = ('status',)
class TranslateForm(ModelForm):
class Meta:
model = Translate
fields = [
'title',
'body',
]
exclude = ('status',)
These are the views.py of forms that I have:
class TranslateFormView(FormView):
form_class = TranslateForm
template_name = 'user_detail.html'
def post(self, request, *args, **kwargs):
add_translation = self.form_class(request.POST)
add_narration = NarrateForm()
if add_translation.is_valid():
add_translation.save()
return self.render_to_response(
self.get_context_data(
success=True
)
)
else:
return self.render_to_response(
self.get_context_data(
add_translation=add_translation,
)
)
class NarrateFormView(FormView):
form_class = NarrateForm
template_name = 'users/user_detail.html'
def post(self, request, *args, **kwargs):
add_narration = self.form_class(request.POST)
add_translation = TranslateForm()
if add_narration.is_valid():
add_narration.save()
return self.render_to_response(
self.get_context_data(
success=True
)
)
else:
return self.render_to_response(
self.get_context_data(
add_narration=add_narration,
)
)
Now this is the view of the user_details from cookiecutter-django
class UserDetailView(LoginRequiredMixin, DetailView):
model = User
slug_field = "username"
slug_url_kwarg = "username"
user_detail_view = UserDetailView.as_view()
This is the code on the template which works on the old django project
<form method="POST" action="#">
{% csrf_token %}
{{ add_narration }}
<button type="submit" name="submit" value="Send Narration">Submit Narration</button>
</form>
<form method="POST" action="#">
{% csrf_token %}
{{ add_translation }}
<button type="submit" name="submit" value="Send Narration">Submit Narration</button>
</form>
I've been trying to make this work for more than 2 hours already and had no luck.

A possible solution could be creating a basic form (extend django.forms.Form) in the forms.py file, manually creating the fields and the modela later on in the views.py file.

give the submit inputs different names as shown here
<form method="POST" action="#">
{% csrf_token %}
{{ add_narration }}
<button type="submit" name="narrationsubmit" value="Send Narration">Submit Narration</button>
</form>
<form method="POST" action="#">
{% csrf_token %}
{{ add_translation }}
<button type="submit" name="transaltionsubmit" value="Send Narration">Submit Narration</button>
</form>
Then handle them as below in your view.
def handleforms(request):
if request.method =="POST" and "narrationsubmit" in request.post:
//process
elif request.method =="POST" and "transaltionsubmit" in request.post:
//process
NB: this is for a function based view. format it for a CBV

Related

How to create a charfield with suggestions in django forms?

I want to create a charfield input in a django form that has suggestions. Essentially I want a choice field that also allows you to write your own value if needed. In other words a hybrid between a charfield and choice field input. Any suggestions on how to achieve this ?
forms.py
class PDFClassificationForm(forms.ModelForm):
nature = forms.CharField(required=False)
class Meta:
model = Documents
fields = [,
'nature',]
labels = {,,
'nature':'Nature/Concerne:',
}
def __init__(self, uuid_pdf, *args, **kwargs):
super(PDFClassificationForm, self).__init__(*args, **kwargs)
nature_choices= Archivagerecurrencelibelle.objects.filter(Q(id_emetteur=Documents.objects.get(uuid=uuid_pdf).id_emetteur) & Q(source="Nature")).values_list('concerne','concerne')
self.fields['nature'].choices = nature_choices
views.py
class DocumentsArchiveUpdateView(UpdateView):
model = Documents
template_name = 'documents/documents_read_write.html'
form_class = PDFClassificationForm
success_url = lazy(reverse, str)("documents_archive_list")
def get_context_data(self, *args, **kwargs):
# Call the base implementation first to get a context
context = super(DocumentsArchiveUpdateView, self).get_context_data(*args, **kwargs)
id_customer = Documents.objects.get(uuid=self.kwargs['uuid_pdf']).id_customer
context["document_owner"] = Entity.objects.get(id=id_customer)
context["uuid_contrat"] = self.kwargs['uuid_contrat']
context["uuid_group"] = self.kwargs['uuid_group']
context["uuid_pdf"] = self.kwargs['uuid_pdf']
return context
def form_valid(self, form):
obj = form.save(commit=False)
obj.id_document_status = DocumentStatusLst.objects.get(id=3)
obj.save()
return super().form_valid(form)
def get_form_kwargs(self,) :
uuid_pdf = self.kwargs['uuid_pdf']
kwargs = super(DocumentsArchiveUpdateView, self).get_form_kwargs()
kwargs["uuid_pdf"] = uuid_pdf
return kwargs
documents_read_write.html
{% extends 'layout.html' %}
{% load crispy_forms_tags %}
<form action = "{%url 'jnt_customer_create' uuid_contrat uuid_group pdfid%}" method="POST" enctype="multipart/form-data">
<!-- Security token -->
{% csrf_token %}
<!-- Using the formset -->
{{ form |crispy}}
<button type="submit" name="btnform1" class="btn btn-primary">Enregistrer</button>
</form>
{% endblock %}
----------- models.py -------
from django.db import models
class EmployeeModel(models.Model):
name = models.CharField(max_length=255)
age = models.PositiveIntegerField()
city = models.CharField(max_length=255)
def __str__(self):
return self.name
----------- form.py -------
class EmployeeFrom(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(EmployeeFrom, self).__init__(*args, **kwargs)
self.fields['city'].widget = forms.Select(choices = CityModel.objects.values_list('name','name'))
class Meta:
model = EmployeeModel
fields = "__all__"
widgets = {
'name':forms.TextInput(attrs={'class':'form-control'}),
'age':forms.NumberInput(attrs={'class':'form-control'}),
}
----------- Html code for form -----------
<div class="modal-body">
<form action="" method="POST">
{% csrf_token %}
<div class="mb-3">
<label class="form-label">{{form.name.label}}</label>
{{form.name}}
</div>
<div class="mb-3">
<label class="form-label">{{form.age.label}}</label>
{{form.age}}
</div>
<div class="mb-3">
<label class="form-label">{{form.city.label}}</label>
<input class="form-select" placeholder="--- Select city ---" name="city" type="text" list="cities">
<datalist id="cities">
{% for i in form.city %}
<option>{{i}}</option>
{% endfor %}
</datalist>
</div>
<button class="btn btn-primary" type="submit">Add Employee</button>
</form>
</div>
========= Ouput ===============
all cities
after entering keyword
==== last output ==============
You might try with this https://github.com/jazzband/django-taggit
I used it in a similar use case, you can pass a whitelist of "tags" as suggestion or populate it with already used tags, while still allowing the creation of new values

How do i make many to many field as a chekbox items in template.?

I have 3 models one is Category(Fields = category_name) and another one is SubSategory(Fields = category(ForeignKey to Category),sub_category).and another model is DummyModel.
# Model
class DummyModel(models.Model):
name = models.CharField(max_length=20)
email = models.EmailField()
category = models.ManyToManyField(Category)
sub_category = models.ManyToManyField(SubCategory)
This is my form
class StartProjectForm(ModelForm):
class Meta:
model = StartProject
fields = (
'name',
'email',
'category',
'sub_category',
)
def __init__(self, *args, **kwargs):
super(StartProjectForm, self).__init__(*args, **kwargs)
self.fields["category"].widget = CheckboxSelectMultiple()
self.fields["category"].queryset = Category.objects.all()
self.fields["sub_category"].widget = CheckboxSelectMultiple()
self.fields["sub_category"].queryset = SubCategory.objects.all()
def save(self, commit=True):
clean = self.cleaned_data.get
name = clean('name')
email = clean('email')
category = clean('category')
sub_category = clean('sub_category')
obj = StartProject()
obj.name = name
obj.email = email
obj.category = category
obj.sub_category = sub_category
obj.save()
This is my view
#view
class StartProjectView(View):
template_name = 'start-project.html'
def get(self, request):
form = StartProjectForm()
return render(request, self.template_name, {'form': form})
def post(self, request):
form = StartProjectForm(request.POST)
if form.is_valid():
form.save()
form = StartProjectForm()
return render(request, self.template_name, {'form':form})
return HttpResponse("<h2>Done</h2>")
This is my Template
# Template
<form method="post">
{% csrf_token %}
<p>name: <input type="text" name="name"></p>
<p>Email: <input type="text" name="email"></p>
{% for form in form %}
<input type="checkbox" name="category">{{ form.category }}
{% endfor %}
<br>
{% for form in form %}
<input type="checkbox" name="sub_category">{{ form.sub_category }}
{% endfor %}
<button type="submit">Start Now</button>
</form>
I want category and subcategory in my template as checkbox items. How do I do that.?
After digging in your needs, what you are looking for is {{ form.FIELD_NAME }}.
Whit your form {{ form.category }} and {{ form.sub_category }} should work.
Take into account that this only renders the input itself, nor labels or other DOM elements.
Review the docs on 'Rendering fields manually' for more info -> https://docs.djangoproject.com/en/2.2/topics/forms/#rendering-fields-manually

Custom Form Field Render using UpdateView not Saving Data

I am trying to use custom HTML to render form field elements. However, now the data is not saving. The data is saving if I use the default form.as_p method.
Related template:
<!--DOES NOT SAVE DATA-->
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.description }}
<input type="submit" value="Update"/>
</form>
<!--SAVES DATA-->
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update"/>
</form>
Related UpdateView:
class ProfileEditView(UserPassesTestMixin, UpdateView):
model = Profile
form_class = ProfileCreateForm
template_name = 'update_profile_backup.html'
def get_success_url(self):
return reverse('profile', kwargs={'pk': self.object.pk})
def test_func(self):
obj = self.get_object()
print(obj.user == self.request.user)
return obj.user == self.request.user
Related ModelForm:
class ProfileCreateForm(forms.ModelForm):
class Meta:
model = Profile
fields = 'platform', 'content_niche', 'youtube_channel_id', 'description','profile_img', 'v_id_0', 'v_id_0_title', 'v_id_0_desc', \
'v_id_1', 'v_id_1_title', 'v_id_1_desc', 'v_id_2', 'v_id_2_title', 'v_id_2_desc'
Is it because the custom render method is not validating the form data? If so, how would I do that with an updateview?

How to send some arguments along with CreateView and then access them in the template?

I was making a online store kind of website and am not able to make my add to cart option to work properly. I haven't yet linked the rest of the code to the button and am using an another link to operate it currently as you can see in the code.I want the form to submit the item name and brand automatically. Please suggest some way.
urls.py
url(r'^(?P<pk>[0-9]+)/addtocart/$', views.ItemAdd.as_view(), name='addtocart'),
models.py
class Mycart(models.Model):
name = models.CharField(max_length=250)
brand = models.CharField(max_length=250)
quantity = models.IntegerField(default='1')
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('products:detail', kwargs={'pk': self.pk})
views.py
class ItemAdd(CreateView):
model = Mycart
fields = ['name', 'brand', 'quantity']
template_name = 'products/add_to_cart.html'
def get_context_data(self, **kwargs):
context = super(ItemAdd, self).get_context_data(**kwargs)
return context
add_to_cart.html
{% extends 'products/base.html' %} {% block body %}
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="hidden" name="name" value="{{ object.name }}">
<input type="hidden" name="brand" value="{{ object.brand }}">
<br>
<p>Enter Quantity</p>
<input type="number" name="quantity" value="">
<button type="submit" class="btn btn-success">Submit</button>
</form>
{% endblock %}
I understand that, when user click on item (product), you want automatically add name and brand to form, so user only need to enter quantity and submit form? Maybe you can try like this:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
product_pk = self.kwargs['pk']
product = Product.objects.get(pk=product_pk)
context.update({
'product': product
})
return context
Now you can access product in your template and get name and brand:
{{ product.name }}
{{ product.brand }}
You could use a Formview. Then you will have:
models.py
class Cart(models.Model):
quantity = models.PositiveIntegerField()
product = models.ForeignKey('products.Product')
forms.py
class AddCartForm(forms.ModelForm):
def save(self, product):
instance = super(AddCartForm, self).save(commit=False)
instance.product = product
instance.save()
return instance
class Meta:
model = Cart
fields = '__all__'
views.py
class AddCartView(FormView):
form_class = AddCartForm
success_url = '/'
def dispatch(self, request, *args, **kwargs):
product_pk = kwargs.get('product_pk')
self.product = get_object_or_404(Product, pk=product_pk)
return super(
AddCartView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kw):
context = super(AddCartView, self).get_context_data(**kw)
context.update(product=self.product)
return context
def form_valid(self, form):
form.save(product=self.product)
return super(AddCartView, self).form_valid(form)
add_cart.html
{% extends 'products/base.html' %} {% block body %}
<form action="{% url 'cart:add' product.pk %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
<button type="submit" class="btn btn-success">Submit</button>
</form>
{% endblock %}

Overriding url() from ImageField

I have a image field
avatar = models.ImageField(upload_to="avatar", null=True, blank=True)
and using view
class EditView(SuccessMessageMixin, UpdateView):
model = MysiteUser
form_class = MysiteUserForm
pk_url_kwarg = 'pk'
template_name = 'update_form.html'
success_url = '/myprofile/'
success_message = "Zmiany zostały wprowadzone."
def form_valid(self, form):
image_to_del = MysiteUser.objects.get(username=form.instance)
print("Na dysku plik", image_to_del.avatar)
print("Formularz i pole 'avatar'", form.instance.avatar)
if form.instance.avatar != self.request.user.avatar:
self.request.user.avatar.delete()
return super().form_valid(form)
in template form
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="save" />
</form>
I want change link like below
<p><label for="id_avatar">Zdjecie:</label> Now: avatar/n.jpg
on image, how can I do this?