Im following the Django docs in order to build a multiple search criteria form. My first question is if this should be the correct method of filtering values in the query and also how can i add the foreignkeys and m2m displayed as selects and multipleselects in the search criteria.. This is my code so far. Thanks
Forms
class SearchPropertyForm(forms.Form):
name = forms.CharField(max_length = 100, widget = forms.TextInput(attrs = {'class':'form-control', 'placeholder':'Nombre'}))
activity = forms.ModelChoiceField(queryset = Activity.objects.all(), widget = forms.Select(attrs = {'class':'form-control', 'placeholder':'Actividad'}))
currency = forms.ModelChoiceField(queryset = Currency.objects.all(), widget = forms.Select(attrs = {'class':'form-control', 'placeholder':'Moneda'}))
price_from = forms.IntegerField(widget = forms.TextInput(attrs = {'class':'form-control', 'placeholder':'Precio-Desde'}))
price_to = forms.IntegerField(widget = forms.TextInput(attrs = {'class':'form-control', 'placeholder':'Precio-Hasta'}))
categories = forms.ModelMultipleChoiceField(queryset = Category.objects.all(), widget = forms.SelectMultiple(attrs = {'class':'form-control', 'placeholder':'Categorias'}))
Model
class Property(models.Model):
class Meta:
verbose_name_plural = "properties"
name = models.CharField(max_length = 200)
description = models.TextField(max_length = 500)
address = models.CharField(max_length = 200)
sqft = models.DecimalField(max_digits = 6, decimal_places = 2)
beds = models.IntegerField()
baths = models.IntegerField()
status = models.BooleanField(default = True)
price = models.DecimalField(max_digits = 6, decimal_places = 2)
likes = models.IntegerField()
categories = models.ManyToManyField(Category, null = True, blank = True)
currency_type = models.ForeignKey(Currency)
activity_type = models.ForeignKey(Activity)
creation_date = models.DateTimeField(auto_now_add = True)
edition_date = models.DateTimeField(default = timezone.now)
def __unicode__(self):
return self.name
View
def search_properties(request):
if request.method == 'POST':
form = SearchPropertyForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
activity = form.cleaned_data['activity']
currency = form.cleaned_data['currency']
price_from = form.cleaned_data['price_from']
price_to = form.cleaned_data['price_to']
categories = form.cleaned_data['categories']
properties = Property.objects.filter(name__icontains = name).filter(
activity_type__exact = int(activity)).filter(
currency_type__exact = int(currency)).filter(
price_from__gte = int(price_from)).filter(
price_from__lte = int(price_to)).filter(
categories__exact = int(categories))
return render(request, 'properties/search_properties.html', {
'properties': properties,
'media_url': settings.MEDIA_URL,
'form':form,
})
else:
form = SearchPropertyForm()
properties = Property.objects.filter(status = True)
return render(request, 'properties/search_properties.html', {
'properties': properties,
'media_url': settings.MEDIA_URL,
'form':form,
})
You can use the Q object in case you are trying to do a or query.
https://docs.djangoproject.com/en/dev/topics/db/queries/#complex-lookups-with-q-objects
so your code could be like this.
from django.db.models import Q
properties = Property.objects.filter(Q(name__icontains = name)|
Q(activity_type__exact = int(activity))|
Q(currency_type__exact = int(currency))|
Q(price_from__gte = int(price_from))|
Q(price_from__lte = int(price_to))|
Q(categories__exact = int(categories))
In the Q object | (pipe) represents an or query and & represents an and query.
So this will return if any of the query is matched.
For the forms section I use Modelform like the following which automatically takes the foreign keys and the multiselects.
class SearchPropertyForm(forms.ModelForm):
class Meta:
model = Property
fields = ('name', 'activity','currency', 'price_form')
You can use Q objects, or simply use django-filter:
Django-filter provides a simple way to filter down a queryset based on parameters a user provides.
Once you have it installed, create a forms.py (since a filter is a type of form), and inside it add the following:
import django_filters
from .models import Property
class PropertyFilter(django_filters.FilterSet):
class Meta:
model = Property
Then, you have to wire it up from your views.py:
from .forms import PropertyFilter
def search(request):
f = PropertyFilter(request.GET, Property.objects.all())
return render(request, 'search.html', {'filter': f})
Your template search.html:
<form method="GET" role="form">
{{ f.form }}
<input type="submit" />
</form>
{% if f|length %}
{% for obj in f %}
{{ obj }}
{% endfor %}
{% else %}
Sorry, no results for your search criteria
{% endif %}
Related
I got 3 models, one with auctions, second with watchlist, third with users
class Auctions(models.Model):
lot = models.CharField(max_length=64)
owner = models.CharField(max_length=64)
url = models.CharField(max_length=256, blank = True)
startBid = models.IntegerField()
description = models.CharField(max_length=64)
category = models.CharField(max_length=64, blank = True)
class User(AbstractUser):
pass
class Watchlist(models.Model):
user = models.CharField(max_length=64)
watchlist = models.CharField(max_length=64, blank = True)
Views:
def addToWatchlist(request, id):
print(id, "ID")
user = request.user
watchlist = Watchlist.objects.filter(user = user, watchlist = id)
data = list(watchlist)
if data == []:
createWatchList = Watchlist(
user = request.user,
watchlist = id
)
createWatchList.save()
else:
watchlist.delete()
return redirect('listing', id=id)
def watchlist(request):
id = Watchlist.objects.filter(user = request.user)
auctions = Auctions.objects.filter(id = id)
return render(request, "auctions/watchlist.html", {
"auctions": auctions
})
I receive an error "ValueError: The QuerySet value for an exact lookup must be limited to one result using slicing."
Can someone explain how to pass multiple QuerySet values into filter()
As a result, I need all auctions, that's a match the watchlist
Thank you!
Try this:
watchlist_id = Watchlist.objects.filter(user = request.user).values('id')
auctions = Auctions.objects.filter(id__in = watchlist_id).all()
Here we first filter watchlist_id and then it contain (id__in) in auctions table.
I have added like and dislike button to Song post When like object is not created if some click on like it is showing intigrity error if like object is already there then it is not rendering that to template.
models.py
Codes in models.py
class Song(models.Model):
song_title = models.CharField(max_length=25)
album = models.ForeignKey(Album, related_name='album_name', on_delete=models.CASCADE, blank=True)
singer = models.ManyToManyField(Singer, blank=True)
language = models.CharField(max_length=25)
class VoteManager(models.Manager):
def get_vote_or_unsaved_blank_vote(self,song,user):
try:
return Vote.objects.get(song=song,user=user)
except ObjectDoesNotExist:
return Vote(song=song,user=user)
class Vote(models.Model):
UP = 1
DOWN = -1
VALUE_CHOICE = ((UP, "👍️"),(DOWN, "👎️"),)
like = models.SmallIntegerField(choices=VALUE_CHOICE)
user = models.ForeignKey(User,on_delete=models.CASCADE)
song = models.ForeignKey(Song, on_delete=models.CASCADE)
voted_on = models.DateTimeField(auto_now=True)
objects = VoteManager()
class Meta:
unique_together = ('user', 'song')
views.py
Codes in views.py
class SongDetailView(DetailView):
model = Song
template_name = 'song/song_detail.html'
def get_context_data(self,**kwargs):
ctx = super().get_context_data(**kwargs)
if self.request.user.is_authenticated:
vote = Vote.objects.get_vote_or_unsaved_blank_vote(song=self.object, user = self.request.user)
if vote.id:
vote_url = reverse('music:song_vote_update', kwargs={'song_id':vote.song.id,'pk':vote.id})
else:
vote_url = reverse('music:song_vote_create', kwargs={'song_id':vote.song.id})
vote_form = SongVoteForm(instance=vote)
ctx['vote_form'] = vote_form
ctx['vote_url'] = vote_url
return ctx
class SongUpdateView(UpdateView):
form_class = SongVoteForm
queryset = Song.objects.all()
def get_object(self,queryset=None):
song = super().get_object(queryset)
user = self.request.user
return song
def get_success_url(self):
song_id = self.kwargs.get('song_id')
return reverse('music:song_detail', kwargs={'pk':song_id})
class SongVoteCreateView(View):
form_class = SongVoteForm
context = {}
def post(self,request,pk=None,song_id=None):
vote_obj,created = Vote.objects.get_or_create(pk=pk)
song_obj = Song.objects.get(pk=song_id)
vote_form = SongVoteForm(request.POST, instance=vote_obj)
if vote_form.is_valid():
new_vote = vote_form.save(commit=False)
new_vote.user = self.request.user
new_vote.song = song_obj
return redirect('/album/')
Song_detail.html
codes in song_detail.html
<form action="{{vote_url}}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ vote_form.as_p }}
<button class="btn btn-primary" type="submit" >Vote</button>
</form>
Error Code
This is the error when submitting the like button. Refer here for the traceback
NOT NULL constraint failed: album_vote.song_id
song and user fields are required. So you have to give song and user while creating Vote.
here is full code::
class SongVoteCreateView(View):
form_class = SongVoteForm
context = {}
def post(self,request,pk=None,song_id=None):
song_obj = Song.objects.get(pk=song_id)
vote_obj,created = Vote.objects.get_or_create(song = song_obj, user = request.user)
vote_form = SongVoteForm(request.POST, instance=vote_obj)
if vote_form.is_valid():
vote_form.save()
return redirect('/album/')
also in VoteManager, the code
return Vote(song=song,user=user)
won't create vote, instead you have to use
return Vote.objects.create(song=song,user=user)
I have two models many to many relationships, I am trying to update a field by subtraction two values from the two models and save the changes to the db.
class LeaveBalance(models.Model):
user=models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True,)
Leave_current_balance= models.FloatField(null=True, blank=True, default=None)
Year=models.CharField(max_length=100,default='')
def __unicode__(self):
return self.Year
class NewLeave(models.Model):
user=models.ForeignKey(User,default='',on_delete=models.CASCADE)
leave_balance=models.ManyToManyField(Leave_Balance)
leave=(
('annual','annual'),
('sick','sick'),
)
Leave_type=models.CharField(max_length=100,choices=leave,blank=False,default='')
Total_working_days=models.FloatField(null=True, blank=False)
DirAuth=(
('Pending','Pending'),
('Approved','Approved'),
('Rejected','Rejected'),
)
Director_Authorization_Status=models.CharField(max_length=100,choices=DirAuth,default='Pending',blank=False)
Date_Authorized=models.DateField(null=True,blank=False)
Authorized_by_Director=models.CharField(max_length=100,default='',blank=False)
def __unicode__(self):
return self.Leave_type
here is my form, when a leave is submitted the director is notified by email. the director can login to the system to approve the leave using the form. once the leave is approved, I want to adjust the Leave_current_balance.
class DirectorForm(forms.ModelForm):
class Meta:
model=NewLeave
fields=('Director_Authorization_Status','Authorized_by_Director','Date_Authorized',)
widgets={
'Date_Authorized':DateInput()
}
This is the function that allows the director to approve the leave which throws the error: u'Leave_current_balance'
def unitDirectorForm(request,id):
if request.method=='POST':
getstaffid=NewLeave.objects.get(id=id)
form = DirectorForm(request.POST, instance=getstaffid)
if form.is_valid():
getstaffid = form.save(commit=False)
getstaffid.save()
total_days = getstaffid.Total_working_days
current_balance = getstaffid.user.leave_balance.Leave_current_balance
diff_balance = current_balance - total_days
current_balance = diff_balance
current_balance=form.fields['Leave_current_balance']
current_balance.save()
getstaffid.leave_balance.add(current_balance)
return HttpResponse('You have successfuly Authorise the leave')
else:
#getstaffid=NewLeave.objects.get(id=id)
form=DirectorForm()
#c_balance=Leave_Balance.objects.get()
balance_form = leavebbalanceForm()
return render(request,'managerauthorisedform.html',{'form':form})
You could get this working in another way too. For example:
def on_balance(user_id):
id = user_id
c_balance = LeaveBalance.objects.get(user=id)
current_balance = c_balance.Leave_current_balance
t_days = NewLeave.objects.get(user=id)
total_days = t_days.Total_working_days
current_balance = current_balance - total_days
balance = LeaveBalance.objects.get(user=id)
balance.leave_balance = current_balance
balance.save()
And the above does not cause combined expression error.
Or just a bit simpler:
def on_balance(user_id):
id = user_id
c_balance = LeaveBalance.objects.get(user=id)
current_balance = c_balance.Leave_current_balance
t_days = NewLeave.objects.get(user=id)
total_days = t_days.Total_working_days
current_balance = current_balance - total_days
c_balance.leave_balance = current_balance
c_balance.save()
UPDATE - restructuring the models and views
So the above code works if it's used in an appropriate model/form/view structure, but instead I would suggest you to restructure the whole thing starting from your models. I give you a simple working example (I tested this and works):
My app name is in this example: Myusers1 , so where ever you see that, you can change that name to your app name if needed.
So the Models:
from django.db import models
from django.conf import settings
from django.utils.text import slugify
from django.db.models import F
from django.urls import reverse
class Director(models.Model):
name = models.CharField(max_length = 100, default = '', null = True, verbose_name = 'Name of Director')
def __str__(self):
return self.name
class Staff(models.Model):
TYPE_CHOICES = (
('REGULAR', 'Regular'),
('MANAGER', 'Manager'),
('FRESH', 'Fresh'),
)
name = models.CharField(max_length = 100, default = '', null = True, unique=True, verbose_name = 'Name of staff member')
birthdate = models.DateField(blank = True, verbose_name = 'Birth date')
department = models.CharField(max_length = 100, default = '', null = True, verbose_name = 'Department')
# department could also be a choice field from another table
type = models.CharField(max_length = 20, choices = TYPE_CHOICES, verbose_name = 'Position Type', null = True)
def __str__(self):
return self.name
class LeaveBalance(models.Model):
staff = models.ForeignKey(Staff, to_field='name', on_delete = models.CASCADE, primary_key = False)
Leave_current_balance = models.FloatField(null = True, blank = True, default = '')
date_updated = models.DateTimeField(auto_now_add = True, verbose_name = 'Last Updated date and time')
def __unicode__(self):
return self.Leave_current_balance
class NewLeave(models.Model):
all_staff = Staff.objects.values()
STAFF_CHOICES = [(d['name'], d['name']) for d in all_staff]
staff = models.CharField(max_length = 100, choices = STAFF_CHOICES)
leave_days_to_approve_now = models.FloatField(null = True, blank = False, default = 5.0, verbose_name = 'Leave days for approval now')
LEAVE_CHOICES=(
('annual','annual'),
('sick','sick'),
)
Leave_type = models.CharField(max_length = 100, choices = LEAVE_CHOICES, blank = False, default = '', verbose_name = 'Type of leave')
Total_working_days = models.FloatField(null = True, blank = False, default = 200.0)
APPROVAL_STATUS_CHOICES=(
('Pending','Pending'),
('Approved','Approved'),
('Rejected','Rejected'),
)
Director_Authorization_Status = models.CharField(max_length = 100, choices = APPROVAL_STATUS_CHOICES, default = 'Pending', blank = False)
Date_Authorized = models.DateTimeField(auto_now_add = True, verbose_name = 'date and time of Authorization')
all_directors = Director.objects.values()
DIRECTOR_CHOICES = [(d['name'], d['name']) for d in all_directors]
Authorized_by_Director = models.CharField(max_length = 100, choices = DIRECTOR_CHOICES, default = '', blank = False)
def __unicode__(self):
return self.Leave_type
def get_absolute_url(self):
pass
# return reverse('newleave-detail', kwargs={'pk': self.pk}) # this should be worked out too
def save(self, *args, **kwargs):
staff_name = self.staff
this_staff = Staff.objects.get(name=staff_name)
name = this_staff.name
minus_value = self.leave_days_to_approve_now
if (self.Director_Authorization_Status == 'Approved'):
LeaveBalance.objects.filter(staff = name).update(Leave_current_balance=F('Leave_current_balance') - minus_value)
return super(NewLeave, self).save(*args, **kwargs)
else:
return super(NewLeave, self).save(*args, **kwargs)
In the above, you can see that I created a Director and Staff Model in which you can set as many staff and directors as you want in the Admin back-end. I created the staff Model because maybe not all of the staff will be users, so I think it is just a bit better to keep them separately in the DB from Users.
Important: first create the Director and Staff Models then migrate immediately since the other two tables will depend on them. Then you can create the other two Models.
I also do not think that in the LeaveBalance Model you should keep more things than what I put there. I think Year field for example redundant, since you can always filter by the date and date range in you want in the database.
Then the views (I used simple views only directly from the Models). With using these view classes you do not have to create Forms since it is automatically created from the Models and you can handle them with different functions/methods as Forms in the Views and in the Model classes.
from django.shortcuts import render, redirect
from django.http import HttpResponseRedirect, HttpResponse, HttpRequest
from django.urls import reverse
from django.views import View
from django.views.generic.detail import DetailView
from django.views.generic import ListView, TemplateView
from django.template import loader
from .models import NewLeave
from django.views.generic.edit import FormView, CreateView, DeleteView, UpdateView
from django.urls import reverse_lazy
class NewLeaveCreate(CreateView):
model = NewLeave
fields = '__all__'
def form_valid(self, form):
super().form_valid(form)
auth_status = form.cleaned_data['Director_Authorization_Status']
if (auth_status == 'Approved'):
return redirect('Myusers1:success_page')
elif (auth_status == 'Pending'):
return redirect('Myusers1:pending_success')
else:
return redirect('Myusers1:rejected_success')
class NewLeaveUpdate(UpdateView):
model = NewLeave
fields = '__all__'
class NewLeaveDelete(DeleteView):
model = NewLeave
success_url = reverse_lazy('newleave-list')
class NewLeaveDetail(DetailView):
model = NewLeave
template_name = 'myusers1/newleave_detail.html'
context_object_name = 'newleave'
queryset = NewLeave.objects.all()
def get_context_data(self, **kwargs):
context = super(NewLeaveDetail, self).get_context_data(**kwargs)
context['leave_details'] = NewLeave.objects.filter(pk=pk)
return context
class Success(TemplateView):
template_name = "authorizationsuccess.html"
class pending_success(TemplateView):
template_name = "pendingsuccess.html"
class rejected_success(TemplateView):
template_name = "rejectedsuccess.html"
Then in urls.py I defined the required urls:
from django.urls import path, re_path
from . import views
from . import models
app_name = 'Myusers1'
urlpatterns = [
path('newleave/add/', views.NewLeaveCreate.as_view(), name='newleave-add'),
path('newleave/<int:pk>/', views.NewLeaveUpdate.as_view(), name='newleave-update'),
path('newleave/<int:pk>/delete/', views.NewLeaveDelete.as_view(), name='newleave-delete'),
# path('newleave/add/<int:pk>/', views.NewLeaveDetail.as_view(), name='newleave-detail'),
path('newleave/add/success/', views.Success.as_view(), name='success_page'),
path('newleave/add/pendingleaves/', views.pending_success.as_view(), name='pending_success'),
path('newleave/add/rejectedleaves/', views.rejected_success.as_view(), name='rejected_success'),
]
I have not worked out all of the url paths.
And the templates like the newleave_form.html
{% extends 'myusers1/base.html' %}
{% block content %}
<div class"container">
<div class="col col-lg-2">
<h2>New Leave Form</h2>
<form method="post">
{% csrf_token %}
{{ form }}
<button type="submit">Authorize</button>
</form>
</div>
</div>
{% endblock %}
And there should be at least 3 different redirect template when a they submit a NewLeave form, authorized, pending, and rejected templates. I just give here the simple authorized success template:
{% extends 'myusers1/base.html' %}
{% block content %}
<h2>Thank you! The authorization of leave was successful</h2>
<div class="col-xs-12 .col-md-8"><li> Back to Home </li></div>
{% endblock %}
Do not forget to migrate and then register the models in the admin.py. Then you should create some staff in the database and few directors to try the above. I hope that the above can give you some direction to accomplish what you are up to with your project. With this I just wanted to give you a very simple example. (You have to create all of the other necessary templates and views).
If you create a new app for trying the above then in your project main urls.py file you should reference (include) your app urls like this with adding one extra line to your project' urls.py file. Then all of your new app urls has to be defined in your app's urls.py file:
This is how your main project's urls.py looks like then:
urlpatterns = [
path('admin/', admin.site.urls),
path('myusers1/', include('Myusers1.urls')),
# so in your case:
path('myapp/', include('myapp.urls')),
]
(you have to change the Myusers1 to your app name,)
And of course we could do a lot of other things with the Model Manager in Django: https://docs.djangoproject.com/en/2.1/topics/db/managers/
You have to call refresh_from_db on balance. like balance.refresh_from_db() to get the updated values from database.
Can someone help me with fixing Django ModelForm?
This particular code can add new item to database as expected, but when I'm trying to edit db record - It just add new record, instead of updating old. I'm quite new in Django framework.
views.py:
def manage(request, item_id = None):
t = get_object_or_404(Hardware, id=item_id) if item_id else None
form = Manage(request.POST or None, instance=t)
if t:
if form.is_valid():
#form.save()
hostname = form.cleaned_data['hostname']
cpu = form.cleaned_data['cpu']
os = form.cleaned_data['os']
ram = form.cleaned_data['ram_total']
storage = form.cleaned_data['storage']
hostdata = Hardware(
hostname=hostname,
cpu=cpu,
ram_total=ram,
os=os,
storage=storage,
lock_state=t.lock_state, # because in edit operation we shouldn't change it.
lock_date=t.lock_date, # because in edit operation we shouldn't change it.
locked_by=t.locked_by) # because in edit operation we shouldn't change it.
hostdata.save()
return HttpResponseRedirect(reverse('main:index'))
elif not t:
if form.is_valid():
hostname = form.cleaned_data['hostname']
cpu = form.cleaned_data['cpu']
os = form.cleaned_data['os']
ram = form.cleaned_data['ram_total']
storage = form.cleaned_data['storage']
current_user = request.user
user = User.objects.get(id=current_user.id)
hostdata = Hardware(
hostname=hostname,
cpu=cpu,
ram_total=ram,
os=os,
storage=storage,
lock_state=0,
lock_date=datetime.datetime.now(),
locked_by=user)
hostdata.save()
return HttpResponseRedirect(reverse('main:index'))
return render(request, 'hardware/edit.html', {'form': form})
models.py:
class Hardware(models.Model):
hostname = models.CharField(max_length=255, default=None)
os = models.CharField(max_length=255, default=None)
cpu = models.CharField(max_length=255, default=None)
ram_total = models.CharField(max_length=255, default=None)
storage = models.CharField(max_length=255, default=None)
lock_state = models.BooleanField(default=0)
locked_by = models.ForeignKey(User)
lock_date = models.DateTimeField(default=None)
alive = models.BooleanField(default=0)
class Meta:
db_table = "hardware"
def __str__(self):
return self.hostname
forms.py:
class Manage(forms.ModelForm):
class Meta:
model = Hardware
fields = ['hostname', 'os', 'cpu', 'ram_total', 'storage']
urls.py:
url(r'^manage/new/$', views.manage, name='add'),
url(r'^manage/edit/(?P<item_id>[0-9]+)/$', views.manage, name='edit')
template:
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save!" />
</form>
You already retrieved the instance t in the first line of your view. The code below will always create a new instance (unless you specify the pk parameter):
hostdata = Hardware(...)
hostdata.save()
Simply do this instead:
if t:
if form.is_valid():
t.hostname = form.cleaned_data['hostname']
t.cpu = form.cleaned_data['cpu']
....
t.save()
However, you really should rely on the save method provided by the ModelForm as the other answers suggested. Here's an example:
def manage(request, item_id=None):
t = get_object_or_404(Hardware, id=item_id) if item_id else None
# if t is None, a new object will be created in form.save()
# if t is an instance of Hardware, t will be updated in form.save()
form = Manage(request.POST, instance=t)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('main:index')
return render(request, 'hardware/edit.html', {'form': form})
You also specified fields in your form:
fields = ['hostname', 'os', 'cpu', 'ram_total', 'storage']
These are the fields which will be set or updated when you call form.save().
I think something like this - using update_fields - should work:
def manage(request, item_id = None):
t = get_object_or_404(Hardware, id=item_id)
form = Manage(request.POST or None, instance=t)
if t:
if form.is_valid():
#form.save()
t.hostname = form.cleaned_data['hostname']
t.cpu = form.cleaned_data['cpu']
t.os = form.cleaned_data['os']
t.ram = form.cleaned_data['ram_total']
t.storage = form.cleaned_data['storage']
t.save(update_fields=['hostname', 'cpu', 'os','ram','storage'])
return HttpResponseRedirect(reverse('main:index'))
........
Try Class Based View, which in it's simplest looks like:
from django.views import generic
class HardwareEditView(generic.UpdateView):
template_name = "hardware.html"
form_class = Manage
You will have to add get_absolute_url to the model.
Generic class based views are exactly for this standard create/update/view common tasks.
As I want to filter on foreign key, I used carmodel with __ in the method dropdownlistsearch() of views.py. When run the code, it tells it must be a field. I don't understand this part. Why do I get this error. And I am using django 1.6.5.
models.py
from django.db import models
class CarInfo(models.Model):0
vin_number = models.CharField(max_length = 17)
model = models.ForeignKey(CarModel)
timestamp = models.DateTimeField(auto_now_add = True, auto_now = False)
updated = models.DateTimeField(auto_now_add = False, auto_now = True)
def __unicode__(self):
return self.vin_number
class CarModel(models.Model):
model = models.CharField(max_length = 60)
def __unicode__(self):
return self.model
views.py
def dropdownsearch(request):
try:
q = request.GET.get('q')
except:
q = None
if q:
cars = CarInfo.objects.filter(carmodel__model__contains=q)
template ='productions/resultstwo.html'
else:
template = 'prodcutions/cars.html'
context = {}
return render(request,template,context)
cars.html
<form action="/cars/s/" method="get">
<select name="q">
{% for info in modelinfos %}
<option value="{{info.model}}">{{info.model}}</option>
{% endfor %}
</select>
</form>
You are filtering on the forward relationship, so you use the actual field you have defined, model.
CarInfo.objects.filter(model__model__contains=q)
def testform(request):
form = CarInfo(request.POST or None)
if form.is_valid():
save_it = form.save(commit = False)
save_it.save()
return render_to_response("productions/testform.html",locals(),context_instance = RequestContext(request))