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
Related
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=...
I want to filter apartments by selecting subcity field in a dropdown in my django app. I'm using django-filters and django-bootstrap-form. But the dropdown does not populate with database querysets. How can I make the dropdown work?
models.py:
from django.contrib.sites.models import Site
from django.contrib.gis.db import models
from django.utils.crypto import get_random_string
from django.contrib.gis.geos import GEOSGeometry,Point
from django.contrib.auth.models import AbstractUser
from django.shortcuts import render
from django.urls import reverse
from django.forms import ModelForm
from django.template.defaultfilters import slugify
import datetime
from leaflet.forms.widgets import LeafletWidget
from django.contrib.gis.db import models as geo_models
# Create your models here.
class User(AbstractUser):
pass
geos_pnt=Point(4314498.56, 1003834.600,srid=3857)
#pnt=GEOSGeometry('POINT(4314498.56, 1003834.600)').wkt
class Apartment(models.Model):
ADKT='Addis Ketema'
AKLT='Akaki-Kality'
ARDA= 'Arada'
BOLE='Bole'
GLLE='Gulele'
KLFE='Kolfe-Keranio'
KIRK='Kirkos'
LDTA='Lideta'
YEKA='Yeka'
NFSL='Nefas Silk-Lafto'
SUBCITY_CHOICES = [
(ADKT, 'Addis Ketema'),
(AKLT, 'Akaki-Kality'),
(ARDA, 'Arada'),
(BOLE, 'Bole'),
(GLLE, 'Gulele'),
(KLFE, 'Kolfe-Keranio'),
(KIRK,'Kirkos'),
(LDTA, 'Lideta'),
(NFSL, 'Nefas Silk-Lafto'),
(YEKA, 'Yeka')]
apt_id = models.CharField(max_length=200, primary_key=True,editable=True)
geom = geo_models.PointField(null=True)
apt_area = models.IntegerField(default=0, null=True)
no_bedrooms = models.IntegerField(null=True)
apt_cost = models.IntegerField(default=0, null=True)
apt_subcity = models.CharField(default='KIRK',choices=SUBCITY_CHOICES,max_length=30,null=True)
register_date = models.DateTimeField(auto_now_add=True,null=True)
objects = models.Manager()
sites =models.ManyToManyField(Site)
#change points from apt_rent_db to kml
def pointkml(self):
points = Apartment.objects.kml()
return render("placemarks.kml", {'places': points})
def get_absolute_url(self):
return reverse('rent_app:apartment-listing', kwargs={'pk': self.pk})
def save(self, *args, **kwargs):
#self.Latitude = self..y
#self.Longitude = self.location.x
self.slug = slugify(self.apt_id)
super(Apartment, self).save(*args, **kwargs)
class Meta:
# order of drop-down list items
verbose_name = ("Apartment")
verbose_name_plural = ("Apartments")
ordering = ('apt_cost',)
app_label = 'rent_app'
def __unicode__(self):
return self.apt_id
#property
def picture_url(self):
return self.picture.url
class UserProfile(models.Model):
first_name = models.CharField(max_length=100, null=False)
last_name = models.CharField(max_length=100,null=False)
gender = models.CharField(max_length=100)
phone_no = models.CharField(max_length=12)
sites = models.ManyToManyField(Site)
views.py:
class ApartmentFilterView(FilterView):
model = Apartment
context_object_name = 'apartments'
filter_class = ApartmentFilter
filters.py:
import django_filters
from .models import Apartment,UserProfile
class ApartmentFilter(django_filters.FilterSet):
ADKT = 'Addis Ketema'
AKLT = 'Akaki-Kality'
ARDA = 'Arada'
BOLE = 'Bole'
GLLE = 'Gulele'
KLFE = 'Kolfe-Keranio'
KIRK = 'Kirkos'
LDTA = 'Lideta'
YEKA = 'Yeka'
NFSL = 'Nefas Silk-Lafto'
SUBCITY_CHOICES = [
(ADKT, 'Addis Ketema'),
(AKLT, 'Akaki-Kality'),
(ARDA, 'Arada'),
(BOLE, 'Bole'),
(GLLE, 'Gulele'),
(KLFE, 'Kolfe-Keranio'),
(KIRK, 'Kirkos'),
(LDTA, 'Lideta'),
(NFSL, 'Nefas Silk-Lafto'),
(YEKA, 'Yeka')]
ordering = django_filters.ChoiceFilter(label='Ordering',subcity_choices=SUBCITY_CHOICES, method='filter_by_ordering')
class Meta:
model = Apartment
fields = {
'apt_cost': ['lte'],
#'apt_dist': ['lt'],
'apt_subcity': ['icontains'],
}
template:
{% extends 'base.html' %}
{% load bootstrap %}
{% block title %} የተገኙ ቤቶች | Apartment List {% endblock title %}
{% block content %}
<form action="" method="get">
{{ filter.form.as_p }}
<input type="submit">
</form>
{% for obj in filter.qs %}
{{obj.apt_id}} - Birr {{obj.apt_cost}}
{% endfor %}
{% endblock %}
Your model should be listed in the Meta class.
class yourfilter(django_filters.FilterSet):
class Meta:
model = your_model
i am a beginner django developer, "ModelForm has no model class specified. " is given on my project , what i can do pls help, i will be greatfull to you if you solve my problem
models.py
from django.db import models
class product(models.Model):
name = models.CharField(max_length=50)
forms.py
from django.forms import ModelForm
from .models import product
class productform(ModelForm):
class Meta:
model:product
fields: '__all__'
views.py
from django.shortcuts import render
from formt.forms import productform
def index(request):
form = productform()
context = {
'form' : form
}
return render(request, 'index.html' , context )
index.html
<h1>form model</h1>
<form action="">
{% csrf_token %}
{{form}}
<input type="submit" text="submit">
</form>
forms.py
class ProductForm(ModelForm):
class Meta:
model = Product
fields = '__all__'
views.py
from .forms import ProductForm
Look at your syntax.
Class names should start with a capital letter.
class ProductForm(ModelForm):
class Meta:
model = Product
fields: '__all__'
I've followed the process laid out on the Django ModelForm's documentation, as well as a couple of tutorials. My field displays as a standard text-entry, rather than a drop down. Can anyone point me in the right direction?
forms.py
from .models import Authority # change to rating!!!
from django import forms
class AuthorityForm(forms.ModelForm):
class Meta:
model = Authority
fields = ('authority_name',)
views.py
from django.shortcuts import render
from django.views.generic import CreateView
from .models import Authority
from .forms import AuthorityForm
# Create your views here.
class HomeCreateView(CreateView):
model = Authority
form_class = AuthorityForm
template_name = 'home.html'
success_url = 'home.html'
models.py
from django.db import models
# Create your models here.
class Authority(models.Model):
authority_name = models.CharField(max_length = 100)
authority_url = models.URLField()
def __str__(self):
return self.authority_name
class Rating(models.Model):
authority_name = models.CharField(max_length = 100)
ratings = models.CharField(max_length = 20000)
# Could this be reduced if remove the trailing letters of non-int values?
# Perhaps all values could be one-hot encoded
home.html
<h2>Choose Authority:</h2>
<form method="post" novalidate>
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<button type="submit">Submit</button>
</form>
I need to validate a condition in my Experiment class that depends on more than one field. I specified a 'clean' method in my ExperimentForm, but the validation method is never raised. The model's validation errors are perfectly displayed.
This is how the forms.py looks like:
from django import forms
from django.utils.translation import ugettext, ugettext_lazy as _
class ExperimentForm(forms.Form):
name = forms.CharField(max_length=254)
student_n = forms.IntegerField()
expert_n = forms.IntegerField()
student_cmd_n = forms.IntegerField()
expert_cmd_n = forms.IntegerField()
is_active = forms.BooleanField()
error_messages = {
'insufficient_assignments': _("The total number of commands to be evaluated must be"
"Greater than 28. Right now it's %(command_number)"),
}
def clean(self):
cleaned_data = super(ExperimentForm, self).clean()
s_n = cleaned_data.get("student_n")
e_n = cleaned_data.get("expert_n")
s_cmd_n = cleaned_data.get("student_cmd_n")
e_cmd_n = cleaned_data.get("expert_cmd_n")
command_number = s_n*s_cmd_n + e_n*e_cmd_n
if command_number < 28:
raise forms.ValidationError(
self.error_messages['insufficient_assignments'],
code='insufficient_assignments',
params={'command_number': command_number},
)
return self.cleaned_data
This is my views.py
from __future__ import unicode_literals
from django.shortcuts import render
from django.http import HttpResponse
from django.template import loader
from django.core.urlresolvers import reverse_lazy
from vacs.forms import ExperimentForm
from django.views.generic import TemplateView,ListView
from django.views.generic.edit import FormView, CreateView, UpdateView, DeleteView
from django.views.generic.detail import DetailView
from vacs.models import Experiment
class ExperimentView(FormView):
template_name = 'vacs/experiment.html'
form_class = ExperimentForm
success_url = '/vacs/experiments/'
def form_valid(self, form):
return super(ExperimentView, self).form_valid(form)
class ExperimentDetailView(DetailView):
model = Experiment
class ExperimentListView(ListView):
model = Experiment
class ExperimentCreateView(CreateView):
model = Experiment
success_url = reverse_lazy('experiment_list')
fields = ['name', 'student_n', 'expert_n', 'student_cmd_n', 'expert_cmd_n']
class ExperimentUpdateView(UpdateView):
model = Experiment
success_url = reverse_lazy('experiment_list')
fields = ['is_active' ]
class ExperimentDeleteView(DeleteView):
model = Experiment
success_url = reverse_lazy('experiment_list')
The models.py is defined in the following way:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
from django.core.validators import MaxValueValidator, MinValueValidator
from django.utils.encoding import python_2_unicode_compatible
from django.contrib.auth.models import User
from django.db import models
from jsonfield import JSONField
import collections
class Experiment(models.Model):
name = models.CharField(max_length=200)
student_n = models.IntegerField(default=0,
validators=[MinValueValidator(0)])
expert_n = models.IntegerField(default=0,
validators=[MinValueValidator(0)])
student_cmd_n = models.IntegerField(default=2,
validators=[MinValueValidator(2)])
expert_cmd_n = models.IntegerField(default=1,
validators=[MinValueValidator(1)])
is_active = models.BooleanField(default=True)
replications = JSONField(load_kwargs={'object_pairs_hook': collections.OrderedDict},
blank=True)
Finally, the template experiment_form.html:
{% extends "vacs/base.html" %}
{% load widget_tweaks %}
{% block content %}
{% if form.errors %}
<div class="alert alert-danger" role="alert">
Form error!
</div>
{% endif %}
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock %}
Thank you!
You need to override the save method for the model.
So to run clean_fields() and clean() Add the following method to your model
def save(self, *args, **kwargs):
self.full_clean()
return super().save(*args, **kwargs)
Three types of cleaning methods are run during form processing. These are normally executed when you call the is_valid() method on a
form.
Django documentation