I have a model named INPUT in my models.py. It has many-to-many field
My problem is that my values are not getting saved in the database or table names INPUT
I don't know where i am wrong.
My models.py is:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Person(models.Model):
title=models.CharField(max_length=1000,unique=True)
cost=models.CharField(max_length=100)
desc=models.TextField(blank=True)
color=models.CharField(max_length=1000)
image_urls=models.CharField(max_length=1000)
source=models.CharField(max_length=1000,unique=True)
category=models.CharField(max_length=1000)
size=models.CharField(max_length=1000)
fit=models.CharField(max_length=1000)
fabric=models.CharField(max_length=1000)
type_dress=models.CharField(max_length=1000)
currency=models.CharField(max_length=1000)
advertiser=models.CharField(max_length=1000)
def __unicode__(self):
return self.title
class foroccasion(models.Model):
occasions=models.CharField(max_length=2000)
def __unicode__(self):
return self.occasions
class forstyle(models.Model):
style=models.CharField(max_length=2000)
def __unicode__(self):
return self.style
class forbodytype(models.Model):
bodytype=models.CharField(max_length=2000)
def __unicode__(self):
return self.bodytype
class Input(models.Model):
tabbody=[
("apple","apple"),
("pear/triangle","pear/triangle"),
("hourglass","hourglass"),
("rectangle","rectangle"),
("inverted triangle","invered triangle")
]
tabstyle=[
("vintage","vintage"),
("sophisticated","sophisticated"),
("chic","chic"),
("bone","bone"),
("edgy","edgy")
]
# apparelid=models.(max_length=104)
apparelid=models.ForeignKey('Person')
# apparelid=models.CharField(max_length=100,blank=True)
userid=models.CharField(max_length=100,blank=True,editable=False)
occassion=models.ManyToManyField(foroccasion)
bodytype=models.ManyToManyField(forbodytype)
style=models.ManyToManyField(forstyle)
def __unicode__(self):
return self.userid
My forms.py is as follows:
import re
from django import forms
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from apple3.models import models
from django.forms import ModelForm
from apple3.models import Input,Person
class UserForm(ModelForm):
class Meta:
model=Input
My views.py is as follows:
def title(request,title_id):
cur=0
cur=Person.objects.get(pk=title_id)
# imge=Person.objects.all()[:109]
# for i in range(1,len(imge)-2):
# if i==int(title_id):
# cur=imge[i]
sz=str(cur.size)
sz=sz.split(',')
fsz=[]
for i in sz:
s=""
for j in range(0,len(i)):
if i[j]!='U' and i[j]!='K' and i[j]!=',':
s+=i[j]
fsz.append(s)
lsz=len(fsz)
#form=UserForm(request.POST)
if request.method == 'POST':# If the form has been submitted...
print "dsflkjdfslkjdsl"
form=UserForm(request.POST)# A form bound to the POST data
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
#form.cleaned_data()
new=form.save(commit=False)
new.userid=request.user
new.occassion=self.cleaned_data["occassion"]
new.bodytype=self.cleaned_data["bodytype"]
new.style=self.cleaned_data["style"]
new.apparelid=self.cleaned_data["apparelid"]
new.save()
form.save_m2m()
else:
form = UserForm() # An unbound form"""
template=loader.get_template('apple3/title.html')
context=RequestContext(request,{
'cur':cur,
'sz':fsz,
'lsz':lsz,
'form':form,
}
)
return HttpResponse(template.render(context))
my template is as follow:
<form action="/dress/female/" method="post">{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Submit" />
</form>
Also i have tried displaying individual elements of the form but it is not getting saved in the database
Please help me
i am new to django.
Add something like this on your form:
YOURFORM(ModelForm):
class Meta:
model=Yourmodel
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(yourform, self).__init__(*args, **kwargs)
def save(self, commit=True):
instance = super(yourform, self).save(commit=False)
if self.user:
instance.user = self.user
return instance.save()
In my example I set the USER field as a value I call from views like this:
form = myForm(request.POST,user=request.user)
Related
I'm writing a program to store analyses for patient and I need to make a form with nested forests with next scheme
Each patient has an analyses results sheet
Each result sheet has date, patient (foreign key) and set of analyses values
Each set of analyses values has strict number and strict types of analyses
Each type of analyse has it's value, name and units
For example I want to create John's analyse result sheet for blood
Patient: John
Date: 10.02.23
Set of values: 'Blood analysis'
Red blood cells: 3,23 10^9
Haemoglobin: 124 g/l
I've made models
patient/models.py
class Patient(models.Model):
hist_number = models.IntegerField(unique=True, verbose_name='Номер истории болезни')
last_name = models.CharField(max_length=32, verbose_name='Фамилия')
analysis/models.py
class PatientAnalysisResultSheet(models.Model):
an_number = models.PositiveBigIntegerField(verbose_name='Номер исследования', unique=True)
date = models.DateField(verbose_name='Дата анализа')
time = models.TimeField(verbose_name='Время')
patient = models.ForeignKey('patient.Patient', verbose_name='Пациент', on_delete=models.CASCADE)
class AnalysisType(models.Model):
name = models.CharField(max_length=256, verbose_name='Исследование', unique=True)
measurement = models.CharField(max_length=10, verbose_name='Единицы измерения')
class PatientAnalysis(models.Model):
sheet = models.ForeignKey(PatientAnalysisResultSheet, on_delete=models.CASCADE)
analysis = models.ForeignKey(AnalysisType, verbose_name='Лабораторный показатель',
on_delete=models.CASCADE)
value = models.FloatField(verbose_name='Значение')
So I googled about formsets and now did next steps:
views.py
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.views.generic import FormView
# Create your views here.
from django.views.generic.detail import SingleObjectMixin
from analysis.forms import PatientAnSheetFormset
from patient.models import Patient
class PatientAnSheet(SingleObjectMixin, FormView):
model = Patient
template_name = 'analysis/patient_ansheets.html'
def get(self, request, *args, **kwargs):
self.object = self.get_object(queryset=Patient.objects.all())
return super().get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.object = self.get_object(queryset=Patient.objects.all())
return super().post(request, *args, **kwargs)
def get_form(self, form_class = None):
return PatientAnSheetFormset(**self.get_form_kwargs(), instance=self.object)
def form_valid(self, form):
form.save()
messages.add_message(
self.request,
messages.SUCCESS,
'Изменения сохранены добавлен!'
)
return HttpResponseRedirect(self.get_success_url())
def get_success_url(self):
return reverse('patient-detail', kwargs={'pk':self.object.pk})
forms.py:
from django.forms import inlineformset_factory
from patient.models import Patient
from analysis.models import PatientAnalysisResultSheet
PatientAnSheetFormset = inlineformset_factory(Patient, PatientAnalysisResultSheet, fields='__all__', extra=1)
But now I'm stuck as I don't know how to create a set of values and how to net it to the form. Appreciate
AIM
I wish to render results.html with all the locations associated with the search_text entered by the User.
To do so, I am attempting to filter the results in get_quersey(), but am struggling to set the form_input variable. I am currently using form_input = self.request.GET.get('search_text').
CODE
models.py
import re
from django.db import models
from twython import Twython
class Location(models.Model):
""" Model representing a Location (which is attached to Hashtag objects
through a M2M relationship) """
name = models.CharField(max_length=1400)
def __str__(self):
return self.name
class Hashtag(models.Model):
""" Model representing a specific Hashtag serch by user """
search_text = models.CharField(max_length=140, primary_key=True)
locations = models.ManyToManyField(Location, blank=True)
def __str__(self):
""" String for representing the Model object (search_text) """
return self.search_text
def display_locations(self):
""" Creates a list of the locations attached to the Hashtag model """
return list(self.locations.values_list('name', flat=True).all())
forms.py
from django import forms
from django.forms import ModelForm
from django.utils.translation import ugettext_lazy as _
from .models import Location, Hashtag
class SearchHashtagForm(ModelForm):
''' ModelForm for user to search by hashtag '''
def clean_hashtag(self):
data = self.cleaned_data['search_text']
# Check search_query doesn't include '#'. If so, remove it.
if data[0] == '#':
data = data[1:]
return data
class Meta:
model = Hashtag
fields = ['search_text',]
labels = {'search_text':_('Hashtag Search'), }
help_texts = { 'search_text': _('Enter a hashtag to search.'), }
views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic
from django.views.generic.edit import FormView
from .models import Location, Hashtag
from .forms import SearchHashtagForm
class HashtagSearch(FormView):
""" FormView for user to enter hashtag search query """
template_name = 'mapping_twitter/hashtag_search_form.html'
form_class = SearchHashtagForm
def get_success_url(self):
return reverse('mapping_twitter:results')
def form_valid(self, form):
# the method is called when valid form data has been POSTed, and returns an HttpResponse
form.clean_hashtag()
form.save()
return super().form_valid(form)
def form_invalid(self, form):
# Check if the search_text is invalid because it already exists in the database. If so, render results.html with that search_text
search_text = self.request.POST.get('search_text')
if search_text and Hashtag.objects.filter(pk=search_text).exists():
return HttpResponseRedirect(reverse('mapping_twitter:results'))
else:
return super(HashtagSearch, self).form_invalid(form)
class SearchResultsView(generic.ListView):
""" Generic class-based view listing search results of locations """
model = Hashtag
template_name = 'mapping_twitter/results.html'
def get_queryset(self, **kwargs):
# ISSUE: restrict the search_text displayed on results.html to the 'search_text' entered by the user
qs = Hashtag.objects.all()
form_input = self.request.GET.get('search_text')
if form_input:
qs = qs.filter(search_text__iexact=form_input)
return qs
def get_context_data(self, **kwargs):
context = super(SearchResultsView, self).get_context_data(**kwargs)
context['search_text'] = Hashtag.objects.all()
return context
In get_context_data you don't use get_queryset method at all. You just write another query which fetch all Hashtag objects. You should rewrite it to this:
def get_context_data(self, **kwargs):
context = super(SearchResultsView, self).get_context_data(**kwargs)
context['search_text'] = self.get_queryset()
return context
Note self.get_queryset() is using instead of Hashtag.objects.all().
Also note to use self.request.GET.get('search_text') you need to pass search_text as GET argument when performing redirect in HashtagSearch view:
class HashtagSearch(FormView):
""" FormView for user to enter hashtag search query """
template_name = 'mapping_twitter/hashtag_search_form.html'
form_class = SearchHashtagForm
def get_success_url(self):
return '{}?search_text={}'.format(reverse('mapping_twitter:results'), self.request.POST.get('search_text'))
UPD
But isntead of two views I recommend you to use single ListView. Just add GET form to your results.html and simple override get_queryset method:
# template
<form method="GET" action="">
<input type="text" name="search_text" placeholder="Search post" value="{{ request.GET.search_text }}">
<input type="submit" value="Search">
</form>
# view
class SearchResultsView(generic.ListView):
""" Generic class-based view listing search results of locations """
model = Hashtag
template_name = 'mapping_twitter/results.html'
def get_queryset(self, **kwargs):
# ISSUE: restrict the search_text displayed on results.html to the 'search_text' entered by the user
qs = Hashtag.objects.all()
form_input = self.request.GET.get('search_text')
if form_input:
qs = qs.filter(search_text__iexact=form_input)
return qs
EXPECTED OUTPUT
Assuming that the user enters "anaconda" in the Form:
Hashtag Search Results
You searched for: anaconda
ACTUAL OUTPUT
Hashtag Search Results
1) You searched for: <QuerySet [<Hashtag: >, <Hashtag: anaconda>]>
CODE
models.py
from django.db import models
class Location(models.Model):
""" Model representing a Location, attached to Hashtag objects through a
M2M relationship """
name = models.CharField(max_length=1400)
def __str__(self):
return self.name
class Hashtag(models.Model):
""" Model representing a specific Hashtag serch by user """
search_text = models.CharField(max_length=140, primary_key=True)
locations = models.ManyToManyField(Location, blank=True)
def __str__(self):
""" String for representing the Model object (search_text) """
return self.search_text
def display_locations(self):
""" Creates a list of the locations """
# Return a list of location names attached to the Hashtag model
return self.locations.values_list('name', flat=True).all()
forms.py
from django import forms
from django.forms import ModelForm
from django.utils.translation import ugettext_lazy as _
from .models import Location, Hashtag
class SearchHashtagForm(ModelForm):
""" ModelForm for user to search by hashtag """
def clean_hashtag(self):
data = self.cleaned_data['search_text']
# Check search_query doesn't include '#'. If so, remove it.
if data[0] == '#':
data = data[1:]
# return the cleaned data
return data
class Meta:
model = Hashtag
fields = ['search_text',]
labels = {'search_text':_('Hashtag Search'), }
help_texts = { 'search_text': _('Enter a hashtag to search.'), }
views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic
from .models import Location, Hashtag
from .forms import SearchHashtagForm
def hashtag_search_index(request):
""" View function for user to enter search query """
# If POST, process Form data
if request.method == 'POST':
# Create a form instance and populate it with data from request (binding):
form = SearchHashtagForm(request.POST)
# Check if form is valid
if form.is_valid():
search_text = form.cleaned_data['search_text']
form.save()
# redirect to a new URL
return HttpResponseRedirect(reverse('mapping_twitter:results'))
# If GET (or any other method), create the default form
else:
form = SearchHashtagForm()
context = {'form':form, 'search_text':Hashtag.search_text}
return render(request, 'mapping_twitter/hashtag_search_index.html', context)
class SearchResultsView(generic.ListView):
""" Generic class-based view listing search results of locations """
model = Hashtag
template_name = 'mapping_twitter/results.html'
def get_queryset(self, **kwargs):
qs = super(SearchResultsView, self).get_queryset()
return qs
def get_context_data(self, **kwargs):
context = super(SearchResultsView, self).get_context_data(**kwargs)
context['search_text'] = Hashtag.objects.all()
return context
results.html
<h1>Hashtag Search Results</h1>
<p>1) You searched for: {{ search_text }}</p>
{% for obj in queryset %}
<p>2) You searched for: {{ obj.search_text }}</p>
{% endfor %}
I think you should pass the queryset of the Model HashTag as you need to render out hashtag.search_text which is an element of that model.
So you can pass the queryset in the view and for loop through it and print all the search_text or pass the object alone and render out its search_text.
context = {
'queryset': qs
}
{% for obj in queryset %}
<p>{{ obj.search_text }}</p>
{% endfor %}
This is my guess, correct me if I am wrong.
For a template to display something, you have to send context or data to that template to print, how can it print something when you don't send anything. So,
context.update({
'hashtag': //value you want to send.
})
does somebody know, can I use SuccessMessageMixin with RedirectView? Because when I use it in my views:
class CarRentView(SuccessMessageMixin,RedirectView):
success_message = "Well done!"
permanent = False
query_string = True
model = Car
def get_redirect_url(self, *args, **kwargs):
car = get_object_or_404(Car, pk=kwargs['pk'])
car.rent=True
car.save()
return reverse('cars')
there is nothing happend.
And I've got another question - is there any way to 'block' car, which is rent for next user and make a queue of people who want the same car?
SuccessMessageMixin for 'FormView' classes, RedirectView does not have forms functionality
Second question more complex
I think you need to do some like (not tested)
models.py
class Car(models.Model):
...
class CarQueue(models.Model):
car = models.ForeignKey(Car)
user = models.ForeignKey(User)
updated_at = models.DateTimeField(auto_now=True)
state = models.PositiveSmallIntegerField(default=1)
# 1 - user rent, 2 - user wait, 0 - archive
...
class Meta:
unique_together = [['car', 'user']]
ordering = ['state', 'updated_at']
views.py
class CarRentView(UpdateView):
model = CarQueue
fields = ['car']
def get_object(self):
return self.object
def get_success_url(self):
# return url according object.state
def form_valid(self, form):
# registered users can rent
form.instance.user = self.request.user
qset = self.model.objects.filter(car=self.car, state__gt=0)
if self.object:
qset = qset.exclude(pk=self.object.pk)
form.instance.state = 1 if qset.exists() else 2
return super(..).form_valid(form)
#method_decorator(login_required)
def dispatch(self, request, *args, **kwargs)
self.car = get_object_or_404(self.model, pk=kwargs['car_pk'])
try:
self.object = self.model.objects.get(car=car, user=request.user)
except ObjectDoesNotExist:
self.object = None
return super(..).dispatch(..)
car_rent_view.html
<form method="post">
{% csrf_token %}
{{ form }}
<input type="submit">
</form>
urls.py
url(r'^rent/(?P<car_pk>[^\/]+)/', views.CartRentView.as_view(), name='CartRentView'),
When I read the documentation about modelforms and widgets it looks like you can use any widget on any modelform but that there are certain default widgets used for form fields corresponding to modelform fields. I'm able to render a radio input using a form field but not with a modelform field.
I have tried many different things, but I just can't seem to render a RadioSelect widget of a modelform field which comes from a model field. Is this even possible?
Btw, my goal is to let the initial value of the radio input correspond with the current value of the model field(A boolean).
Attempt 1:
# views.py
class SettingsView(FormView):
template_name = 'settings.html'
success_url = 'settings/saved/'
form_class = NicknameForm
def post(self, request, *args, **kwargs):
profile = request.user.get_profile()
if request.POST['show_nickname'] == 'False':
profile.show_nickname = False
profile.save()
elif request.POST['show_nickname'] == 'True':
profile.show_nickname = True
profile.save()
return super(NicknameFormView, self).post(request, *args, **kwargs)
def get_context_data(self, **kwargs):
"""
To be able to use 'show_nickname_form' instead of plain 'form' in the template.
"""
context = super(NicknameFormView, self).get_context_data(**kwargs)
context["show_nickname_form"] = context.get('form')
return context
# models.py
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User,
unique=True,
verbose_name='user',
related_name='profile')
show_nickname = models.BooleanField(default=True)
# forms.py
from django import forms
from models import Profile
CHOICES = (('shows_nickname', 'Yes'), ('hides_nickname', 'No'))
class NicknameForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('show_nickname',)
widgets = {
'show_nickname': forms.RadioSelect(attrs={'choices': CHOICES}),
}
Part from my template:
<form action='' method="post">
{{ show_nickname_form.as_ul }} {% csrf_token %}
<input type="submit" value="Save setttings">
</form>
The form that is rendered from {{ show_nickname_form.as_ul }}:
<li><label for="id_show_nickname_0">show nickname:</label>
<ul></ul>
</li>
<div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='1BqD6HJbP5e01NVwLtmFBqhhu3Y1fiOw' /></div>`
Attempt 2:
# forms.py
from django import forms
from models import Profile
class NicknameForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('show_nickname',)
widgets = {
'show_nickname': forms.RadioSelect(),
}
Attempt 3
# forms.py
CHOICES = ((True, 'On',),
(False, 'Off',))
class NicknameForm(ModelForm):
show_nickname = ChoiceField(widget=RadioSelect, choices=CHOICES, initial=True , label='')
class Meta:
model = Profile
fields = ('show_nickname',)
This renders the radio input fine but I need it to take the initial value of the corresponding model field show_nickname instead of the constant True.
I am using Django 1.4 btw.
You need to make it into a ChoiceField instead of a BooleanField with a choice for each and a RadioWidget in order for it to display radio buttons.
https://docs.djangoproject.com/en/dev/ref/forms/fields/#django.forms.ChoiceField
If you want to keep the boolean field, you will most likely have to do some hacking to create your own field/widget.
# views.py
class SettingsView(FormView):
template_name = 'settings.html'
success_url = 'settings/saved/'
form_class = NicknameForm
def get_form(self, form_class):
"""
Returns an instance of the form to be used in this view.
"""
form = super(SettingsView, self).get_form(form_class)
if 'show_nickname' in form.fields:
profile = self.request.user.get_profile()
form.fields['show_nickname'].initial = profile.show_nickname
return form
def post(self, request, *args, **kwargs):
profile = request.user.get_profile()
if request.POST['show_nickname'] == 'False':
profile.show_nickname = False
profile.save()
elif request.POST['show_nickname'] == 'True':
profile.show_nickname = True
profile.save()
return super(NicknameFormView, self).post(request, *args, **kwargs)
def get_context_data(self, **kwargs):
"""
To be able to use 'show_nickname_form' instead of plain 'form' in the template.
"""
context = super(NicknameFormView, self).get_context_data(**kwargs)
context["show_nickname_form"] = context.get('form')
return context