I'm Creating a project and i have one doubt, so the site if for a support center where a the django project logs a case for the user after user fill out a general form.
So i have created a model name Case and it has fields like case_number, email and all that.
Now, in views.py i am using CBV CreateView to create save the userform and create a case number simple.
Where i am stuck at is, the case number which is a 10 digit string field needs to be randomly created, but how do i store it after customer is done with filling the form?
because whatever ill mention in fields will show up as a input for customer and case_number is not what i want customer to fill it, it should be auto generated.
I believe it can be done simply by:-
r2 = [random.randint(0, 10),random.randint(0, 10),random.randint(0, 10),random.randint(0, 10),random.randint(0, 10),random.randint(0, 10),random.randint(0, 10),random.randint(0, 10),random.randint(0, 10),random.randint(0, 10)]
case_number = (''.join(str(x) for x in r2))
and in CBV CreateView will let me create a number randomly and save it but i want this to be done at the backend so i cant mention it in create view,
This is just doubt, i have tried it yet.
models.py
class Case:
case_number = models.CharField(max_length=10)
issue=models.TextField()
product=models.CharField(max_field=100)
def get_absolute_url(self):
return reverse('case:single')
Views.py
class CaseCreation(CreateView):
model=Case
fields=('issue', 'product')
r2=[random.randint(0,10), random.randint(0,10), random.randint(0,10), random.randint(0,10), random.randint(0,10), random.randint(0,10), random.randint(0,10), random.randint(0,10), random.randint(0,10), random.randint(0,10)]
self.case_number = (''.join(str(x) for x in r2))
The Expected result is that i want randomly a 10 digit number to get crated for customer and get saved in the db
DB is sql lite3.
Ok so just to let you guys know i finally came up with an answer,
I defined the logic of creating the cases in models.py as below.
def case_generation(self):
r2=[random.randint(0,10), random.randint(0,10), random.randint(0,10), random.randint(0,10), random.randint(0,10), random.randint(0,10), random.randint(0,10), random.randint(0,10), random.randint(0,10), random.randint(0,10)]
self.case_number = (''.join(str(x) for x in r2))
self.save()
Now in views.py i defined a function and called the function defined in models.py and save.
#login_required
def case_number_generation(request, pk):
case = get_object_or_404(Case, pk=pk)
case.case_generation()
return redirect("cases:single_pk", pk=case.pk)
in between this i defined the urls.py such that one the user generates the case, the functions will be called by itself.
If your interested to look into the full code, no worries let me know ill post it here if required. ;)
Related
I am experimenting with play/scala. I have following two case classes and I want to map data from form into this model
case class User (
name:String,
age:Int,
female:Boolean,
address:Address
)
case class Address (
fullStreet:String,
county:String,
country:String
)
In controller class, I have following mapping function and action defined
val userForm = Form((mapping("name"->text,
"age"->number,
"female"->boolean,
"address"->mapping("fullStreet"->text,
"county"->text,
"country"->text)(Address.apply)(Address.unapply)
)(User.apply)(User.unapply)))
def post = Action { implicit request =>
val u:Form[User] = userForm.bindFromRequest
Ok(views.html.dataIndex(u))
}
I am facing the following issue: To make the complete code work, I have to create a form which contains all the fields required in mapping as follows:
<h1>Feed User Data</h1>
#helper.form(action=routes.Data.post){
#helper.inputText(userForm("name"))
#helper.inputText(userForm("age"))
#helper.checkbox(userForm("female"))
<fieldset>
#helper.inputText(userForm("address.fullStreet"),'_label -> "Full Street")
#helper.inputText(userForm("address.county"),'_label -> "County")
#helper.select(userForm("address.country"),Seq(""->"---",
"United Kingdom"->"UK",
"France"->"FR") )
</fieldset>
<input type="submit" name="send" value="submit"/>
}
If I create a form with say only input field for name, then bindFromRequest returns None instead of mapping only name field. Is there a way in which the form can contain less fields than required in mapping. I am not talking about fields in form with empty/optional values. I do not want to put the fields in the form at all.
I usually create a case class that represents the form data (probably not all the info from the domain class), and in the controller/service I create the domain entity using my own rules (for instance, a default value for a field not represented on the form)
I have a form object that handles 2 associated objects. I'm trying to get some validation working on the form object, but am not having much success.
I think the issue is that the attributes I'm validating are delegated to the model objects, but I'm not sure how else to handle this situation: when the form is displayed, these attributes need to pull from the actual models to show the values on the form in edit mode, but when I update the form, I need to validate the submitted parameters, not the values being pulled from the models themselves.
One thought I have is using a EditBorrowerForm object that pulls attributes from associated models and a UpdateBorrowerForm that performs all the validations and updates the models. But that seems like a lot of extra work for something trivial.
I've seen a lot of form objects used for CREATE actions (where you only validate fields before passing them to the models), but haven't seen any good examples of UPDATE actions (where you need to both pull fields from models as well as update them).
Here are the models I'm working with:
class Client < ActiveRecord::Base
has_many :borrowers
end
class Borrower < ActiveRecord::Base
belongs_to :client
end
And my form object:
class BorrowerForm
include ActiveModel::Model
attr_accessor :client, :borrower
delegate :first_name, :last_name, :date_of_birth, to: :client
delegate :citizenship, :marital_status, to: :borrower
validates :first_name, :last_name, :citizenship, presence: true
def initialize(borrower)
#borrower = borrower
#client = #borrower.client
end
def update_attributes(params)
# Never validates properly...
if valid?
ActiveRecord::Base.transaction do
borrower.update_attributes(params.slice(:citizenship, :marital_status)
client.update_attributes(params.slice(:first_name, :last_name, :date_of_birth)
end
true
else
false
end
end
end
And the controller:
class BorrowersController < ApplicationController
def edit
#borrower = BorrowerForm.new(Borrower.find(params[:id])
end
def update
#borrower = BorrowerForm.new(Borrower.find(params[:id])
if #borrower.update_attributes(params)
redirect_to :index
else
render :edit
end
end
end
I have a subscriptions form where I am trying to set the plan the user has chosen, the business they would like to associate with the subscription and the payment details. In my form I use a select tag to display a list of all of the businesses and it displays properly in my view but upon save I get the following error:
undefined method `map' for #<Business:0x007f8ea7955b90>
new.html.erb
<div class="field">
<%= select_tag :business_id, options_from_collection_for_select(#businesses, "id", "name") %>
</div>
subscriptions_controller.rb
...
def new
#subscription = Subscription.new
#plan = Plan.find(params["plan_id"])
#businesses = Business.all
end
def create
#subscription = Subscription.new(subscription_params)
raise "Please, check subscription errors" unless #subscription.valid?
#subscription.process_payment
#subscription.save
redirect_to #subscription, notice: 'Subscription was successfully created.'
rescue => e
flash[:error] = e.message
render :new
end
private
def set_subscription
#subscription = Subscription.find(params[:id])
end
def subscription_params
params.require(:subscription).permit(:plan_id, :business_id, :card_token, :coupon)
end
Am I setting up the select_tag properly? Do I need to fix my create method? Looked at other solutions on SO with little success.
Rails instantiates a new controller for every request. There's some information about that here.
This means that any instance variables you've set in new won't be available when you process the POST in create.
In your case, you are rendering the :new template in the rescue block of the create action when the new subscription fails validation. You're only getting the error at this point, not when you originally access the form.
The problem is that render :new doesn't call the new action; it just renders the template. In the case where the subscription fails validation and the form is re-rendered, the new action has never been called by this controller instance, and the instance variables do not have the values expected by the template.
Try this instead of render :new:
redirect_to new_subscription_url
This will instantiate a new controller and call the new action, so that you will be starting over with a clean slate. The instance variables needed in the new template will be assigned the correct values before the template is rendered.
As an alternative, you could set the instance variables in the rescue block:
def create
...
rescue => e
flash[:error] = e.message
#businesses = Business.all
render :new
end
Here's a similar question on Stack Overflow.
Hope that helps. Happy coding!
I have several CRUD operations to perform, each one on a collection of models (e.g. game schedule, team roster, game result, game stats, etc.).
Up to this point in my Play experience (just a few months, 1 project live) I have been working with one-to-one form binding to model instance.
I know I can numerically index form field names, but then how to bind the posted form to List[Model]?
This is what my one-to-one binding looks like:
// abstract away bindFromRequest to make binding more concise in controllers
def bindForm[T](f: play.api.data.Form[T])(implicit r: play.api.mvc.Request[_]) =
f.bindFromRequest fold(e=> Left(e.errorsAsJson), Right(_))
and then in controllers:
val result = for {
model <- bindForm(form).right
id <- dao.create(model) as json
} yield id
what I would like to do is the same, but instead of model binding returning a single Model on success, have it return a List[Model], and pass on to overloaded DAO create/edit/delete operations.
I see that there is a list method that one can use as part of a Form mapping, but I have a feeling that that would wreak havoc with my JDBC query wrapper (ScalaQuery/Slick), whose case class/companion object mapping would likely not play well with collections properties.
For example, existing mapping of a game schedule looks like:
object CompositeForm {
import play.api.data.{Form, Forms}, Forms._
import utils.Validator.Bindings.jodaLocalTimeFormat
val mapper = mapping(
'id -> ignored(0),
'gameDate -> jodaDate,
'gameType -> optional(text),
'location -> optional(text),
'team1 -> number,
'team2 -> number
)(Composite.apply)(Composite.unapply)
val form = Form( mapper )
}
using list(gameDate), list(gameType) instead then means that form binding will return a single Composite instance whose properties are all collections -- maybe it will work, but doesn't seem nearly as clean/straightforward as working with a collection of model instances.
Ideas appreciated ;-)
The as yet documented seq() option in play form mapping was pointed out to me on Play google group by #Julien Richard-Foy
Using repeat() and seq() together allows one to repeat a form mapping, thus creating a collection of indexed foo.bar[n] formfield elements.
Example
object ScheduleForm {
import play.api.data.{Form, Forms}, Forms._
val mapper = mapping(
'composite -> seq(CompositeForm.mapper),
'note -> seq(ScheduleNoteForm.mapper)
)(Schedule.apply)(Schedule.unapply)
val form = Form( mapper )
}
and then in a view:
#repeat(_form("composite"), min=#numGames) { f=>
#inputDate(f("gameDate"), '_label-> "Game Date", 'class-> "required")
...
}
I am trying to implement manytomany field relation in django-nonrel on mongodb. It was suggessted at to:
Django-nonrel form field for ListField
Following the accepted answer
models.py
class MyClass(models.Model):
field = ListField(models.ForeignKey(AnotherClass))
i am not sure where the following goes, it has been tested in fields.py, widgets,py, models.py
class ModelListField(ListField):
def formfield(self, **kwargs):
return FormListField(**kwargs)
class ListFieldWidget(SelectMultiple):
pass
class FormListField(MultipleChoiceField):
"""
This is a custom form field that can display a ModelListField as a Multiple Select GUI element.
"""
widget = ListFieldWidget
def clean(self, value):
#TODO: clean your data in whatever way is correct in your case and return cleaned data instead of just the value
return value
admin.py
class MyClassAdmin(admin.ModelAdmin):
form = MyClassForm
def __init__(self, model, admin_site):
super(MyClassAdmin,self).__init__(model, admin_site)
admin.site.register(MyClass, MyClassAdmin)
The following Errors keep popping up:
If the middle custom class code is used in models.py
name 'SelectMultiple' is not defined
If custom class code is taken off models.py:
No form field implemented for <class 'djangotoolbox.fields.ListField'>
You just need to import SelectMultiple by the sound of it. You can put the code in any of those three files, fields.py would make sense.
Since it's pretty usual to have:
from django import forms
at the top of your file already, you probably just want to edit the code below to:
# you'll have to work out how to import the Mongo ListField for yourself :)
class ModelListField(ListField):
def formfield(self, **kwargs):
return FormListField(**kwargs)
class ListFieldWidget(forms.SelectMultiple):
pass
class FormListField(forms.MultipleChoiceField):
"""
This is a custom form field that can display a ModelListField as a Multiple Select GUI element.
"""
widget = ListFieldWidget
def clean(self, value):
#TODO: clean your data in whatever way is correct in your case and return cleaned data instead of just the value
return value
You probably also want to try and learn a bit more about how python works, how to import modules etc.