Django pass object to model of another form - python

I have implemented a Python form/view/template that lets you configure different notifications for a product:
models.py
class PNotification(models.Model):
add = models.BooleanField(default=False, help_text='Receive messages when an engagement is
added')
delete = models.BooleanField(default=False, help_text='Receive
class Product(models.Model):
forms.py
class PNotificationForm(forms.ModelForm):
class Meta:
model = PNotification
exclude = ['']
class ProductForm(forms.ModelForm):
The PNotification has an own view and template:
<h3> Edit Notifications for {{ product.name }}</h3>
<form class="form-horizontal" method="post">{% csrf_token %}
{% include "dojo/form_fields.html" with form=form %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input class="btn btn-primary" type="submit" value="Submit"/>
</div>
</div>
</form>
When I call the page (edit/product_id/notifications) to edit an products notifications, the h3 is set correct, so the product is passed to the form/template.
My problem is: I need to link PNotification with a product.
How can I pass product.id to my PNotificationForm so I can save it there? This field should be the primary key of PNotification.
Edit
Here is my view.py:
def edit_product_notifications(request, pid):
prod = Product.objects.get(pk=pid)
logger.info('Editing product')
if request.method == 'POST':
pnotification = PNotificationForm(request.POST, instance=prod)
if pnotification.is_valid():
pnotification.save()
logger.info('saved')
else:
pnotification = PNotificationForm()
if pnotification.is_valid():
pnotification.save()
logger.info('saved')
logger.info(PNotification.objects.get(id=1).msteams)
logger.info('returning')
return render(request,
'dojo/edit_product_notifications.html',
{'form': pnotification,
'product': prod
}).
I am passing the product id and then getting it from objects.get().

In urls.py the path to that view needs to have <int:pk>. The path would look like this edit/<int:pn_pk>/notifications
In your view you need to get the kwargs which is the argument passed by the url.
In a function based view:
def your_view_name(request, pk):
# use pk how you want.
PN = PNotification.objects.get(pk=pn_pk)
return render(...)

Related

Creating Dropdown from Model in Django

I am looking to create a dropdown in a template where the values of the dropdown come from a field (reference) within my Orders model in models.py. I understand creating a dropdown where the values are set statically, but since I am looking to populate with values stored in the DB, I'm unsure of where to start.
I've created the model and attempted playing around with views.py, forms.py and templates. I am able to get each of the order numbers to display but not in a dropdown and I am struggling with how to write my template.
models.py
from django.db import models
class Orders(models.Model):
reference = models.CharField(max_length=50, blank=False)
ultimate_consignee = models.CharField(max_length=500)
ship_to = models.CharField(max_length=500)
def _str_(self):
return self.reference
forms.py
from django import forms
from .models import *
def references():
list_of_references = []
querySet = Orders.objects.all()
for orders in querySet:
list_of_references.append(orders.reference)
return list_of_references
class DropDownMenuReferences(forms.Form):
reference = forms.ChoiceField(choices=[(x) for x in references()])
views.py
def reference_view(request):
if request.method == "POST":
form = references(request.POST)
if form.is_valid():
form.save()
return redirect('index')
else:
form = references()
return render(request, 'proforma_select.html', {'form': form})
proforma_select.html
{% extends 'base.html' %}
{% block body %}
<div class="container">
<form method="POST">
<br>
{% for field in form %}
<div class="form-group row">
<label for="id_{{ field.name }}" class="col-2 col-form-label"> {{ field.label }}</label>
<div class="col-10">
{{ field }}
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary" name="button">Add Order</button>
</form>
</div>
{% endblock %}
All I get when I render the template is each of the reference #s listed out but NOT within a dropdown. This leads me to believe my problem is mainly with the template, but I'm unsure as I am new to using Django.
Are you using Materialize CSS? If yes, then Django forms renders dropdowns differently from how Materialize expects them. So you will want to override the form widget. You can do something like so:
forms.py:
class DropDownMenuReferences(forms.Form):
reference = forms.ChoiceField(choices=[(x) for x in references()],
widget=forms.Select(choices=[(x) for x in references()], attrs={'class':
'browser-default'}))
This overrides the parameters passed into html. You can also pass any name tags in the attrs too.
The issue:
https://github.com/Dogfalo/materialize/issues/4904

Django and MySQL save multiple data

I am trying to save multiple fields of data. I've also changed the database connection from the default sqlite3 to MySQL. And I don't know how to do this
Here's my views.py
def customerview(request):
if request.POST:
form = CustomerForm(request.POST)
if form.is_valid():
if form.save():
return redirect('sales')
else:
return redirect('index')
else:
return redirect('index')
else:
form = CustomerForm
return render(request, 'customer.html', {'form':form})
def salesview(request):
if request.POST:
form = SalesForm(request.POST)
if form.is_valid():
if form.save():
return redirect('index')
else:
return redirect('index')
else:
return redirect('index')
else:
form = SalesForm
data = Customer.objects.latest('id')
return render(request, 'sales.html', {'form':form, 'range':range(data.number_of_transactions)})
Here's my models.py
class Customer(models.Model):
customer_name = models.CharField(max_length=200)
number_of_transactions = models.IntegerField()
class Sales(models.Model):
product_type = models.CharField(max_length=100)
product_code = models.CharField(max_length=100)
product_size = models.CharField(max_length=100)
product_quantity = models.IntegerField()
Here's my brands.html
<form class="form" role="form" action="" method="post"> {% csrf_token %}
{% for i in range %}
<div class="col">
<div class="col-sm-3">
<div class="">
{{ form.product_type | add_class:'form-control' }}
<label for="regular2">Product Type</label>
</div>
</div>
<div class="col-sm-3">
<div class="">
{{ form.product_code | add_class:'form-control' }}
<label for="regular2">Product Code</label>
</div>
</div>
</div>
{% endfor %}
<div class="col-md-12">
<hr>
<div class="card-actionbar-row">
<input type="submit" class="btn btn-flat btn-primary ink-reaction" value="SUBMIT">
</div>
</div>
</form>
The idea is to get the customer details and number of transactions to be performed then that determines the number of fields to be displayed in the sales view. And that works fine.
The problem is to get each of the transactions to be saved in the database. When I submit and check my database tables, only one transaction is saved.
It's clear that you're trying to run before you can walk here.
Firstly, you should concentrate on getting a simple list view to work, without getting confused about the additional complexity involved in displaying a list in a form view. So, make your view inherit from ListView, and remove all the methods. Then fix your template, so that it iterates over stock_list or object_list rather than just stock.
Secondly, once you've got that working, you could try to integrate it with a form. When you do that, learn what methods to override. get_queryset must return a queryset, it should not render a template. In any case, you should almost never need to render a template manually in a class-based view, because the existing logic will do that for you. And if you want to add a queryset to the template context in a create view, for example, you should be overriding get_context_data; which needs to return a dictionary.
Thirdly, if at some point you do need to render a template manually, read the documentation to learn the order of parameters to render: it is request, template_name, context, not as you have it.

Generate objects in django template dynamically

I have 2 models in my system:
class Display(models.Model):
name = models.CharField
UE = models.CharField
description
class Register(models.Model):
temp1 = models.FloatField()
temp2 = models.FloatField()
flow = models.FloatField()
I create displays using for inside a template, but the value of each display is a respective field in Register model. I can't make the loop with Register because i use only row (i can't loop fields). Understand?
Take a look of my code:
View:
def main(request):
dp_col = Display.objects.all()
reg = Registers.objects.latest('pk')
context = {
'dp_col': dp_col,
'reg':reg
}
return render(request,'operation.html',context)
Template:
{% for dp in dp_col %}
<div class='col-md-6'>
<div class="display-content">
<div class="display-data">
<h3 class="text-center display-desc">{{dp.name}}
<span>:</span>
<span class="text-center display-value">I need put the value of each field here</span>
<span class='display-unit'> {{dp.UE}}</span>
</h3>
</div>
</div>
</div>
{% empty %}
<!--colocar alguma coisa aqui, caso não tenha nada no for-->
{% endfor %}
Any ideas?
Thanks a lot!
This can be easily solved by using a Django Forms:
yourapp/forms.py
from django import forms
class DisplayForm(forms.ModelForm):
class Meta:
model = Display
fields = '__all__'
yourapp/views.py
from .forms import DisplayForm
def main(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = DisplayForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = DisplayForm()
return render(request, 'operation.html', {'form': form})
In operations.html:
<form method="post" action="">
{{ form }}
</form>
Or if you want custom html in each field:
<form method="post" action="">
{% for field in form %}
{{ field.label_tag }} {{ field }}
{% endfor %}
</form>
Reference:
https://docs.djangoproject.com/en/1.11/topics/forms/

Django Model Form not appearing in admin

I've got a feedback app in django and it all seems to work fine, no errors i can submit the form and it all seems to work, however i have my model registered into my admin however when i submit the form i doesn't appear in my admin. Sorry if this is very basic i just cant get my head around it please help.
in my models.py
class Feedback(models.Model):
email = models.CharField(max_length=100)
message = models.CharField(max_length=1000)
def __unicode__(self):
return self.title
which i then pass through to forms.py
class FeedbackModelForm(forms.ModelForm):
class Meta:
model = Feedback
fields = ["email", "message"]
and my view is
def feedbackform(request):
form = FeedbackModelForm(request.Post or None)
if form.is_valid():
form.save()
return render(request, "feedback.html", {"form": form})
now in my html looks like this
{% block content %}
<div id="feedback">
<div id="feedback-form" style='display:none;' class="col-xs-4 col-md-4 panel panel-default">
<form method="POST" action="{{ form }}" class="form panel-body" role="form">{% csrf_token %}
<div class="form-group">
<input class="form-control" name="email" autofocus placeholder="Your e-mail" type="email" />
</div>
<div class="form-group">
<textarea class="form-control" name="message" required placeholder="Please write your feedback here..." rows="5"></textarea>
</div>
<button class="btn btn-primary pull-right" type="submit">Send</button>
</form>
</div>
<div id="feedback-tab">Feedback</div>
</div>
{% endblock %}
and in my admin
from .models import Feedback
from .forms import FeedbackModelForm
class FeedbackAdmin(admin.ModelAdmin):
form = FeedbackModelForm
admin.site.register(Feedback, FeedbackAdmin)
You have passed the
{{ form }}
as the action attribute, which is completely wrong. Put it inside a div as
{{ form.as_p }}
that will work for you.
And in the action attribute pass a url in the form of
{% url 'home_page_example' %}
if you wanted to remain in the same page and redirect via view
you can write
action = "."
Show us how did you register your model in the admin.
Make sure that you explicit config the form, like this
class FeedbackAdmin(admin.ModelAdmin)
form = FeedbackModelForm
admin.site.register(Feedback, FeedbackAdmin)
You should return email or message in def __unicode__(self):, not title.
class Feedback(models.Model):
email = models.CharField(max_length=100)
message = models.CharField(max_length=1000)
def __unicode__(self):
return self.email
I think that you should check if the view is currently saving your Feedback.
Try inspecting the DB or in a manage.py shell check if len(Feedback.objects.all()) change when you submit a Feedback in your view.
Also, I recommend you to change the email field to an EmailField and use the FormView class based view.

How create a custom form in django with database values

model.py
class Venue(models.Model):
venue_Name = models.CharField(max_length=100)
place = models.CharField(max_length=50)
rent = models.IntegerField()
parking_area = models.IntegerField()
class Decoration(models.Model):
rate = models.IntegerField()
I have printed the values in database as radio buttons what i want to do is that i want to get the total sum i.e venue.rent + decoration.rate and print it in another page What shoud i give in form action I'm not that familiar with forms.
html
<form action="{% %}" method="post">
{% for venue in venues %}
<input type="radio" name=venue value=venue.rent />{{ venue.venue_Name}}
{% endfor %}
{% for decoration in decorations %}
<input type="radio" name=decor value=decoration.rate />{{ decoration.rating }}
{% endfor %}
<input type="submit" value=" " />
</form>
what should i write in view and urls to get the sum
You can use Django's form for validation and parsing. For that you would set up a form like so:
forms.py
from django import forms
class TotalSumForm(forms.Form):
venue = forms.ModelChoiceField(queryset=Venue.objects.all(), required=True)
decoration = forms.ModelChoiceField(
queryset=Decoration.objects.all(), required=True)
def get_total(self):
# send email using the self.cleaned_data dictionary
return self.cleaned_data['venue'].rent +\
self.cleaned_data['decoration'].rate
And then using a class based view, add the result to context upon submission.
views.py
from myapp.forms import TotalSumForm(
from django.views.generic.edit import FormView
class TotalCost(FormView):
template_name = 'your_template.html'
form_class = TotalSumForm
success_url = '/thanks/'
def form_valid(self, form):
# This method is called when valid form data has been POSTed.
total_result = form.get_total()
# return back to your_template.html with the total in context
return self.render_to_response(self.get_context_data(
form=form, total=total_result))
The urls are pretty simple:
urls.py
from django.conf.urls import patterns, url
import myapp.views
urlpatterns = patterns(
'',
url(r'^total_calc/$', myapp.views.TotalCost.as_view(), name='calculate_total'),
)
Your html could be modified like so
your_template.html
<html>
<body>
<h1>TEST SUCCESFULL!</h1>
{% if total %}
<p>Total cost for venue and decoration: {{ total }}</p>
{% endif %}
<form action="{% url 'calculate_total' %}" method="post">
{{ form.as_p }}
<input type="submit" value="Calculate Total" />
</form>
</body>
</html>

Categories