Hello I have a django project for calorie tracker and when I go to fooditem_create url I get this error :
FoodItemCreateView is missing a QuerySet. Define FoodItemCreateView.model, FoodItemCreateView.queryset, or override FoodItemCreateView.get_queryset().
this is my views:
from .forms import *
from django.urls import reverse_lazy
from .models import *
from accounts.models import CustomUser
from django.views import generic
from django.views.generic import ListView
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
class FoodItemCreateView(LoginRequiredMixin, generic.CreateView):
mode = Fooditem
template_name = 'fooditem_create.html'
fields = "__all__"
success_url = reverse_lazy('fooditem_list.html')
class FoodItemListView(LoginRequiredMixin,ListView):
model = Fooditem
template_name = 'fooditem_list.html'
fields = "__all__"
class FoodItemDeleteView(LoginRequiredMixin,generic.DeleteView):
model = Fooditem
template_name = 'fooditem_delete.html'
success_url = reverse_lazy('fooditem_list.html')
#login_required(login_url='login')
def SelectFoodCreateView(request):
usernow = CustomUser.objects.get(id=request.user.id)
form = selectfoodForm(request.user, instance=usernow)
if request.method == "POST":
form = selectfoodForm(request.user, request.POST, instance=usernow)
if form.is_valid():
name = form.cleaned_data.get('name')
category = form.cleaned_data.get('category')
quantity = form.cleaned_data.get('quantity')
person = form.cleaned_data.get('person')
selectedfood = Selectfooditem.objects.create(
name=name, quantity=quantity, category=category, person=person)
selectedfood.save()
return redirect('/manage/profile')
else:
form = selectfoodForm(request.user)
context = {'form': form}
return render(request, 'addfood_create.html', context)
#login_required(login_url='login')
def ProfileView(request):
usernow = CustomUser.objects.get(id=request.user.id)
calorielimit = usernow.calorielimit
selectedfood = Selectfooditem.objects.filter(person=request.user)
calorieconsumed = 0
calorieleft = calorielimit
for food in selectedfood :
calorieconsumed+= (food.name.calorie * food.quantity)
calorieleft = calorielimit - calorieconsumed
context = { 'Food selected by {user}':selectedfood ,'Calorielimit':calorielimit , 'Calorieconsumed': calorieconsumed , 'calorieleft' : calorieleft}
return render(request, 'profile.html', context)
class DeleteFoodView(LoginRequiredMixin,generic.DeleteView):
model = Selectfooditem
template_name = 'deletefoodview_delete.html'
success_url = reverse_lazy('profile')
#login_required(login_url='login')
def EditCalorielimitView(request):
if request.method == 'POST':
user = CustomUser.objects.get(id=request.user.id)
user.calorielimit = request.POST.get('calorielimit')
user.save()
return redirect('manage/profile')
return render(request, 'calorielimit_edit.html')
my html template:
{% extends 'base.html' %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<button class="btn btn-success ml-2" type="submit">Save</button>
</form>
{% endblock content %}>
and my models:
from django.db import models
from accounts.models import CustomUser
class Fooditem(models.Model):
name = models.CharField(max_length=200)
calorie = models.PositiveIntegerField(default=0)
carbs = models.FloatField(default=0,null=True,blank=True)
protein = models.FloatField(default=0,null=True,blank=True)
fat = models.FloatField(default=0,null=True,blank=True)
person = models.ForeignKey(CustomUser,on_delete=models.CASCADE)
def __str__(self):
return str('{name} ({cal} calorie)'.format(name=self.name, cal=self.calorie))
class Selectfooditem(models.Model):
option=(
('breakfast','breakfast'),
('lunch','lunch'),
('dinner','dinner'),
('snacks','snacks'),
)
name=models.ForeignKey(Fooditem,on_delete=models.CASCADE)
category=models.CharField(max_length=50,choices=option)
quantity = models.PositiveIntegerField(default=1)
person = models.ForeignKey(CustomUser,on_delete=models.CASCADE)
I searched for the error and I think this error is for listview not for createview
its just a typo
class FoodItemCreateView(LoginRequiredMixin, generic.CreateView):
mode = Fooditem
mode should be model=...
Related
So i have a model called folder, i want to show all the folder created by current user on HomeView, but somehow it's not working, what i think is that folders are not getting connected to user who created them.
models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.deletion import CASCADE
from django.core.validators import MinValueValidator
from django.core.exceptions import PermissionDenied
# The Folders Model.
class Folder(models.Model):
name = models.CharField(max_length = 250)
parent = models.ForeignKey('self', on_delete = CASCADE, null = True, blank = True )
cr_date = models.DateTimeField(auto_now_add = True)
user = models.OneToOneField(to=User, on_delete=CASCADE, null=True, blank=True)
def __str__(self):
return "%s" % self.name
view.py
class HomeView(TemplateView):
template_name = "ahmed_drive/home.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
user = self.request.user
home_folders = Folder.objects.filter(user=user).order_by('-cr_date')
home_files = Fileshare.objects.filter(uploaded_by=user).order_by('-id')
context['home_folders'] = home_folders
context['home_files'] = home_files
return context
#method_decorator(login_required, name="dispatch")
class FolderCreate(CreateView):
model = Folder
fields = ["name", "parent"]
def formvalid():
if form.is_valid():
form.save()
return redirect('home.html')
else :
return render(request,{'form': form})
home.html
{% extends 'base.html' %}
{% block content %}
{% for Folder in home_folders %}
<h1> {{Folder.name}} </h1>
{% endfor %}
{% endblock %}
when you create folder you don't connect user to it.
you need to do it before saving form
def form_valid(self, form):
folder = form.save(commit=False)
folder.user = request.user
folder.save()
return redirect('home.html')
I'm a Django beginner and try to implement a class based CreateView with two forms and an OneToOne relation but have no glue how to do this in one view.
For example: the following is given:
#models.py
# some imports..
class RedItem(models.Model):
name = models.Charfield(max_length=255)
storage = models.OneToOneField("Storage", on_delete=models.CASCADE)
class BlueItem(models.Model):
name = models.Charfield(max_length=255)
storage = models.OneToOneField("Storage", on_delete=models.CASCADE)
class Storage(models.Model):
shelf = models.Charfield(max_length=255)
room = models.Charfield(max_length=255)
...the View:
#views.py
from django.views.generic.edit import CreateView
from .models import RedItem, BlueItem, Storage
# some other imports..
class RedItemCreate(CreateView):
model = RedItem
fields = ['name']
template_name_suffix = "_form"
```html
and a Form:
```html
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save">
</form>
The question is now how can a user fill in both (e.g. RedItem + Storage) in one batch?
Thanks in advance for any direction.
Update and a working approach:
I have to create forms in forms.py and add it the the CreateView.
#urls.py
from django.urls import path
from .views import *
urlpatterns = [
path('reditemlist/', ExampleList.as_view(), name='example_list'),
path('reditemcreate/', ExampleCreate.as_view(), name='example_create')
]
#forms.py
from django.forms import ModelForm
from .models import RedItem, Storage
class RedItemForm(ModelForm):
class Meta:
model = RedItem
fields = ['name']
class StorageForm(ModelForm):
class Meta:
model = Storage
fields = ['shelf']
And the CreateView:
#views.py
from django.shortcuts import render
from django.views.generic.list import ListView
from django.views.generic.edit import CreateView
from .models import *
from .forms import *
from django.urls import reverse_lazy
class ExampleList(ListView):
model = RedItem
class ExampleCreate(CreateView):
model = RedItem
form_class = RedItemForm
success_url = reverse_lazy('example_list')
def get_context_data(self, **kwargs):
context = super(ExampleCreate, self).get_context_data(**kwargs)
if self.request.POST:
context['reditem'] = RedItemForm(self.request.POST)
context['storage'] = StorageForm(self.request.POST)
else:
context['reditem'] = RedItemForm()
context['storage'] = StorageForm()
return context
def form_valid(self, form):
context = self.get_context_data()
storage = context['storage']
if storage.is_valid() and form.is_valid():
f = form.save()
shelf = storage.save(commit = False)
shelf.reditem = f
shelf.save()
return super().form_valid(form)
<form method="post">{% csrf_token %}
{{ form.as_p }}
{{ storage.as_p }}
<input type="submit" value="Save">
</form>
Next stop: UpdateView
1
I'm working on Django. I'm getting the error below. I didn't find the solution despite the much increased.Please refer the this link for trace back
Codes in views.py
class UpdateVote(LoginRequiredMixin,UpdateView):
form_class = VoteForm
queryset = Vote.objects.all()
def get_object(self,queryset=None):
vote = super().get_object(queryset)
user = self.request.user
if vote.user != user:
raise PermissionDenied('can not change another user vote')
return vote
def get_success_url(self):
movie_id = self.object.movie.id
return reverse('core:movie_detail', kwargs={'pk':movie_id})
def render_to_response(self, context, **response_kwargs):
movie_id = context['object'].id
movie_detail_url = reverse('core:movie_detail',kwargs={'pk':movie_id})
return redirect(to=movie_detail_url)
class MovieDetail(DetailView):
queryset = Movie.objects.all_with_prefetch_persons()
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(movie=self.object,user=self.request.user)
if vote.id:
vote_url_form = reverse('core:UpdateVote',kwargs={'movie_id':vote.movie.id,'pk':vote.id})
else:
vote_url_form = (reverse('core:create_vote',kwargs={'movie_id':self.object.id}))
vote_form = VoteForm(instance=vote)
ctx['vote_form'] = vote_form
ctx['vote_url_form'] = vote_url_form
return ctx
Codes in form.py
I have used this form to link with UpdateView
from django import forms
from django.contrib.auth import get_user_model
from .models import Movie,Vote
class VoteForm(forms.ModelForm):
user = forms.ModelChoiceField(widget=forms.HiddenInput,queryset=get_user_model().objects.all(),disabled=True)
movie = forms.ModelChoiceField(widget=forms.HiddenInput,queryset = Movie.objects.all(),disabled=True)
value = forms.ChoiceField(widget=forms.RadioSelect,choices=Vote.VALUE_CHOICE)
class Meta:
model = Vote
fields = ('value','user','movie',)
urls.py
This is the url mapping for the view.
from django.contrib import admin
from django.urls import path
from .views import MovieList,MovieDetail,PersonDetail,CreateVote,UpdateVote
app_name = 'core'
urlpatterns = [
path('movies/', MovieList.as_view(), name='movie_list'),
path('movie/<int:pk>/', MovieDetail.as_view(), name='movie_details'),
path('person/<int:pk>/', PersonDetail.as_view(), name='person_details'),
path('movie/<int:movie_id>/vote/', CreateVote.as_view(), name='create_vote'),
path('movie/<int:movie_id>/vote/<int:pk>', UpdateVote.as_view(), name='UpdateVote'),
]
HTML template
This is the template I used.
{% block sidebar %}
<div>
{% if vote_form %}
<form action="{{vote_form_url}}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ vote_form.as_p }}
<button class="btn btn-primary" type="submit" >Vote</button>
</form>
{% else %}
<p>Login to vote for this movie</p>
{% endif %} </div> {% endblock %}
Your UpdateVote view is using VoteForm and the queryset on that view is from Vote model, so that the object field inside that view is the instance of Vote model, not Movie model.
This code movie_id = context['object'].id also not work because context might not included object of UpdateVote view, that caused the error KeyError, Exception Value: 'object'. You could get movie_id via kwargs field inside UpdateVote view because you've already defined movie_id in the path.
With this:
path('movie/<int:movie_id>/vote/<int:pk>', UpdateVote.as_view(), name='UpdateVote'),
Your view can get the values by using kwargs like so:
class UpdateVote(LoginRequiredMixin,UpdateView):
form_class = VoteForm
queryset = Vote.objects.all()
def get_object(self,queryset=None):
vote = super().get_object(queryset)
user = self.request.user
if vote.user != user:
raise PermissionDenied('can not change another user vote')
return vote
def get_success_url(self):
movie_id = self.kwargs.get('movie_id')
return reverse('core:movie_detail', kwargs={'pk':movie_id})
def render_to_response(self, context, **response_kwargs):
movie_id = self.kwargs.get('movie_id')
movie_detail_url = reverse('core:movie_detail',kwargs={'pk':movie_id})
return redirect(to=movie_detail_url)
My problem is similar to how to edit model data using django forms, but I'm not able to solve it.
I would like to get an form with prefielled fields and to allow user to edit them.
I believe my problem is in views.py file, but unfrotuntely I'm not able to solve it.
models.py
from django.db import models
class Item(models.Model):
product = models.CharField(max_length=150)
quantity = models.DecimalField(max_digits=8, decimal_places=3)
price = models.DecimalField(max_digits=7, decimal_places=2)
purchase_date = models.DateTimeField()
warranty = models.DecimalField(max_digits=4, decimal_places=1)
comment = models.TextField()
forms.py
from django import forms
from items.models import Item
class EditItemForm(forms.ModelForm):
class Meta:
model = Item
fields = ('product','quantity', 'price', 'purchase_date', 'warranty', 'comment')
urls.py
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^show_all/$', 'items.views.items'),
url(r'^(?P<item_id>\d+)/$', 'items.views.item'),
url(r'^edit/(?P<item_id>\d+)/$', 'items.views.edit'),
)
edit.html
<form action="/items/edit/" method="post" class="form horizontal well">{% csrf_token %}
{{ form.as_p }}
<imput type="submit" class="btn btn-inverse" value="Aktualizuj">
</form>
views.py
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from items.models import Item
from decimal import Decimal
from django.core.context_processors import csrf
from items.forms import EditItemForm
def edit(request):
if request.method == 'POST':
form = EditItemForm(request.POST, instance=request.item)
if form.is_valid():
form.save()
return HttpResponseRedirect('/items/show_all/')
else:
form = EditItemForm(instance=item)
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('edit.html', args)
Above code is resulting this message:
TypeError at /items/edit/1/
edit() got an unexpected keyword argument 'item_id'
Can you please help me?
Django 1.6, Python 3.4
You've imagined an attribute called request.item. There's no such thing. You need to get the item from the database, via the ID passed into the function as alecxe showed.
def edit(request, item_id):
item = Item.objects.get(pk=item_id)
if request.method == 'POST':
form = EditItemForm(request.POST, instance=item)
edit() view should allow a keyword argument item_id:
def edit(request, item_id=None):
if request.method == 'POST':
...
I'm trying to write a form clean method to ensure that an entered pair of dates is not currently covered by date ranges stored in the model.
So I want to catch fromdate >= value <= todate but the between filters in my clean methods aren't getting it.
Can anyone offer some enlightenment?
Models.py
class Dates(models.Model):
fromdate = models.DateField()
todate = models.DateField()
Forms.py
class Form(forms.Form):
fromdate = forms.DateField()
todate = forms.DateField()
class Meta:
model = Dates
def clean_fromdate(self):
form_fromdate = self.cleaned_data.get('fromdate')
exists = Dates.objects.filter(fromdate__contains=form_fromdate).exists()
if exists == True:
raise forms.ValidationError(_("A period is already entered for this date"))
between = Dates.objects.filter(fromdate__gte=form_fromdate,
todate__lte=form_fromdate).exists()
if between == True:
raise forms.ValidationError(_("Period already between this date 1"))
return form_fromdate
def clean_todate(self):
form_todate = self.cleaned_data.get('todate')
exists = Dates.objects.filter(todate__contains=form_todate).exists()
if exists == True:
raise forms.ValidationError(_("A period is already entered for this date"))
between = PeriodsOfInactivity2012.objects.filter(fromdate__gte=form_todate,
todate__lte=form_todate).exists()
if between == True:
raise forms.ValidationError(_("Period already between this date 2"))
return form_todate
This should work for you
from django import forms
from models import Dates
class Form(forms.ModelForm):
fromdate = forms.DateField()
todate = forms.DateField()
class Meta:
model = Dates
def clean(self):
form_fromdate = self.cleaned_data.get('fromdate')
form_todate = self.cleaned_data.get('todate')
between = Dates.objects.filter(fromdate__gte=form_fromdate, todate__lte=form_todate).exists()
if between:
raise forms.ValidationError("Period already between this dates")
super(Form, self).clean()
EDIT
#views.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django.http import HttpResponse
from django.template import RequestContext
from django.shortcuts import render_to_response
from forms import Form
def index(request, template='index.html'):
form = Form()
if request.method == "POST":
form = Form(request.POST)
if form.is_valid():
return HttpResponse(form)
kwvars = {
"form": form,
}
return render_to_response(template, kwvars, context_instance=RequestContext(request))
#forms.py
from django import forms
from models import Dates
class Form(forms.ModelForm):
fromdate = forms.DateField()
todate = forms.DateField()
class Meta:
model = Dates
def clean(self):
form_fromdate = self.cleaned_data.get('fromdate')
form_todate = self.cleaned_data.get('todate')
between = Dates.objects.filter(fromdate__gte=form_fromdate, todate__lte=form_todate).exists()
if between:
raise forms.ValidationError("Period already between this date 1")
super(Form, self).clean()
#index.html
<html>
<head>
</head>
<body>
<form action="" method="POST">
{% csrf_token %}
{% if form.errors %}
errors: {{ form.errors }}
{% endif %}
{{ form }}
<input type="submit" value="submit">
</form>
</body>
</html>