Re: Zip code lookup field
I figured it out! The problem was that my custom zip code field's clean() function was returning the profile object's *id*, not the actual zip code instance. > zip_code_id = Postal_Code.objects.get(postal_code=value).id > return int(zip_code_id) As it turns out, the function should have returned the actual object. All I had to do to make this code work, therefore, was remove the ".id" from the end of the first line above. Voila! Lesson learned: Custom fields for foreign keys must return an instance, not the key. Thanks again for the help. Hope this thread helps someone else in the future. Cheers, LS --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---
Re: Zip code lookup field
Here's a bit of the testing I have run in the shell... >>> from mysite2.profile.models import Profile >>> from django import newforms >>> from mysite2.admin import ProfileOptions >>> # instantiate a Profile object >>> test_profile = Profile.objects.get(id=1) >>> # instantiate the adminoptions class >>> # used by the admin site >>> options = ProfileOptions(Profile) >>> # create a form class for the profile instance >>> form = newforms.form_for_instance(test_profile,formfield_callback = >>> options.formfield_for_dbfield) >>> form >>> # check that the zip_code field is of type ZipCodeField >>> form.base_fields['zip_code'] >>> # in my database, i currently have only one zip code >>> # 90069, with a key of 1. >>> form.base_fields['zip_code'].initial 1 >>> form.base_fields['zip_code'].clean(value='90069') 1 >>> form.base_fields['zip_code'].clean(value='111') Traceback (most recent call last): File "", line 1, in ? File "Sites/Django/mysite2/../mysite2/admin.py", line 40, in clean raise ValidationError, "Please enter a valid zip code." ValidationError: [u'Please enter a valid zip code.'] >>> form.base_fields['zip_code'].clean(value='') Traceback (most recent call last): File "", line 1, in ? File "/Users/leifstrickland/Sites/DjangoProject/mysite2/../mysite2/ admin.py", line 40, in clean raise ValidationError, "Please enter a valid zip code." ValidationError: [u'Please enter a valid zip code.'] >>> zip_code_field = form.base_fields['zip_code'] >>> zip_code_field.widget.render(name='zip_code',value=1) u'' >>> zip_code_field.widget.render(name='zip_code',value='') u'' As you can see, everything seems to be working. I'm so puzzled... --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---
Re: Zip code lookup field
Here's a bit of the testing I have run in the shell... >>> from mysite2.profile.models import Profile >>> from django import newformms >>> from mysite2.admin import ProfileOptions >>> >>> # instantiate a Profile object >>> test_profile = Profile.objects.get(id=1) >>> >>> # instantiate the adminoptions class >>> # used by the admin site >>> options = ProfileOptions(Profile) >>> >>> # create a form class for the profile instance >>> form = newforms.form_for_instance(test_profile,formfield_callback = >>> options.formfield_for_dbfield) >>> form >>> >>> # check that the zip_code field is of type ZipCodeField >>> form.base_fields['zip_code'] >>> >>> # in my database, i currently have only one zip code >>> # 90069, with a key of 1. >>> >>> form.base_fields['zip_code'].initial 1 >>> >>> form.base_fields['zip_code'].clean(value='90069') 1 >>> >>> form.base_fields['zip_code'].clean(value='111') Traceback (most recent call last): File "", line 1, in ? File "Sites/Django/mysite2/../mysite2/admin.py", line 40, in clean raise ValidationError, "Please enter a valid zip code." ValidationError: [u'Please enter a valid zip code.'] >>> >>> form.base_fields['zip_code'].clean(value='') Traceback (most recent call last): File "", line 1, in ? File "/Users/leifstrickland/Sites/DjangoProject/mysite2/../mysite2/ admin.py", line 40, in clean raise ValidationError, "Please enter a valid zip code." ValidationError: [u'Please enter a valid zip code.'] >>> >>> zip_code_field = form.base_fields['zip_code'] >>> zip_code_field.widget.render(name='zip_code',value=1) u'' >>> >>> zip_code_field.widget.render(name='zip_code',value='') u'' As you can see, everything seems to be working. I'm so puzzled... --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---
Re: Zip code lookup field
Yes, the ModelAdmin is registered with django.contrib.admin.site. And the change and add pages for the model are displaying correctly. It even provides the expected error message if I enter an invalid Zip code. But when I enter a correct Zip code and Save, it gives me an Integrity Error: --- IntegrityError at /admin/profile/profile/2/ null value in column "zip_code_id" violates not-null constraint TRACEBACK /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/core/handlers/base.py in get_response response = callback(request, *callback_args, **callback_kwargs) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/contrib/admin/sites.py in root return self.model_page(request, *url.split('/', 2)) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/contrib/admin/sites.py in model_page return admin_obj(request, rest_of_url) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/contrib/admin/options.py in __call__ return self.change_view(request, unquote(url)) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/contrib/admin/options.py in change_view return self.save_change(request, model, form, inline_formsets) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/contrib/admin/options.py in save_change new_object = form.save(commit=True) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/newforms/models.py in save return save_instance(self, instance, fields, fail_message, commit) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/newforms/models.py in save_instance instance.save() ... /Sites/Django/mysite2/../mysite2/profile/models.py in save super(Profile, self).save() ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/db/models/base.py in save db_values + [pk_val]) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/db/backends/util.py in execute return self.cursor.execute(sql, params) ... --- In the last step, the local db_values var is a tuple of values to be used in the DB query. All values are correct except for the zip_code_id, which is None. That shouldn't be the case, because the zip code field's clean() function has worked properly (i.e., returned the corresponding zip_code_id) in shell and admin testing. So somehow the value returned by the clean() function is being overwritten or ignored later in the script. I just can't figure it out. Thanks again for all the help. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---
Re: Zip code lookup field
Yes, the ModelAdmin is registered with django.contrib.admin.site. And the change and add pages for the model are displaying correctly. It even provides the expected error message if I enter an invalid Zip code. But when I enter a correct Zip code and Save, it gives me an Integrity Error: --- IntegrityError at /admin/profile/profile/2/ null value in column "zip_code_id" violates not-null constraint TRACEBACK /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/core/handlers/base.py in get_response response = callback(request, *callback_args, **callback_kwargs) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/contrib/admin/sites.py in root return self.model_page(request, *url.split('/', 2)) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/contrib/admin/sites.py in model_page return admin_obj(request, rest_of_url) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/contrib/admin/options.py in __call__ return self.change_view(request, unquote(url)) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/contrib/admin/options.py in change_view return self.save_change(request, model, form, inline_formsets) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/contrib/admin/options.py in save_change new_object = form.save(commit=True) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/newforms/models.py in save return save_instance(self, instance, fields, fail_message, commit) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/newforms/models.py in save_instance instance.save() ... /Users/leifstrickland/Sites/DjangoProject/mysite2/../mysite2/profile/ models.py in save super(Profile, self).save() ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/db/models/base.py in save db_values + [pk_val]) ... /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site- packages/django/db/backends/util.py in execute return self.cursor.execute(sql, params) ... --- In the last step, the local db_values var is a tuple of values to be used in the DB query. All values are correct except for the zip_code_id, which is None. That shouldn't be the case, because the zip code field's clean() function has worked properly (i.e., returned the corresponding zip_code_id) in shell and admin testing. So somehow the value returned by the clean() function is being overwritten or ignored later in the script. I just can't figure it out. Thanks again for all the help. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---
Re: Zip code lookup field
On 6/27/07, leif strickland <[EMAIL PROTECTED]> wrote: ... > zip_code_id = > Postal_Code.objects.get(postal_code=value).id Is Postal_Code.postal_code a string or numeric? ... > try: > zip_code = Postal_Code.objects.get(id = > value).postal_code > except: > zip_code = value Again, you may want to str() .postal_code if it's numeric. Are you registering your custom ModelAdmin with django.contrib.admin.site? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---
Re: Zip code lookup field
OK, I've been tinkering with this all day, and I'm still having one big problem As Jeremy suggested, I created custom ZipCodeField and MyAdmin classes. In addition, I created a custom ZipcodeLookupInput widget. I've tested this in the shell and on the test server, and the clean and render functions appear to be working beautifully. The widget's render() function looks up the initial value (the zip code id) and uses the corresponding zip code as its display value, and the field's clean() function converts the user-provided zip into an id and returns it as an integer value. Unfortunately, I keep getting an error when I try to save. It appears that the zip_code_id is None by the time a DB query is attempted in django.db.backends.util. But this makes no sense, beacuse the clean() function seems to be working properly (i.e., it returns an integer value). Does anyone know what might be happening? I have pasted my custom classes code below. from mysite.address.models import Postal_Code from django import newforms as forms [...] class ProfileOptions(admin.ModelAdmin): def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name == 'zip_code': return ZipCodeField(**kwargs) else: return super(ProfileOptions,self).formfield_for_dbfield(db_field, **kwargs) class ZipCodeField(forms.fields.CharField): def __init__(self, **kwargs): kwargs['widget'] = ZCLookupTextInput self.max_length, self.min_length = 5, 5 super(ZipCodeField, self).__init__(**kwargs) def clean(self, value): super(ZipCodeField, self).clean(value) try: zip_code_id = Postal_Code.objects.get(postal_code=value).id except Postal_Code.DoesNotExist: raise ValidationError, "Please enter a valid zip code." return int(zip_code_id) class ZCLookupTextInput(forms.widgets.TextInput): def render(self, name, value, attrs=None): try: zip_code = Postal_Code.objects.get(id = value).postal_code except: zip_code = value return super(ZCLookupTextInput, self).render(name, zip_code, attrs) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---
Re: Zip code lookup field
OK, I've been tinkering with this all day, and I'm still having one big problem As Jeremy suggested, I created custom ZipCodeField and MyAdmin classes. In addition, I created a custom ZipcodeLookupInput widget. I've tested this in the shell and on the test server, and the clean and render functions appear to be working beautifully. The widget's render() function looks up the initial value (the zip code id) and uses the corresponding zip code as its display value, and the field's clean() function converts the user-provided zip into an id and returns it as an integer value. Unfortunately, I keep getting an error when I try to save. It appears that the zip_code_id is None by the time a DB query is attempted in django.db.backends.util. But this makes no sense, beacuse the clean() function seems to be working properly (i.e., it returns an integer value). Does anyone know what might be happening? I have pasted my custom classes code below. from mysite.address.models import Postal_Code from django import newforms as forms [...] class ProfileOptions(admin.ModelAdmin): def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name == 'zip_code': return ZipCodeField(**kwargs) else: return super(ProfileOptions,self).formfield_for_dbfield(db_field, **kwargs) class ZipCodeField(forms.fields.CharField): def __init__(self, **kwargs): kwargs['widget'] = ZCLookupTextInput self.max_length, self.min_length = 5, 1 super(ZipCodeField, self).__init__(**kwargs) def clean(self, value): super(ZipCodeField, self).clean(value) try: zip_code_id = Postal_Code.objects.get(postal_code=value).id except Postal_Code.DoesNotExist: raise ValidationError, "Please enter a valid zip code." return int(zip_code_id) class ZCLookupTextInput(forms.widgets.TextInput): def render(self, name, value, attrs=None): try: zip_code = Postal_Code.objects.get(id = value).postal_code except: zip_code = value return super(LookupTextInput, self).render(name, zip_code, attrs) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---
Re: Zip code lookup field
Great advice -- thanks! I'll work on it today and let you know how it comes together. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---
Re: Zip code lookup field
On 6/27/07, leif <[EMAIL PROTECTED]> wrote: ... > Thanks for the input, Jeremy. I've actually decided to use newforms- > admin since I won't be going to production for another few months Sorry for missing that the first time. :) Admin uses django.newforms.models.form_for_model, which takes an optional formfield_callback in order to map between DB fields and form fields. In order to supply that parameter, it looks like you'll need to inherit from django.contrib.admin.options.ModelAdmin and override formfield_for_dbfield. That method maps between database fields and form fields. Have formfield_for_dbfield return your custom field class (a subclass of django.newforms.fields.Field; CharField might make sense), then override the Field.clean method to do your FK lookup and raise a ValidationError if it's not a valid zip code. NB: I haven't used newforms much myself yet. Please report back if you run into any troubles. :) You'll end up with something like this: class MyAdmin(ModelAdmin): def formfield_for_dbfield(self, db_field, **kwargs): if isinstance(db_field, models.ForeignKey) and db_field.name == 'zip_code': return ZipCodeField(**kwargs) else: super(MyAdmin, self).formfield_for_dbfield(db_field, **kwargs) --- class ZipCodeField(CharField): def __init__(self, *args, **kwargs): self.max_length, self.min_length = 5, 5 super(ZipCodeField, self).__init__(*args, **kwargs) def clean(self, value): value = super(ZipCodeField, self).clean(self, value) from yourmodels import ZipCode try: ZipCode.objects.get(pk=value) except ZipCode.DoesNotExist: raise ValidationError, "Please enter a valid zip code" return value --- from django.contrib.admin import site site.register(YourModel, YourAdminClass) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---
Re: Zip code lookup field
> Django's existing admin uses oldforms. The newforms-admin branch is > working to rewrite admin to be more flexible and use newforms. If you > need it on trunk now, you'll need to use oldforms. Thanks for the input, Jeremy. I've actually decided to use newforms- admin since I won't be going to production for another few months (and hopefully it will be incorporated into the trunk soon). Do you know how I can attack the problem using that branch? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---
Re: Zip code lookup field
On 6/26/07, leif <[EMAIL PROTECTED]> wrote: > My main problem, though, is figuring out how to create a text input > lookup field for the ZIP code foreign key. > Do I need to code a new > widget? A new form field class? A function to hook into newforms' > validation? > And if I create a widget or form field class, how to I coax Django > into using it for the admin change and add pages? Django's existing admin uses oldforms. The newforms-admin branch is working to rewrite admin to be more flexible and use newforms. If you need it on trunk now, you'll need to use oldforms. You'll need to inherit from django.db.models.fields.Field and override Field.get_manipulator_field_objs. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---
Re: Zip code lookup field
Very good point, Tim. I'll consider that issue as I move forward with my application. My main problem, though, is figuring out how to create a text input lookup field for the ZIP code foreign key. Do I need to code a new widget? A new form field class? A function to hook into newforms' validation? And if I create a widget or form field class, how to I coax Django into using it for the admin change and add pages? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---
Re: Zip code lookup field
> My question, then, is this: What's the most elegant way to > pull off this hack? By the way, I am using newforms and the > newforms-admin branch. (I want my customizations to work with > 1.0 and beyond.) Generally, zip-codes and cities have a one-to-one correspondence. However, this isn't 100% the case. You could offer a zip-entry and then, if ambiguity arose, allow the user to choose the intended town to clarify, much like other error/validation processes where you'd repopulate the screen with the existing data but flag the ambiguity as an error condition. It would also be helpful to given the user a preview anyways in case they mis-typed their zip-code. -tim --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---