after I saved one item using MyModelClass.save() method of django in one view/page , at another view I use MyModelClass.objects.all() to list all items in MyModelClass but the newly added one always is missing at the new page. i am using django 1.1
i am using mysql
middleware setting
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.locale.LocaleMiddleware',
)
my model:
class Company(models.Model):
name = models.CharField(max_length=500)
description = models.CharField(max_length=500,null=True)
addcompany view
def addcompany(request):
if request.POST:
form = AddCompanyForm(request.POST)
if form.is_valid():
companyname = form.cleaned_data['companyname']
c = Company(name=companyname,description='description')
c.save()
return HttpResponseRedirect('/admins/')
else:
form = AddCompanyForm()
return render_to_response('user/addcompany.html',{'form':form},context_instance=RequestContext(request))
after this page
in another view
i called this form in another view
class CompanyForm(forms.Form):
companies=((0,' '),)
for o in CcicCompany.objects.all():
x=o.id,o.name
companies+=(x,)
company = forms.ChoiceField(choices=companies,label='Company Name')
to list all companies but the recently added one is missing.
The transaction should be successful, since after i do a apache server reboot , i can see the newly added company name
Thanks for any help...
The issue is that you're (once, at import-time) to dynamically building a choices list in your form declaration, but expecting it to be modified each time you use the form. Python doesn't work that way.
See here for docs on choices:
http://docs.djangoproject.com/en/dev/ref/models/fields/#choices
But in particular, this bit:
"[I]f you find yourself hacking choices to be dynamic, you're probably better off using a proper database table with a ForeignKey. choices is meant for static data that doesn't change much, if ever."
Similar applies to forms. Perhaps you want a ModelForm and ModelChoiceField?
As pointed out by other users, the choices are created at the time that you import your module (only once) so they're not going to get updated after the first use.
You should most likely use the django.forms.ModelChoiceField to accomplish this. It takes a queryset and allows you to customize the label as well.
Another way you could do this is to wrap your code in a function, and return a new class each time. That's really not as nice of an approach since the framework provides you with ModelChoiceField, but it's an option since python allows you to return locally defined classes.
Your CcicCompany.objects.all() code is only run once when the Form class is first parsed. So of course any additional objects will not be in this list. You can achieve this in the form's __init__ method instead, so it is run afresh each time a form is generated. You can access the choices via self.fields['field_name'].choices
I'm guessing you're doing something similar to the following:
m = MyModelClass(foo='bar')
m.save()
or
MyModelClass(foo='bar').save()
or
kwargs = {'foo':'bar'}
MyModelClass(**kwargs).save()
Perhaps sharing some code might provide more insight.
Well, I hoped that you would post more code (as I mentioned in my comment), so I'm still guessing...
Are you using TransactionMiddleware and is it possible that the first request does a rollback instead of a commit?
Which database backend are you using? (if it is Sqlite, then consider using PostgreSQL or MySQL, because sqlite does not play nice with regard to concurrent connections)
Please post all relevant code (full class including possible managers in your models.py, as well as the full views), maybe then it's easier for others to help you.
UPDATE:
Your code:
companies=((0,' '),)
for o in Company.objects.all():
x=o.id,o.name
companies+=(x,)
is quite unusual, and it's still not clear what you put into the template. The code is a bit unusual since you are creating a tuple of tuples, but I can't see an error here. The bug must be somewhere else.
Anyway, I'd rather do something like that instead of creating tuples:
view:
companies = Company.objects.all()
return direct_to_template(.... {'companies': companies...} ...)
template:
{% for company in companies %}
<!-- put an empty company at the top of the list for whatever reason -->
{% if forloop.first %}
whatever<br />
{% endif %}
{{ company.name }}<br />
{% endfor %}
Related
I am developing an application which have related models like Trip can have multiple loads.
So how can I design the create form to achieve the desired functionality? I know formset can be used to achieve the functionality but I want custom functionality like:
User can create new load while creating trip, the added loads will be show in a html table within the form with edit and delete functionality being on the Trip create page.
I have achieved the functionality using two ways but I am looking for a neater and cleaner approach. What I have done so far was:
I added the Loads using ajax and retrieved the saved load's id and store in a hidden field, when submitting the main Trip's form i create object for Trip and retrieve Loads's object using id and map that Trip id in the Load's object.
I have keep Loads data in the javascript objects and allow user to perform add edit delete Loads without going to the database, once user submit the main Trip form i post Loads's data and create objects and save in the database.
Please let me know if anybody have done this type of work and have a cleaner approach
This sounds like a good use case for django-extra-views.
(install with pip install django-extra-views and add extra_views to your INSTALLED_APPS)
You can create and update models with inlines with simple class based views.
In Views
from extra_views import CreateWithInlinesView, UpdateWithInlinesView, InlineFormSetFactory
from .models import Load, Trip
class LoadInline(InlineFormsetFactory):
model = Load
fields = [<add your field names here>]
class CreateTripView(CreateWithInlinesView):
model = Trip
inlines = [LoadInline]
fields = [<add your trip model fields here>]
template = 'trips/create.html`
template:
<form method="post">
...
{{ form }}
{% for formset in inlines %}
{{ formset }}
{% endfor %}
...
<input type="submit" value="Submit" />
</form>
The update view is very similar. Here are the docs:
https://github.com/AndrewIngram/django-extra-views#createwithinlinesview-or-updatewithinlinesview
The thing that often gets overlooked is commit=False, and the ability to process more than one form or formset in a single view. So you could have a formset for trips, and a form for load, and process the information creating all the objects once all the forms validate.
Here is a restructured view function outline which I use to process multiple forms (haven't edited my app-specific names, don't want to introduce errors):
def receive_uncoated( request): #Function based view
# let's put form instantiation in one place not two, and reverse the usual test. This
# makes for a much nicer layout with actions not sandwiched by "boilerplate"
# note any([ ]) forces invocation of both .is_valid() methods
# so errors in second form get shown even in presence of errors in first
args = [request.POST, ] if request.method == "POST" else []
batchform = CreateUncWaferBatchForm( *args )
po_form = CreateUncWaferPOForm( *args, prefix='po')
if request.method != "POST" or any(
[ not batchform.is_valid(), not po_form.is_valid() ]):
return render(request, 'wafers/receive_uncoated.html', # can get this out of the way at the top
{'batchform': batchform,
'po_form': po_form,
})
#POST, everything is valid, do the work
# create and save some objects based on the validated forms ...
return redirect( 'wafers:ok' )
NB the use of any is vital. It avoids Python short-cut evaluation of a conditional and therefore makes all errors on second and subsequent forms available to the user even if the first form failed validation.
Back to this question: You would replace batch_form with a trip_form, and po_form with a ModelFormset for loads. After your form and formset both validated, you would create all the requested objects using
trip = trip_form.save( commit=False)
load_list = loads_formset.save( commit = False)
# fill in some related object in trip then save trip
foo = Foo.objects.get( ...)
trip.foo = foo
trip.save()
# link loads to trip and save them
for load in load_list:
load.trip = trip
load.save()
You probably want to run this in a transaction so that if something goes wrong (DatabaseError) with saving one of the loads, you don't get a partial trip stored in the database but rather get the whole thing rolled back.
I have this model Note:
class Note(models.Model):
category = models.ForeignKey(Category)
author = models.ForeignKey('auth.User')
title = models.CharField(max_length=40)
text = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
And I want to display this form:
class NoteEditForm(forms.ModelForm):
class Meta:
model = Note
fields = ('title', 'text')
in a template, but I want it to appear for each existing Note object in the database (it has to be that way). I've done something like that but then I hardcoded the form, pointing to the edit view URL with each object pk as a parameter; but I'm sure it has to be a clearer way, just I haven't found it. Could you guys help me with that? Thanks!
The easiest way to do this is to use a formset (also see model formsets).
For your Note model and NoteEditForm you could do something like this. You'd usually put this wherever you've defined your NoteEditForm but it can go in another file, such as views.py.
from django.forms import modelformset_factory
NoteEditFormSet = modelformset_factory(Note, form=NoteEditForm)
Using NoteEditFormSet in a view and template is almost the same as using a regular form, but there are a few differences to be aware of if you want to do anything complicated so have a look at the docs (view and template). If that's not clear enough, add a few details of what you're trying to do in your view and template and I'll try to help.
By default the formset will use Note.objects.all() as its queryset, which is what you say you want, but you can change that (details are covered in the docs).
Update:
To save an individual Note with an AJAX request I would add a second view to handle those requests. So if your formset for all Notes is served by a view at /notes/, you could add a view to handle your AJAX request at /notes/<note_id>/ (obviously just an example, adjust to fit your URL structure).
Then your JS on the /notes/ page is responsible for serializing the data for a single note and making the request to /notes/<note_id>/ (remember the CSRF token).
The HTML inputs generated for the formset have their IDs prefixed with something like id_form-<number>- and there are hidden inputs containing Note primary keys which will let you work out which ID prefix applies to each note.
I would think about doing it like this
{% for note in Notequeryset %}
<form action={% url 'url_name_to_form' pk={{note.pk}} %}>
{{form.as_p}}
</form>
{% endfor %}
Let me know what you think
I'm building a "preview" function into the CMS for my website which uses the existing front-end template to render a model. This model has an association:
class FeatureWork(models.Model):
name = models.CharField(max_length=100)
...
class FeatureWorkLink(models.Model):
feature_work = models.ForeignKey(FeatureWork)
In the view for the preview, I'm trying to build the model such that when the template calls feature.featureworklink_set.all it returns the associated links. Since neither model has been saved yet, all the standard Django form techniques seem to go out the window.
This is what I have so far, but it blows up when I call the add method on the manager, since the parent hasn't been saved yet:
form = FeatureWorkAdminForm(initial=request.POST)
featured = form.save(commit=False)
for link in request.POST['links'].split(","):
featured.featureworklink_set.add(FeatureWorkLink(image=link))
Why don't you just add:
preview = BooleanField()
to your models, save everything to database and don't look for hacks. This way you can have drafts for free.
You can actually save it in transaction and rollback when template is ready. It's not very efficient, but at least it will work.
featured.featureworklink_set.add(FeatureWorkLink(image=link)) will immediately attempt to create a relationship between a FeatureWork and FeatureWorkLink, which isn't going to happen because that instance of FeatureWork is not present in the database and you cannot satisfy the predicates for building the foreign key relationship.
But the great thing is that Django's Model and ModelForm instances will not validate foreign key relationships until your actually trying to commit the data. So manually constructing your FeaturedWorkLink with an uncommited, non-existing FeatureWork should satisfy any presentation of the data you need to do, much to what you'd expect:
links = []
form = FeatureWorkAdminForm(initial=request.POST)
featured = form.save(commit=False)
for link in request.POST['links'].split(","):
links.add(FeatureWorkLink(image=link, feature_work=featured))
# then somewhere in your templates, from the context
{% for link in links %}
<img src="{{ link.image }}"
title="Image for the featured work: '{{ link.feature_work.name }}'" />
{% endfor %}
So basically, during the course of collecting the data to create a FeatureWork, you'll have to maintain the FeatureWorkLink instances through subsequent requests. This is where you'd use a model form set, but provide an uncommitted FeatureWork for the feature_work property for every model form instance of the set, up until the point where all the data has been collected, where you then provide a commited FeatureWork instance, so that the model form set can satisfy referential integrity and finally be commited to the database.
OK, so let me give you an overview first. I have this site and in it there is a form section. When you access that section you can view or start a new project. Each project has 3-5 different forms.
My problem is that I don't want viewers to have to go through all 3-5 pages to see the relevant information they need. Instead I want to give each project a main page where all the essential data entered into the forms is shown as non-editable data. I hope this makes sense.
So I need to find a way to access all that data from the different forms for each project and to feed that data into the new page I'll be calling "Main". Each project will have a separate main page for itself.
I'm pretty much clueless as to how I should do this, so any help at all would be appreciated.
Thanks
You could try this. After that, you could:
Try creating a model for each project. This is done in "models.py" of the application modules created by django-admin
Use views to show that data to people (on your Main page)
If you've already seen all that, then:
First, you should create a view for your main page. So if you have an application my_app, my_app/views.py should be like:
def main_page_view(request, project_name):
# Your code here
pass
Then, to use this, you'd modify urls.py and add in something like:
(r'^projects/(?:<project_name>[a-zA-Z0-9]+)', 'my_app.views.main_page_view'),
Also, you'd need models, which are created in models.py, by subclassing django.models.Model
EDIT: re-reading your question, I guess you need this
Data can be passed from a view to a template through the context.
So say you create a summary view...
def summary(request, *args, **kwargs):
In that view you can query the database using the model api and pass the result of that query into the template for rendering. I'm not sure what your models look like, but say you had a model that had a title and the owner (as a ForeignKey to user)...
class Project(models.Model):
title = models.CharField(max_length=250)
user = models.ForeignKey(User)
Your model will be obviously be different. In your view you could query for all of the models that belong to the current user...
def summary(request, *args, **kwargs):
projects = Project.objects.filter(user=request.user)
Once you've gathered that, you can pass in the query to the template rendering system...
def summary(request, *args, **kwargs):
projects = Project.objects.filter(user=request.user)
render_to_response('project_summary.html', {'projects': projects }, ... )
When you pass the query to the template, you've named it projects. From within the template you can access it by this name...
<body>
<table>
{% for project in projects %}
<tr><td>{{ project.title }}</td></tr>
{% endfor %}
</table>
</body>
(Notice also how you can access a property of the model from within the template as well.)
Greetings,
I am trying to implement a TimeField model which only consists of HH:MM (ie 16:46) format, I know it is possible to format a regular Python time object but I am lost about how to manage this with Django.
Cheers
Django widget can be used to achieve this easily.
from django import forms
class timeSlotForm(forms.Form):
from_time = forms.TimeField(widget=forms.TimeInput(format='%H:%M'))
DateTime fields will always store also seconds; however, you can easily tell the template to just show the hours and minute, with the time filter:
{{ value|time:"H:M" }}
where "value" is the variable containing the datetime field.
Of course, you can also resort to other tricks, like cutting out the seconds from the field while saving; it would require just a small change to the code in the view handling the form, to do something like this:
if form.is_valid():
instance = form.save(commit=False)
instance.nosecs = instance.nosecs.strptime(instance.nosecs.strftime("%H:%M"), "%H:%M")
instance.save()
(note: this is an ugly and untested code, just to give the idea!)
Finally, you should note that the admin will still display the seconds in the field.
It should not be a big concern, though, because admin should be only used by a kind of users that can be instructed not to use that part of the field.
In case you want to patch also the admin, you can still assign your own widget to the form, and thus having the admin using it. Of course, this would mean a significant additional effort.
So I think the proposed and accepted solution is not optimal because with:
datetime.widget = forms.SplitDateTimeWidget(time_format=('%H:%M'))
For a SplitDateTimeField in my case but for you only change it to TimeWidget.
Hope it helps other people too.
TimeField model
in Template
Is displayed
{{ value|time:"H:i" }}
Is not displayed
{{ value|time:"H:M" }}
Django 1.4.1
For a ModelForm, you can easily add a widget like this, to avoid the seconds being shown (just show hh:mm):
class MyCreateForm(forms.ModelForm):
class Meta:
model = MyModel
fields = ('time_in', 'time_out', )
widgets = {
'time_in': forms.TimeInput(format='%H:%M'),
'time_out': forms.TimeInput(format='%H:%M'),
}
You can at least modify the output in the __str__ method on the model by using datetime.time.isoformat(timespec='minutes'), like this:
def __str__(self):
return self.value.isoformat(timespec='minutes')
Now the value is showing as HH:MM in admin pages.
On Django 1.9 the following format should work:
{{ yourData.value|time:"H:i" }}
Django has a whole set of template tags and filters.
Django 1.9 documentation on this is:
https://docs.djangoproject.com/en/1.9/ref/templates/builtins/#time