I have difficulties to work with 2 forms within one view. Here is my code and issue :
Model
class Process(models.Model):
name = models.CharField(max_length = 200)
order = models.IntegerField(
default=0,
validators=[
MinValueValidator(0)
]
)
status = models.BooleanField(default = True)
process_owner = models.CharField(max_length = 200)
created_by = models.CharField(max_length = 200)
created_at = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(auto_now = True)
class SubProcess(models.Model):
process = models.ForeignKey(Process, on_delete=models.CASCADE)
next_sub_process = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=False)
name = models.CharField(max_length = 200)
status = models.BooleanField(default = True)
sub_process_owner = models.CharField(max_length = 200)
created_by = models.CharField(max_length = 200)
created_at = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(auto_now = True)
Forms
class createProcessForm(ModelForm):
class Meta:
model = Process
fields = ['name', 'order',]
class createSubProcessForOneShotCreationForm(ModelForm):
class Meta:
model = SubProcess
fields = ['name',]
Template
<form action="{% url 'processmanagement:create_process_subProcess_step' %}" method="post">
{% csrf_token %}
<p>Process</p>
{{ form_process }}
<p>Sub Process</p>
{{ form_subProcess }}
<p></p>
<input type="submit" value="Submit" />
</form>
The view
def create_process_subProcess_step(request):
if request.method == 'POST':
form_process = createProcessForm(request.POST)
print('form_process : ' + str(form_process))
form_subProcess = createSubProcessForOneShotCreationForm(request.POST)
if form_process.is_valid() and form_subProcess.is_valid():
process_instance = form_process.save()
subProcess_instance = form_subProcess.save(commit=False)
subProcess_instance.process = process_instance
subProcess_instance.save()
return redirect('processmanagement:displayProcessAndSubProcess')
form_process = createProcessForm()
form_subProcess = createSubProcessForOneShotCreationForm()
context = {
'form_process' : form_process,
'form_subProcess' : form_subProcess
}
return render(request, 'processmanagement/create_process_subProcess_step', context)
When creating 2 forms within one view and saving those, it looks like the data related to the name from the second form is saved in DB in both first and second objects while the first form should populate the first object and the second form should populate the second object. e.g : in the web page, you validate : process name = A, subprocess name = B, in Db you get process name = B, subprocess name = B.
How should I handle that ?
MariaDb results
I went through different topics such as autocommit, cache issue, db issue (I have changed from SQLite to MariaDB) but nothing helped me.
You should use a prefix in your form instantiations so that the field names don't conflict.
Related
I have 5 forms: MyForm, EducationForm, ExperienceForm, RecommendationForm, OtherDocumentsForm
I want to disply them in one form template. I can not do it with CreateView because it only accepts one form class. How can I create single view for multiple forms?
class MyForm(forms.ModelForm):
class Meta:
model = UserForm_uz
fields = 'all'
class EducationForm(forms.ModelForm):
class Meta:
model = Education_uz
fields = 'all'
class ExperienceForm(forms.ModelForm):
class Meta:
model = Experience_uz
fields = 'all'
class RecommendationForm(forms.ModelForm):
class Meta:
model = Recommendation_uz
fields = 'all'
class OtherDocumentsForm(forms.ModelForm):
class Meta:
model = OtherDocuments
fields = 'all'
I want all the forms to be submitted in a single request and single button. They related with foreignkey to each other EducationForm, ExperienceForm, RecommendationForm, OtherDocumentsForm connected to MyForm with foreignKey
My models:
from django.db import models
language_choices = [('1', 'Билмайман'),
('2', 'Ёмон'),
('3', 'Лугат ёрдамида'),
('4', 'Ўртача'),
('5', 'Яхши'),
('6', 'Жуда яхши'), ]
approve_choices = [('Yes', 'Ха'),
('No', 'Йўк')]
agreement_choices = [('Yes', 'Ха'),
('No', 'Йўк')]
class UserForm_uz(models.Model):
rasm = models.ImageField(upload_to='rasmlar',null=True,blank=True)
lastName = models.CharField(max_length=200)
firstName = models.CharField(max_length=200)
middleName = models.CharField(max_length=200)
birthData = models.DateField()
nation = models.CharField(max_length=50)
birthPlace = models.CharField(max_length=250)
marriage_status = models.CharField(max_length=20)
children = models.CharField(max_length=20)
militaryResp = models.CharField(max_length=150)
language_uzbek = models.CharField(choices=language_choices,max_length=150)
language_russian = models.CharField(choices=language_choices,max_length=150)
language_english = models.CharField(choices=language_choices,max_length=150)
language_boshqa = models.CharField(max_length=50)
computer_literacy = models.CharField(max_length=15)
functional_resp = models.CharField(max_length=250)
work_experience = models.CharField(max_length=200)
yutuqlar = models.CharField(max_length=200)
leaving_work_reason = models.CharField(max_length=200)
main_skills = models.CharField(max_length=300)
expected_salary = models.CharField(max_length=100)
reasontoWork = models.CharField(max_length=300)
relatives_company = models.CharField(max_length=300)
criminal_history = models.CharField(max_length=250)
homeNumber = models.CharField(max_length=15)
phoneNumber = models.CharField(max_length=15)
email = models.EmailField()
additional_info = models.CharField(max_length=300)
approve_info = models.CharField(choices=approve_choices,max_length=20)
agreement = models.CharField(choices=agreement_choices,max_length=20)
passport_file = models.FileField(upload_to='fayllar')
diplom_file = models.FileField(upload_to='fayllar')
trudovoyKnishka = models.FileField(upload_to='fayllar')
fullName = models.CharField(max_length=100)
class Education_uz(models.Model):
form = models.ForeignKey(
UserForm_uz,
on_delete=models.CASCADE,
)
startingDate = models.DateField()
endingDate = models.DateField()
name = models.CharField(max_length=200)
degree = models.CharField(max_length=50)
speciality = models.CharField(max_length=150)
diplomSeriya = models.CharField(max_length=50)
class Experience_uz(models.Model):
form = models.ForeignKey(
UserForm_uz,
on_delete=models.CASCADE,
)
startWorkDate = models.DateField()
endWorkDate = models.DateField()
name = models.CharField(max_length=100)
lavozim = models.CharField(max_length=100)
address = models.CharField(max_length=100)
class Recommendation_uz(models.Model):
form = models.ForeignKey(
UserForm_uz,
on_delete=models.CASCADE,
)
fullName = models.CharField(max_length=150)
workPlace = models.CharField(max_length=150)
phoneAndEmail = models.CharField(max_length=100)
class OtherDocuments(models.Model):
form = models.ForeignKey(
UserForm_uz,
on_delete=models.CASCADE,
)
file = models.FileField(upload_to='fayllar')
comment = models.CharField(max_length=100)
Since MyForm will be submitted at the same time as the other forms you need to exclude the ForeignKey field to UserForm_uz from all the other models, the related object doesn't exist yet so you can't select it
class EducationForm(forms.ModelForm):
class Meta:
model = Education_uz
# Repeated for all four forms
exclude = ['form'] # Whatever the ForeignKey to UserForm_uz is named
Here's an example view that uses three of the forms (I missed out two to save typing). Give each form a prefix, this reduces the risk of having form fields with conflicting names. Validate them all in one go, if any form is invalid the view should not continue. Save MyForm first and use the output to pass to the other forms as the foreign key value
def my_view(request):
if request.method == 'POST':
my_form = MyForm(request.POST, request.FILES, prefix='user')
education_form = EducationForm(request.POST, request.FILES, prefix='education')
experience_form = ExperienceForm(request.POST, request.FILES, prefix='experience')
if all([my_form.is_valid(), education_form.is_valid(), experience_form.is_valid()]):
form = my_form.save()
education = education_form.save(commit=False)
education.form = form
education.save()
experience = experience_form.save(commit=False)
experience.form = form
experience.save()
return redirect('some-view')
else:
my_form = MyForm(prefix='user')
education_form = EducationForm(prefix='education')
experience_form = ExperienceForm(prefix='experience')
return render(request, 'template.html', {'my_form': my_form, 'education_form': education_form, 'experience_form': experience_form})
In your template (template.html) you'll need to render all forms in the same form tag
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ my_form }}
{{ education_form }}
{{ experience_form }}
<input type="submit" />
</form>
I made a multiplechoicefield form (to ask what category user wants to select), but i can't get the answer back...it always renders "None".
I added some 'print' in the code to be sure that it was the problem and it is.
I don't understand why.
forms.py:
class Category(forms.ModelForm):
class Meta:
model = Auctions
fields = ("category",)
#fields = ('category',)
#widgets = {'category' : forms.RadioSelect()}
catform = forms.MultipleChoiceField(choices=fields, widget=forms.CheckboxSelectMultiple())
models.py
'''
class Auctions(models.Model):
Category = [('FASHION', 'Fashion'),('TOYS','Toys'),('ELECTRONICS','Electronics'),('HOME','Home')]
ID_auction = models.AutoField(primary_key = True)
title = models.CharField(max_length = 80)
description = models.TextField()
startingbid = models.IntegerField()
image = models.URLField(blank = True)
category = models.CharField(max_length = 80, choices = Category)
author_id = models.ForeignKey(User,on_delete = models.CASCADE, related_name = "auteur")
highest_bid = models.IntegerField("Bid", blank = True, null = True)
buyer = models.ForeignKey(User, on_delete = models.CASCADE, related_name = "acheteur")
active = models.BooleanField(default=True)
'''
views.py
'''
def filter_cat(request):
if request.method == "POST":
form = Category(request.POST)
print(form)
if form.is_valid():
cat = form.cleaned_data.get("catform")
print(cat)
auctions = Auctions.objects.filter(category = cat)
return render(request, "auctions/index.html",{
'active_listing' : auctions, 'cat' : cat
})
else :
form = Category()
return render(request, "auctions/filter_cat.html",{'form' : form})
'''
when I select FASHION for example i get this on the terminal :
for print(form):
Category:
---------
Fashion
Toys
Electronics
Home
for print(cat):
None
I'm attempting to pull a user's organization, and provide a queryset to on a context processor that will get filtered through multiple different filter depending on the menu selection. The current error I am getting is as titled: Truncated incorrect DOUBLE value:(followed by the org_name of one of all the organizations databased). I have no problems until I create a news article and attach an organization.
organizations model:
class Organizations(models.Model):
org_name = models.CharField(max_length=200)
org_admin = models.ForeignKey(User) #Defines the admin user account for editing
org_description = models.CharField(max_length=1000)
org_phone = models.CharField(max_length=10)
org_county = models.ForeignKey(County)
org_address = models.CharField(max_length=200, blank=True)
org_address2 = models.CharField(max_length=200, blank=True)
org_city = models.CharField(max_length=200, blank=True)
org_zip = models.CharField(max_length=10, blank=True)
org_type = models.ForeignKey(OrgType, blank=True)
sub_org = models.ForeignKey('self', null=True, blank=True) # defines a heirarchy of organiztions
org_logo = models.ImageField(upload_to = 'pic_folder/', blank=True)
org_web = models.CharField(max_length=500, blank=True)
org_facebook = models.CharField(max_length=200, blank=True)
org_twitter = models.CharField(max_length=200, blank=True)
def __unicode__(self):
return self.org_name
news model:
class News(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(User)
slug = models.SlugField(unique=True)
content = models.TextField()
date = models.DateTimeField(default=datetime.now)
category = models.CharField(max_length=1, choices=NEWS_CATEGORIES, blank=True)
news_orgs = models.ManyToManyField(Organizations, blank=True)
news_county = models.ManyToManyField(County, blank=False)
def __unicode__(self):
return self.title
UserOrgConnections model :
class UserOrgConnections(models.Model):
user = models.ForeignKey(User)
orgs = models.ManyToManyField(Organizations)
context processor:
def mynews(request):
now = datetime.now()
if request.user.is_authenticated():
user = request.user.get_profile()
userorgs = UserOrgConnections.objects.filter(user = user)
print userorgs.values('orgs')
county = user.county.all()
MyNews = News.objects.filter(news_orgs__org_name=userorgs)
promotions = OrgPromotion.objects.filter(organization__org_county=county)
dailyspecials = OrgDailySpecials.objects.filter(organization__org_county=county)
newsall = MyNews.all().order_by('-date')
entnews = MyNews.filter(news_county=county, category='E')
technews = MyNews.filter(news_county=county, category='T')
healthnews = MyNews.filter(news_county=county, category='H')
livingnews = MyNews.filter(news_county=county, category='L')
humornews = MyNews.filter(news_county=county, category='H')
travelnews = MyNews.filter(news_county=county, category='R')
moneynews = MyNews.filter(news_county=county, category='M')
return {
'newsall': newsall,
'now': now,
'entnews': entnews,
'technews': technews,
'livingnews': livingnews,
'humornews': humornews,
'travelnews': travelnews,
'moneynews': moneynews,
}
The template snippet:
{% for newsall in newsall %}
{% if newsall.date >= now %}
{{ newsall }}
{{newsall.date }}
{% endif %}
{% endfor %}
The following sequence of code looks suspicious:
userorgs = UserOrgConnections.objects.filter(user = user)
MyNews = News.objects.filter(news_orgs__org_name=userorgs)
This is effectively asking for a sequence of News objects whose news_orgs.org_name value is equal to the list of userorgs. You haven't listed the model for UserOrgConnections so it's not possible to determine a solution with the information provided.
Perhaps you should look at the Django Queryset in operator which is capable of performing a query which filters on a list.
Hi, I have this models:
class Mercadoria(models.Model):
idmercadoria = models.IntegerField(verbose_name=u'Código', primary_key=True)
referencia = models.CharField(verbose_name=u'Referência', max_length=30)
descricao = models.CharField(verbose_name=u'Descrição', max_length=250)
status = models.CharField(verbose_name=u'Status', max_length=1)
class Meta:
ordering = ['referencia', 'descricao']
managed = False
db_table = 'mercadoria'
def __unicode__(self):
return self.referencia + ' - ' + self.descricao
class Produto(models.Model):
idproduto = models.IntegerField(verbose_name=u'Código', primary_key=True)
idmercadoria = models.ForeignKey('Mercadoria', db_column='idmercadoria',
verbose_name=u'Mercadoria')
idtamanho = models.ForeignKey('Tamanho', db_column='idtamanho',
verbose_name=u'Tamanho')
idcores = models.ForeignKey('Cores', db_column='idcores',
verbose_name=u'Cores')
estoqueatual = models.DecimalField(u'Estoque Atual', max_digits=18,
decimal_places=4, null=False, default=0)
saldodisponivel = models.DecimalField(u'Saldo Disponível', max_digits=18,
decimal_places=4, null=False, default=0)
codigobarra = models.CharField(verbose_name=u'Código Barras', max_length=13)
tipoproduto = models.CharField(verbose_name=u'Tipo Produto', max_length=1)
class Meta:
ordering = ['idmercadoria']
managed = False
db_table = 'produto'
class ItensPedido(models.Model):
idpedido = models.ForeignKey('Pedido', db_column='idpedido',
primary_key=True, default=-1)
idproduto = models.ForeignKey('Produto', db_column='idproduto')
And I have a problem to get "referencia" fields from "Mercadoria" model, using "ItensPedido" model.
The problem is: this database is legacy database, used by your ERP Delphi software, and the person who design the database, is crazy! In my template, I want to get "Mercadoria" models data.
I try this: {{ itens.idproduto.idmercadoria.descricao.value }} e {{ itens.idproduto__idmercadoria__descricao.value }} but doesn't work.
I try to modify my view to get select_related() work, like this:
def get_field_qs(field, **kwargs):
if field.name == 'idproduto':
field.queryset = Produto.objects.select_related()
return field.formfield(**kwargs)
ItensInlineFormSet = inlineformset_factory(Pedido, ItensPedido, form=PedidoItensForm,
extra=1, fk_name='idpedido', formfield_callback=get_field_qs)
and same problem.. doesn't show me the data from "mercadoria" model.
What`s I'm doing wrong?
Thanks
I'm having an issue where I instantiate a ModelForm-based form with a pre-existing instance of the model in the GET portion of my view function. This model already has several fields filled in; the ModelForm is used to collect other fields in the model. The pre-existing fields are excluded in the ModelForm's definition.
The problem is, during POST processing, after successful validation of the ModelForm, I'm calling ModelForm.save(commit=False)...and the model returned (which should be the same one I passed in as 'instance' in the GET handling, remember) has somehow lost all the fields that were previously set. The fields actually set by the form are fine; but it's no longer the original instance of my model.
This is not the behavior I expected; and in fact I've used this partial-model-in-modelform previously, and it works other places. What am I missing here??
Hopefully some code'll make all this clear...
So here's the Model:
class Order(models.Model):
STATUS = (
('Created', -1),
('Pending', 0),
('Charged', 1),
('Credited', 2),
)
SHIPPING_STATUS = (
('Cancelled', 0),
('Ready for pickup', 1),
('Shipped', 2),
('OTC', 3),
)
orderID = models.IntegerField(max_length=15, null=True, blank=True)
store = models.ForeignKey(Store)
paymentInstrument = models.ForeignKey(PaymentInstrument, null=True, blank=True)
shippingMethod = models.ForeignKey(ShippingMethod, null=True, blank=True)
last_modified = models.DateTimeField(null=True, blank=True)
date = models.DateTimeField(auto_now_add=True, null=True, blank=True)
total = models.FloatField(default=0.0, blank=True)
shippingCharge = models.FloatField(default=0.0, blank=True)
tax = models.FloatField(default=0.0, blank=True)
status = models.CharField(max_length=50, choices=STATUS, default = 'Created')
shippingStatus = models.CharField(max_length=50, choices=SHIPPING_STATUS, default = '1')
errstr = models.CharField(max_length=100, null=True, blank=True)
# billing info
billingFirstname = models.CharField(max_length = 50, blank = True)
billingLastname = models.CharField(max_length = 50, blank = True)
billingStreet_line1 = models.CharField(max_length = 100, blank = True)
billingStreet_line2 = models.CharField(max_length = 100, blank = True)
billingZipcode = models.CharField(max_length = 5, blank = True)
billingCity = models.CharField(max_length = 100, blank = True)
billingState = models.CharField(max_length = 100, blank = True)
billingCountry = models.CharField(max_length = 100, blank = True)
email = models.EmailField(max_length=100, blank = True)
phone = models.CharField(max_length=20, default='', null=True, blank=True)
shipToBillingAddress = models.BooleanField(default=False)
# shipping info
shippingFirstname = models.CharField(max_length = 50, blank = True)
shippingLastname = models.CharField(max_length = 50, blank = True)
shippingStreet_line1 = models.CharField(max_length = 100, blank = True)
shippingStreet_line2 = models.CharField(max_length = 100, blank = True)
shippingZipcode = models.CharField(max_length = 5, blank = True)
shippingCity = models.CharField(max_length = 100, blank = True)
shippingState = models.CharField(max_length = 100, blank = True)
shippingCountry = models.CharField(max_length = 100, blank = True)
Here's the ModelForm definition:
class OrderForm(ModelForm):
class Meta:
model = Order
exclude = ('orderID',
'store',
'shippingMethod',
'shippingStatus',
'paymentInstrument',
'last_modified',
'date',
'total',
'payportCharge',
'errstr',
'status', )
widgets = {
'billingCountry': Select(choices = COUNTRIES, attrs = {'size': "1"}),
'shippingCountry': Select(choices = COUNTRIES, attrs = {'size': "1"}),
'billingState': Select(choices = STATES, attrs = {'size': "1"}),
'shippingState': Select(choices = STATES, attrs = {'size': "1"}),
}
And here is the view function:
def checkout(request):
theDict = {}
store = request.session['currentStore']
cart = request.session.get('cart', False)
order = request.session['currentOrder'] # some fields already set
if not cart: # ...then we don't belong on this page.
return HttpResponseRedirect('/%s' % store.urlPrefix)
if request.method == 'GET':
form = OrderForm(instance=order, prefix='orderForm')
else: # request.method == 'POST':
logging.info("Processing POST data...")
form = OrderForm(request.POST, prefix='orderForm')
if form.is_valid():
### AT THIS POINT, ORDER FIELDS ARE STILL GOOD (I.E. FILLED IN)
order = form.save(commit=False)
### AFTER THE SAVE, WE'VE LOST PRE-EXISTING FIELDS; ONLY ONES SET ARE
### THOSE FILLED IN BY THE FORM.
chargeDict = store.calculateCharge(order, cart)
request.session['currentOrder'] = order
return HttpResponseRedirect('/%s/payment' % store.urlPrefix)
else:
logging.info("Form is NOT valid; errors:")
logging.info(form._errors)
messages.error(request, form._errors)
theDict['form'] = form
theDict['productMenu'] = buildCategoryList(store)
t = loader.get_template('checkout.html')
c = RequestContext(request, theDict)
return HttpResponse(t.render(c))
Any/all help appreciated...
When you instantiate the form during the POST, the instance of the model you're editing is None, because you're not passing it in, and you're not persisting the form instance from the GET. Django won't do anything on its own to persist data between requests for you.
Try:
...
form = OrderForm(request.POST or None, instance=order, prefix='orderForm')
if request.method == 'POST':
logging.info("Processing POST data...")
if form.is_valid():
...
Now the instance will be populated for GET and POST, but the data from request.POST is optional for the form if it's None. It also saves you from having to instantiate the form in two places depending on request.method