简体   繁体   中英

django objects.all() method issue

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?

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

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.

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 %}
    <a href="{% url company_view "0" %}">whatever</a><br />
  {% endif %}

  <a href="{% url company_view company.id %}">{{ company.name }}</a><br />
{% endfor %}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM