I'm a bit confused as why it keeps returning the 'enter a valid date' message. Is it my formatting?
I've tried different combinations of %m-%d-%Y, but still no luck.
models.py
class DeliveryDate(models.Model):
cart = models.ForeignKey('Cart', null=True, blank=True)
date = models.DateField()
def __str__(self):
return str(self.cart.id)
return self.date
views.py
def add_delivery_date(request):
the_id = request.session['cart_id']
cart = Cart.objects.get(id=the_id)
form = DeliveryDateForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
delivery_date = form.save(commit=False)
date = request.POST['date']
delivery_date = DeliveryDate.objects.create(cart=cart, date=date)
delivery_date.save()
return HttpResponseRedirect('thank-you.html')
context = {
"form": form
}
return render(request, 'choose_delivery_date.html', context)
forms.py
class DeliveryDateForm(forms.ModelForm):
date = forms.DateField(input_formats=['%m %d %Y'], widget=SelectDateWidget, initial=datetime.date.today())
class Meta:
model = DeliveryDate
fields = ['date']
First in your Django ModelForm let's change the date model field's widget without adding an extra field.
This is done in the __ init __ method :
from django.forms.extras.widgets import SelectDateWidget
class DeliveryDateForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(DeliveryDateForm, self).__init__(*args, **kwargs)
#Change date field's widget here
self.fields['date'].widget = SelectDateWidget()
class Meta:
model = DeliveryDate
fields = ['date']
By adding a field like you did :
class DeliveryDateForm(forms.ModelForm):
date = forms.DateField(input_formats=['%m %d %Y'], widget=SelectDateWidget, initial=datetime.date.today())
Is actually adding an extra FormField to your ModelForm which has the same name than the ModelField.
Doing this way, you'll simply change the binded date ModelField widget to 3 selects for Day/month/year
Second, your form validation is quit odd :
What I usually write looks like that:
def add_delivery_date(request):
the_id = request.session['cart_id']
cart = Cart.objects.get(id=the_id)
form = DeliveryDateForm()
if request.method == "POST":
form = DeliveryDate(data=request.POST)
if form.is_valid():
delivery_date = form.save(commit=False)
delivery_date.cart = cart
delivery_date.save()
return HttpResponseRedirect('thank-you.html')
return render(request, 'choose_delivery_date.html', {
'form': form
})
Related
I cannot find a way in the Django documentation to pass a value between different function views. I would like to create an object in my create_player_view, capture that new object pk and pass it to scoring_view. Doing this through the form action field has been unsuccessful as no data is passing between the views. What is a better way to do this?
I want a simple behavior that takes the Match ID created in create_player_view and passes it for update/use to scoring_view.
models
class Players(models.Model):
matchID = models.AutoField(primary_key=True)
player1Name = models.CharField(max_length=10)
player2Name = models.CharField(max_length=10)
def __str__(self):
return f'{self.matchID}: {self.player1Name} vs {self.player2Name}'
class Scores(models.Model):
matchID = models.OneToOneField(Players, on_delete=models.CASCADE, related_name='match')
p1_set_1_score = models.IntegerField(default=0)
p1_set_2_score = models.IntegerField(default=0)
p1_set_3_score = models.IntegerField(default=0)
p1_set_4_score = models.IntegerField(default=0)
p2_set_1_score = models.IntegerField(default=0)
p2_set_2_score = models.IntegerField(default=0)
p2_set_3_score = models.IntegerField(default=0)
p2_set_4_score = models.IntegerField(default=0)
def __str__(self):
return f'{self.matchID}: '
views
def create_player_view(request):
"""
allows users to name two
players competing vs one another
"""
if request.method == "POST":
form = PlayerForm(request.POST)
if form.is_valid():
form.save(commit=True)
return redirect('tennis:m_score') #is it possible to pass this view created instance?
else:
message = "Form could not be completed"
return render(request, "create_player.html", {"message":message})
else:
form = PlayerForm()
return render(request, "create_player.html",
{'form': form})
def scoring_view(request):
"""
View allows user to select the participating 2 players
and record their scores per set.
"""
if request.method == "POST":
form = ScoresForm(request.POST )#, instance=player_instance)
if form.is_valid():
form.save(commit=True)
return redirect('tennis:m_results')
else:
form = ScoresForm()
return render(request, "now_playing.html", {'form':form}) #todo add filtering
forms.py
class PlayerForm(ModelForm):
class Meta:
model = Players
exclude = ('matchID',)
labels = {
'playerName':('Player 1 Name', 'Player 2 Name'),
}
class ScoresForm(ModelForm):
class Meta:
model = Scores
fields = "__all__"
###urls.py
from django.urls import path
from tennis import views
app_name="tennis"
urlpatterns = [
path('players/', views.create_player_view, name="c_pl"),
path('scoring/<new_player>/', views.scoring_view, name="m_score"),
path('summary/', views.match_summary_view, name="m_results"),
]
Edit your views:
def create_player_view(request):
""""
allows users to name two
players competing vs one another
"""
if request.method == "POST":
form = PlayerForm(request.POST)
if form.is_valid():
new_player = = form.save(commit=True)
return redirect('tennis:m_score', new_player=new_player) # If you want to pass the pk instead of the object itself write: new_player=new_player.pk
else:
message = "Form could not be completed"
return render(request, "create_player.html", {"message":message})
else:
form = PlayerForm()
return render(request, "create_player.html",
{'form': form})
def scoring_view(request, new_player):
""""
View allows user to select the participating 2 players
and record their scores per set.
"""
if request.method == "POST":
# You can use the value of new_player as your needs
data = request.POST
data['matchID'] = new_player
form = ScoresForm(data)
if form.is_valid():
form.save(commit=True)
return redirect('tennis:m_results')
else:
form = ScoresForm()
return render(request, "now_playing.html", {'form':form}) #todo add filtering
I'm trying to save and retrive the data owned by the user.
I mean, in one Sqlite3 DB I store the tables for all users but each one has their one data store in it, how can I give each one their own data.
this are my models, view and form
MODEL.PY
class Cuentas (models.Model):
rubro_cta = models.ForeignKey(TipoC, on_delete=models.CASCADE, verbose_name = u'Tipo')
sub_rubro_cta = models.ForeignKey(Sub_rubro, on_delete=models.CASCADE, verbose_name = u'Sub Rubro')
titulo_cuenta = models.CharField(max_length=50)
detalle_cuenta = models.CharField(max_length=60)
importe_cuenta = models.FloatField()
def save(self, *args, **kwargs):
self.importe_cuenta = round(self.importe_cuenta, 2)
super(Cuentas, self).save(*args, **kwargs)
def __str__(self):
return self.detalle_cuenta
FORMS.PY
class CuentasForm (forms.ModelForm):
class Meta:
model = Cuentas
fields = ['rubro_cta', 'sub_rubro_cta', 'detalle_cuenta', 'importe_cuenta']
labels = {
'rubro_cta': _('Cuenta'),
'sub_rubro_cta': _('Tipo'),
'detalle_cuenta': _('Detalle'),
'importe_cuenta': _('Importe'),
}
VIEWS.PY
#login_required
def carga (request):
if request.method == 'POST':
form = CuentasForm(request.POST)
if form.is_valid:
form.save()
return redirect('balance')
else:
form = CuentasForm()
return render (request, "ProyetoWebApp/carga.html",{"form": form})
you have to add a foreign key field to user in your Cuentas class:
class Cuentas (models.Model):
user = models.ForeignKey(User, models.CASCADE)
...
in your view add this code for GET method:
info = None
if request.method == 'GET':
info = Cuentas.objects.get(user=request.user)
return render (request, "ProyetoWebApp/carga.html",{"form": form, "info":info})
I want to limit the choices of a ManyToManyField to those matching a ForeignKey. The form displays properly, but upon saving results in an error Select a valid choice. <choice> is not one of the available choices.
Before I was trying to limit the queryset by passing a parameter in the view to the form, and then using that parameter to filter the queryset.
Models:
class VenueEventTimeslot(models.Model):
venue = models.ForeignKey(Venue)
name = models.CharField(max_length=255)
class VenueEvent(models.Model):
venue = models.ForeignKey(Venue)
event_timeslots = models.ManyToManyField(VenueEventTimeslot)
class VenueEventForm(ModelForm):
event_timeslots = ModelMultipleChoiceField(queryset=None, widget=CheckboxSelectMultiple())
def __init__(self, *args, **kwargs): # limit timeslots to those of the venue only
venue_obj = kwargs.pop('venue_obj',None)
super(VenueEventForm, self).__init__(*args,**kwargs)
self.fields['event_timeslots'].queryset=VenueEventTimeslot.objects.filter(venue=venue_obj)
class Meta:
model = VenueEvent
fields = ['event_timeslots']
Views:
#login_required
def calendar(request, pk):
venue = Venue.objects.get(pk = pk)
if request.method == "POST":
form = VenueEventForm(request.POST)
if form.is_valid():
# form stuff
else:
form = VenueEventForm(venue_obj = venue)
context = {'venue':venue, 'form':form}
return render(request, ... , context)
However, if I pass the queryset from the view, it works perfectly.
Models:
class VenueEventTimeslot(models.Model):
# same as above
class VenueEvent(models.Model):
# same as above
class VenueEventForm(ModelForm):
class Meta:
model = VenueEvent
fields = ['date','client_name','event_timeslots']
widgets = {
'date': SelectDateWidget(),
'event_timeslots': CheckboxSelectMultiple(),
}
Views:
#login_required
def calendar(request, pk):
venue = Venue.objects.get(pk = pk)
if request.method == "POST":
form = VenueEventForm(request.POST)
if form.is_valid():
# form stuff
else:
form = VenueEventForm()
form.fields['event_timeslots'].queryset=VenueEventTimeslot.objects.filter(venue=venue)
context = {'venue':venue, 'form':form}
return render(request, ..., context)
Would anyone be able to shed some light on this?
I just solved a problem similar to this yesterday which is right here, How To Exclude A Value In A ModelMultipleChoiceField?, but I think the issue with your init function is the way it is formatted. Instead of venue=venue_obj, you need to change it to pk=venue_obj because it appear you are getting the pk of venue in the view instead of the venue attribute of VenueEvent , and I reformatted your form a bit to make it look cleaner.
forms.py
class VenueEventForm(ModelForm):
def __init__(self, *args, **kwargs): # limit timeslots to those of the venue only
venue_obj = kwargs.pop('venue_obj')
super(VenueEventForm, self).__init__(*args,**kwargs)
self.fields['event_timeslots'] = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple(), queryset=VenueEventTimeslot.objects.filter(pk=venue_obj))
class Meta:
model = VenueEvent
fields = ['event_timeslots']
views.py
#login_required
def calendar(request, pk):
venue = Venue.objects.get(pk = pk)
if request.method == "POST":
form = VenueEventForm(request.POST, venue_obj=venue)
if form.is_valid():
# form stuff
else:
print VenueEventForm.errors
else:
form = VenueEventForm(venue_obj=venue)
context = {'venue':venue, 'form':form}
return render(request, ... , context)
I have a simple model with 2 classes:
class Company(models.Model):
company_name = models.CharField(default='', max_length=128, blank=True, null=True)
class Visitor(models.Model):
visitor_company = models.ForeignKey(Company)
visitor_name = models.CharField(default='', max_length=128, blank=False, null=False)
I also have a simple form:
class VisitorForm(forms.ModelForm):
visitor_company = forms.CharField()
class Meta:
model = Visitor
fields = "__all__"
And here is the view.py code:
def home(request):
form = Visitor()
if request.method == "POST":
form = Visitor(request.POST)
if form.is_valid():
obj, created = Visitor.objects.get_or_create(**form.cleaned_data)
if created:
messages.add_message(request, messages.SUCCESS, 'Visitor added.')
else:
messages.add_message(request, messages.INFO, 'Visitor exists : %s' % obj.visitor_name)
return redirect('visitors')
context = { 'form': form }
return render(request, "visitors/home.html", context)
I have set visitor_company as a CharField as I want to use Typeahead for users to specify the ForeignKey, rather than Django's built in dropdown (which would appear if I did not set the input type).
However, when I use this method, even if I input a valid company_name in the visitor_company field, I get Cannot assign "XXX": "Visitor.visitor_company" must be a "Company" instance.
How do I input a Company instance? Is it also possible to use get_or_create on a ForeignKey like this if the Company record doesn't exist?
This is untested code, so consider this a starting point, no real solution:
forms.py
class VisitorForm(forms.ModelForm):
visitor_company = forms.CharField()
def clean_visitor_company(self):
vc = self.cleanded_data['visitor_company']
try:
vc_object = Company.objects.get(company_name=vc)
except Company.DoesNotExist:
vc_object = Company.objects.create(company_name=vc)
return vc_object
class Meta:
model = Visitor
fields = "__all__"
views.py
def home(request):
form = VisitorForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('visitors')
return render(request, "visitors/home.html", { 'form': form })
The issue is next: I'm using existing templates for my site. I have an order page. I want to use my own template for form
I know that I can implement it just using {% for field in form %}. But I need to show not all fields. For example, here is my Order model:
class Order(models.Model):
state_choices = ('ACTIVE', 'COMPLETED', 'FROZEN')
order_date = models.DateTimeField(auto_now_add=True)
delivery_time = models.CharField(max_length=100)
address_city = models.CharField(max_length=40)
address_street = models.CharField(max_length=40)
address_building = models.CharField(max_length=40)
state = models.CharField(max_length=200, default='ACTIVE')
client = models.ForeignKey(CustomUser)
I need to show just: address_city, address_street, address_building and delivery_time. Because in view I just return current user and set it to client. Here is my view that saves Order:
def submit(request):
args = {}
args['form'] = OrderForm
if request.POST:
order_form = OrderForm(request.POST)
if order_form.is_valid():
order_form.save()
user = request.user
address_country = order_form.cleaned_data['address_country']
address_city = order_form.cleaned_data['address_city']
address_building = order_form.cleaned_data['address_building']
delivery_time = order_form.cleaned_data['delivery_time']
new_order = Order(address_country=address_country,
address_city=address_city,
address_building=address_building,
delivery_date=delivery_time, client=user)
new_order.save()
Basket.objects.filter(client=user).delete()
return redirect('/order/')
else:
return render(request, 'order_page.html', args)
I guess that new_order is odd, because order_form.save() saves it. But how to set user of current session to Order through form?
To understand it all, here is my OrderForm code:
class OrderForm(forms.ModelForm):
class Meta():
model = Order
fields = ['address_city', 'address_street', 'address_building', 'delivery_time']
I handle this kind of logic in the form's init method, and when creating the form in the view I pass in the request object as a kwarg for the form to get its data from, then hide the appropriate fields:
In forms.py...
class YourForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
request = kwargs.pop('request', None)
super(YourForm, self).__init__(*args, **kwargs)
if request:
self.fields['field'].initial = process_request_to_get_value(request)
self.fields['field'].widget = forms.HiddenInput()
# More logic here if needed
class Meta:
model = Order
In views.py...
def your_view(request):
if request.method == 'POST':
form = YourForm(request.POST, request = request)
if form.is_valid():
form.save()
return HttpResponseRedirect('somewhere')
else:
form = YourForm(request = request)
return render_to_response('template',
{'form': form,},
context_instance = RequestContext(request))